forked from github/server
Merge branch 'muttmail'
This commit is contained in:
commit
6a6089b48c
|
@ -9,7 +9,7 @@ end_of_line = lf
|
|||
insert_final_newline = true
|
||||
|
||||
# 4 space indentation
|
||||
[*.{c,h,lua}]
|
||||
[*.{c,h,lua,py}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
install(PROGRAMS create-orders backup-eressea run-turn send-zip-report
|
||||
send-bz2-report compress.py compress.sh epasswd.py orders-process
|
||||
process-orders.py accept-orders.py
|
||||
checkpasswd.py sendreport.sh sendreports.sh orders-accept DESTINATION bin)
|
||||
|
||||
install(DIRECTORY cron/ DESTINATION bin USE_SOURCE_PERMISSIONS
|
||||
|
|
|
@ -0,0 +1,377 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from email.Utils import parseaddr
|
||||
from email.Parser import Parser
|
||||
import os
|
||||
import os.path
|
||||
import ConfigParser
|
||||
from re import compile, IGNORECASE
|
||||
from stat import ST_MTIME
|
||||
from string import upper, split, replace
|
||||
import logging
|
||||
import sys
|
||||
import subprocess
|
||||
from sys import stdin
|
||||
from time import ctime, sleep, time
|
||||
from socket import gethostname
|
||||
from rfc822 import parsedate_tz, mktime_tz
|
||||
|
||||
if 'ERESSEA' in os.environ:
|
||||
dir = os.environ['ERESSEA']
|
||||
elif 'HOME' in os.environ:
|
||||
dir = os.path.join(os.environ['HOME'], 'eressea')
|
||||
else: # WTF? No HOME?
|
||||
dir = "/home/eressea/eressea"
|
||||
if not os.path.isdir(dir):
|
||||
print "please set the ERESSEA environment variable to the install path"
|
||||
sys.exit(1)
|
||||
rootdir = dir
|
||||
|
||||
game = int(sys.argv[1])
|
||||
gamedir = os.path.join(rootdir, "game-%d" % (game, ))
|
||||
frommail = 'eressea-server@kn-bremen.de'
|
||||
gamename = 'Eressea'
|
||||
sender = '%s Server <%s>' % (gamename, frommail)
|
||||
|
||||
inifile = os.path.join(gamedir, 'eressea.ini')
|
||||
if not os.path.exists(inifile):
|
||||
print "no such file: " . inifile
|
||||
else:
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.read(inifile)
|
||||
if config.has_option('game', 'email'):
|
||||
frommail = config.get('game', 'email')
|
||||
if config.has_option('game', 'name'):
|
||||
gamename = config.get('game', 'name')
|
||||
if config.has_option('game', 'sender'):
|
||||
sender = config.get('game', 'sender')
|
||||
else:
|
||||
sender = "%s Server <%s>" % (gamename, frommail)
|
||||
config = None
|
||||
prefix = 'turn-'
|
||||
hostname = gethostname()
|
||||
orderbase = "orders.dir"
|
||||
sendmail = True
|
||||
# maximum number of reports per sender:
|
||||
maxfiles = 20
|
||||
# write headers to file?
|
||||
writeheaders = True
|
||||
# reject all html email?
|
||||
rejecthtml = True
|
||||
|
||||
def unlock_file(filename):
|
||||
try:
|
||||
os.unlink(filename+".lock")
|
||||
except:
|
||||
print "could not unlock %s.lock, file not found" % filename
|
||||
|
||||
def lock_file(filename):
|
||||
i = 0
|
||||
wait = 1
|
||||
if not os.path.exists(filename):
|
||||
file=open(filename, "w")
|
||||
file.close()
|
||||
while True:
|
||||
try:
|
||||
os.symlink(filename, filename+".lock")
|
||||
return
|
||||
except:
|
||||
i = i+1
|
||||
if i == 5: unlock_file(filename)
|
||||
sleep(wait)
|
||||
wait = wait*2
|
||||
|
||||
messages = {
|
||||
"multipart-en" :
|
||||
"ERROR: The orders you sent contain no plaintext. " \
|
||||
"The Eressea server cannot process orders containing HTML " \
|
||||
"or invalid attachments, which are the reasons why this " \
|
||||
"usually happens. Please change the settings of your mail " \
|
||||
"software and re-send the orders.",
|
||||
|
||||
"multipart-de" :
|
||||
"FEHLER: Die von dir eingeschickte Mail enthält keinen " \
|
||||
"Text. Evtl. hast Du den Zug als HTML oder als anderweitig " \
|
||||
"ungültig formatierte Mail ingeschickt. Wir können ihn " \
|
||||
"deshalb nicht berücksichtigen. Schicke den Zug nochmals " \
|
||||
"als reinen Text ohne Formatierungen ein.",
|
||||
|
||||
"maildate-de":
|
||||
"Es erreichte uns bereits ein Zug mit einem späteren " \
|
||||
"Absendedatum (%s > %s). Entweder ist deine " \
|
||||
"Systemzeit verstellt, oder ein Zug hat einen anderen Zug von " \
|
||||
"dir auf dem Transportweg überholt. Entscheidend für die " \
|
||||
"Auswertungsreihenfolge ist das Absendedatum, d.h. der Date:-Header " \
|
||||
"deiner Mail.",
|
||||
|
||||
"maildate-en":
|
||||
"The server already received an order file that was sent at a later " \
|
||||
"date (%s > %s). Either your system clock is wrong, or two messages have " \
|
||||
"overtaken each other on the way to the server. The order of " \
|
||||
"execution on the server is always according to the Date: header in " \
|
||||
"your mail.",
|
||||
|
||||
"nodate-en":
|
||||
"Your message did not contain a valid Date: header in accordance with RFC2822.",
|
||||
|
||||
"nodate-de":
|
||||
"Deine Nachricht enthielt keinen gueltigen Date: header nach RFC2822.",
|
||||
|
||||
"error-de":
|
||||
"Fehler",
|
||||
|
||||
"error-en":
|
||||
"Error",
|
||||
|
||||
"warning-de":
|
||||
"Warnung",
|
||||
|
||||
"warning-en":
|
||||
"Warning",
|
||||
|
||||
"subject-de":
|
||||
"Befehle angekommen",
|
||||
|
||||
"subject-en":
|
||||
"orders received"
|
||||
}
|
||||
|
||||
# return 1 if addr is a valid email address
|
||||
def valid_email(addr):
|
||||
rfc822_specials = '/()<>@,;:\\"[]'
|
||||
# First we validate the name portion (name@domain)
|
||||
c = 0
|
||||
while c < len(addr):
|
||||
if addr[c] == '"' and (not c or addr[c - 1] == '.' or addr[c - 1] == '"'):
|
||||
c = c + 1
|
||||
while c < len(addr):
|
||||
if addr[c] == '"': break
|
||||
if addr[c] == '\\' and addr[c + 1] == ' ':
|
||||
c = c + 2
|
||||
continue
|
||||
if ord(addr[c]) < 32 or ord(addr[c]) >= 127: return 0
|
||||
c = c + 1
|
||||
else: return 0
|
||||
if addr[c] == '@': break
|
||||
if addr[c] != '.': return 0
|
||||
c = c + 1
|
||||
continue
|
||||
if addr[c] == '@': break
|
||||
if ord(addr[c]) <= 32 or ord(addr[c]) >= 127: return 0
|
||||
if addr[c] in rfc822_specials: return 0
|
||||
c = c + 1
|
||||
if not c or addr[c - 1] == '.': return 0
|
||||
|
||||
# Next we validate the domain portion (name@domain)
|
||||
domain = c = c + 1
|
||||
if domain >= len(addr): return 0
|
||||
count = 0
|
||||
while c < len(addr):
|
||||
if addr[c] == '.':
|
||||
if c == domain or addr[c - 1] == '.': return 0
|
||||
count = count + 1
|
||||
if ord(addr[c]) <= 32 or ord(addr[c]) >= 127: return 0
|
||||
if addr[c] in rfc822_specials: return 0
|
||||
c = c + 1
|
||||
return count >= 1
|
||||
|
||||
# return the replyto or from address in the header
|
||||
def get_sender(header):
|
||||
replyto = header.get("Reply-To")
|
||||
if replyto is None:
|
||||
replyto = header.get("From")
|
||||
if replyto is None: return None
|
||||
x = parseaddr(replyto)
|
||||
return x[1]
|
||||
|
||||
# return first available filename basename,[0-9]+
|
||||
def available_file(dirname, basename):
|
||||
ver = 0
|
||||
maxdate = 0
|
||||
filename = "%s/%s,%s,%d" % (dirname, basename, hostname, ver)
|
||||
while os.path.exists(filename):
|
||||
maxdate = max(os.stat(filename)[ST_MTIME], maxdate)
|
||||
ver = ver + 1
|
||||
filename = "%s/%s,%s,%d" % (dirname, basename, hostname, ver)
|
||||
if ver >= maxfiles:
|
||||
return None, None
|
||||
return maxdate, filename
|
||||
|
||||
def formatpar(string, l=76, indent=2):
|
||||
words = split(string)
|
||||
res = ""
|
||||
ll = 0
|
||||
first = 1
|
||||
|
||||
for word in words:
|
||||
if first == 1:
|
||||
res = word
|
||||
first = 0
|
||||
ll = len(word)
|
||||
else:
|
||||
if ll + len(word) > l:
|
||||
res = res + "\n"+" "*indent+word
|
||||
ll = len(word) + indent
|
||||
else:
|
||||
res = res+" "+word
|
||||
ll = ll + len(word) + 1
|
||||
|
||||
return res+"\n"
|
||||
|
||||
def store_message(message, filename):
|
||||
outfile = open(filename, "w")
|
||||
outfile.write(message.as_string())
|
||||
outfile.close()
|
||||
return
|
||||
|
||||
def write_part(outfile, part):
|
||||
charset = part.get_content_charset()
|
||||
payload = part.get_payload(decode=True)
|
||||
|
||||
if charset is None:
|
||||
charset = "latin1"
|
||||
try:
|
||||
msg = payload.decode(charset, "ignore")
|
||||
except:
|
||||
msg = payload
|
||||
charset = None
|
||||
try:
|
||||
utf8 = msg.encode("utf-8", "ignore")
|
||||
outfile.write(utf8)
|
||||
except:
|
||||
outfile.write(msg)
|
||||
return False
|
||||
outfile.write("\n");
|
||||
return True
|
||||
|
||||
def copy_orders(message, filename, sender):
|
||||
# print the header first
|
||||
if writeheaders:
|
||||
from os.path import split
|
||||
dirname, basename = split(filename)
|
||||
dirname = dirname + '/headers'
|
||||
if not os.path.exists(dirname): os.mkdir(dirname)
|
||||
outfile = open(dirname + '/' + basename, "w")
|
||||
for name, value in message.items():
|
||||
outfile.write(name + ": " + value + "\n")
|
||||
outfile.close()
|
||||
|
||||
found = False
|
||||
outfile = open(filename, "w")
|
||||
if message.is_multipart():
|
||||
for part in message.get_payload():
|
||||
content_type = part.get_content_type()
|
||||
logger.debug("found content type %s for %s" % (content_type, sender))
|
||||
if content_type=="text/plain":
|
||||
if write_part(outfile, part):
|
||||
found = True
|
||||
else:
|
||||
charset = part.get_content_charset()
|
||||
logger.error("could not write text/plain part (charset=%s) for %s" % (charset, sender))
|
||||
|
||||
else:
|
||||
if write_part(outfile, message):
|
||||
found = True
|
||||
else:
|
||||
charset = message.get_content_charset()
|
||||
logger.error("could not write text/plain message (charset=%s) for %s" % (charset, sender))
|
||||
outfile.close()
|
||||
return found
|
||||
|
||||
# create a file, containing:
|
||||
# game=0 locale=de file=/path/to/filename email=rcpt@domain.to
|
||||
def accept(game, locale, stream, extend=None):
|
||||
global rootdir, orderbase, gamedir, gamename, sender
|
||||
if extend is not None:
|
||||
orderbase = orderbase + ".pre-" + extend
|
||||
savedir = os.path.join(gamedir, orderbase)
|
||||
# check if it's one of the pre-sent orders.
|
||||
# create the save-directories if they don't exist
|
||||
if not os.path.exists(gamedir): os.mkdir(gamedir)
|
||||
if not os.path.exists(savedir): os.mkdir(savedir)
|
||||
# parse message
|
||||
message = Parser().parse(stream)
|
||||
email = get_sender(message)
|
||||
logger = logging.getLogger(email)
|
||||
# write syslog
|
||||
if email is None or valid_email(email)==0:
|
||||
logger.warning("invalid email address: " + str(email))
|
||||
return -1
|
||||
logger.info("received orders from " + email)
|
||||
# get an available filename
|
||||
lock_file(gamedir + "/orders.queue")
|
||||
maxdate, filename = available_file(savedir, prefix + email)
|
||||
if filename is None:
|
||||
logger.warning("more than " + str(maxfiles) + " orders from " + email)
|
||||
return -1
|
||||
# copy the orders to the file
|
||||
text_ok = copy_orders(message, filename, email)
|
||||
unlock_file(gamedir + "/orders.queue")
|
||||
|
||||
warning, msg, fail = None, "", False
|
||||
maildate = message.get("Date")
|
||||
if maildate != None:
|
||||
turndate = mktime_tz(parsedate_tz(maildate))
|
||||
os.utime(filename, (turndate, turndate))
|
||||
logger.debug("mail date is '%s' (%d)" % (maildate, turndate))
|
||||
if False and turndate < maxdate:
|
||||
logger.warning("inconsistent message date " + email)
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["maildate-" + locale] % (ctime(maxdate),ctime(turndate)), 76, 2) + "\n"
|
||||
else:
|
||||
logger.warning("missing message date " + email)
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["nodate-" + locale], 76, 2) + "\n"
|
||||
|
||||
if not text_ok:
|
||||
warning = " (" + messages["error-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["multipart-" + locale], 76, 2) + "\n"
|
||||
logger.warning("rejected - no text/plain in orders from " + email)
|
||||
os.unlink(filename)
|
||||
savedir = savedir + "/rejected"
|
||||
if not os.path.exists(savedir): os.mkdir(savedir)
|
||||
lock_file(gamedir + "/orders.queue")
|
||||
maxdate, filename = available_file(savedir, prefix + email)
|
||||
store_message(message, filename)
|
||||
unlock_file(gamedir + "/orders.queue")
|
||||
fail = True
|
||||
|
||||
if sendmail and warning is not None:
|
||||
subject = gamename + " " + messages["subject-"+locale] + warning
|
||||
print("mail " + subject)
|
||||
ps = subprocess.Popen(['mutt', '-s', subject, email], stdin=subprocess.PIPE)
|
||||
ps.communicate(msg)
|
||||
|
||||
if not sendmail:
|
||||
print text_ok, fail, email
|
||||
print filename
|
||||
|
||||
if not fail:
|
||||
lock_file(gamedir + "/orders.queue")
|
||||
queue = open(gamedir + "/orders.queue", "a")
|
||||
queue.write("email=%s file=%s locale=%s game=%s\n" % (email, filename, locale, game))
|
||||
queue.close()
|
||||
unlock_file(gamedir + "/orders.queue")
|
||||
|
||||
logger.info("done - accepted orders from " + email)
|
||||
|
||||
return 0
|
||||
|
||||
# the main body of the script:
|
||||
try:
|
||||
os.mkdir(os.path.join(rootdir, 'log'))
|
||||
except:
|
||||
pass # already exists?
|
||||
LOG_FILENAME=os.path.join(rootdir, 'log/orders.log')
|
||||
logging.basicConfig(level=logging.DEBUG, filename=LOG_FILENAME)
|
||||
logger = logging
|
||||
delay = None # TODO: parse the turn delay
|
||||
locale = sys.argv[2]
|
||||
infile = stdin
|
||||
if len(sys.argv)>3:
|
||||
infile = open(sys.argv[3], "r")
|
||||
retval = accept(game, locale, infile, delay)
|
||||
if infile!=stdin:
|
||||
infile.close()
|
||||
sys.exit(retval)
|
|
@ -1,378 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
#!/bin/sh
|
||||
python accept-orders.py "$@"
|
||||
|
||||
from email.Utils import parseaddr
|
||||
from email.Parser import Parser
|
||||
import os
|
||||
import os.path
|
||||
import ConfigParser
|
||||
from re import compile, IGNORECASE
|
||||
from stat import ST_MTIME
|
||||
from string import upper, split, replace
|
||||
import logging
|
||||
import sys
|
||||
from sys import stdin
|
||||
from time import ctime, sleep, time
|
||||
from socket import gethostname
|
||||
from rfc822 import parsedate_tz, mktime_tz
|
||||
|
||||
if 'ERESSEA' in os.environ:
|
||||
dir = os.environ['ERESSEA']
|
||||
elif 'HOME' in os.environ:
|
||||
dir = os.path.join(os.environ['HOME'], '/eressea')
|
||||
else: # WTF? No HOME?
|
||||
dir = "/home/eressea/eressea"
|
||||
if not os.path.isdir(dir):
|
||||
print "please set the ERESSEA environment variable to the install path"
|
||||
sys.exit(1)
|
||||
rootdir = dir
|
||||
|
||||
game = int(sys.argv[1])
|
||||
gamedir = os.path.join(rootdir, "game-%d" % (game, ))
|
||||
frommail = 'eressea-server@kn-bremen.de'
|
||||
gamename = 'Eressea'
|
||||
sender = '%s Server <%s>' % (gamename, frommail)
|
||||
|
||||
inifile = os.path.join(gamedir, 'eressea.ini')
|
||||
if not os.path.exists(inifile):
|
||||
print "no such file: " . inifile
|
||||
else:
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.read(inifile)
|
||||
if config.has_option('game', 'email'):
|
||||
frommail = config.get('game', 'email')
|
||||
if config.has_option('game', 'name'):
|
||||
gamename = config.get('game', 'name')
|
||||
if config.has_option('game', 'sender'):
|
||||
sender = config.get('game', 'sender')
|
||||
else:
|
||||
sender = "%s Server <%s>" % (gamename, frommail)
|
||||
config = None
|
||||
prefix = 'turn-'
|
||||
hostname = gethostname()
|
||||
orderbase = "orders.dir"
|
||||
sendmail = True
|
||||
# maximum number of reports per sender:
|
||||
maxfiles = 20
|
||||
# write headers to file?
|
||||
writeheaders = True
|
||||
# reject all html email?
|
||||
rejecthtml = True
|
||||
|
||||
def unlock_file(filename):
|
||||
try:
|
||||
os.unlink(filename+".lock")
|
||||
except:
|
||||
print "could not unlock %s.lock, file not found" % filename
|
||||
|
||||
def lock_file(filename):
|
||||
i = 0
|
||||
wait = 1
|
||||
if not os.path.exists(filename):
|
||||
file=open(filename, "w")
|
||||
file.close()
|
||||
while True:
|
||||
try:
|
||||
os.symlink(filename, filename+".lock")
|
||||
return
|
||||
except:
|
||||
i = i+1
|
||||
if i == 5: unlock_file(filename)
|
||||
sleep(wait)
|
||||
wait = wait*2
|
||||
|
||||
messages = {
|
||||
"multipart-en" :
|
||||
"ERROR: The orders you sent contain no plaintext. " \
|
||||
"The Eressea server cannot process orders containing HTML " \
|
||||
"or invalid attachments, which are the reasons why this " \
|
||||
"usually happens. Please change the settings of your mail " \
|
||||
"software and re-send the orders.",
|
||||
|
||||
"multipart-de" :
|
||||
"FEHLER: Die von dir eingeschickte Mail enth<74>lt keinen " \
|
||||
"Text. Evtl. hast Du den Zug als HTML oder als anderweitig " \
|
||||
"ung<6E>ltig formatierte Mail ingeschickt. Wir k<>nnen ihn " \
|
||||
"deshalb nicht ber<65>cksichtigen. Schicke den Zug nochmals " \
|
||||
"als reinen Text ohne Formatierungen ein.",
|
||||
|
||||
"maildate-de":
|
||||
"Es erreichte uns bereits ein Zug mit einem sp<73>teren " \
|
||||
"Absendedatum (%s > %s). Entweder ist deine " \
|
||||
"Systemzeit verstellt, oder ein Zug hat einen anderen Zug von " \
|
||||
"dir auf dem Transportweg <20>berholt. Entscheidend f<>r die " \
|
||||
"Auswertungsreihenfolge ist das Absendedatum, d.h. der Date:-Header " \
|
||||
"deiner Mail.",
|
||||
|
||||
"maildate-en":
|
||||
"The server already received an order file that was sent at a later " \
|
||||
"date (%s > %s). Either your system clock is wrong, or two messages have " \
|
||||
"overtaken each other on the way to the server. The order of " \
|
||||
"execution on the server is always according to the Date: header in " \
|
||||
"your mail.",
|
||||
|
||||
"nodate-en":
|
||||
"Your message did not contain a valid Date: header in accordance with RFC2822.",
|
||||
|
||||
"nodate-de":
|
||||
"Deine Nachricht enthielt keinen gueltigen Date: header nach RFC2822.",
|
||||
|
||||
"error-de":
|
||||
"Fehler",
|
||||
|
||||
"error-en":
|
||||
"Error",
|
||||
|
||||
"warning-de":
|
||||
"Warnung",
|
||||
|
||||
"warning-en":
|
||||
"Warning",
|
||||
|
||||
"subject-de":
|
||||
"Befehle angekommen",
|
||||
|
||||
"subject-en":
|
||||
"orders received"
|
||||
}
|
||||
|
||||
# return 1 if addr is a valid email address
|
||||
def valid_email(addr):
|
||||
rfc822_specials = '/()<>@,;:\\"[]'
|
||||
# First we validate the name portion (name@domain)
|
||||
c = 0
|
||||
while c < len(addr):
|
||||
if addr[c] == '"' and (not c or addr[c - 1] == '.' or addr[c - 1] == '"'):
|
||||
c = c + 1
|
||||
while c < len(addr):
|
||||
if addr[c] == '"': break
|
||||
if addr[c] == '\\' and addr[c + 1] == ' ':
|
||||
c = c + 2
|
||||
continue
|
||||
if ord(addr[c]) < 32 or ord(addr[c]) >= 127: return 0
|
||||
c = c + 1
|
||||
else: return 0
|
||||
if addr[c] == '@': break
|
||||
if addr[c] != '.': return 0
|
||||
c = c + 1
|
||||
continue
|
||||
if addr[c] == '@': break
|
||||
if ord(addr[c]) <= 32 or ord(addr[c]) >= 127: return 0
|
||||
if addr[c] in rfc822_specials: return 0
|
||||
c = c + 1
|
||||
if not c or addr[c - 1] == '.': return 0
|
||||
|
||||
# Next we validate the domain portion (name@domain)
|
||||
domain = c = c + 1
|
||||
if domain >= len(addr): return 0
|
||||
count = 0
|
||||
while c < len(addr):
|
||||
if addr[c] == '.':
|
||||
if c == domain or addr[c - 1] == '.': return 0
|
||||
count = count + 1
|
||||
if ord(addr[c]) <= 32 or ord(addr[c]) >= 127: return 0
|
||||
if addr[c] in rfc822_specials: return 0
|
||||
c = c + 1
|
||||
return count >= 1
|
||||
|
||||
# return the replyto or from address in the header
|
||||
def get_sender(header):
|
||||
replyto = header.get("Reply-To")
|
||||
if replyto is None:
|
||||
replyto = header.get("From")
|
||||
if replyto is None: return None
|
||||
x = parseaddr(replyto)
|
||||
return x[1]
|
||||
|
||||
# return first available filename basename,[0-9]+
|
||||
def available_file(dirname, basename):
|
||||
ver = 0
|
||||
maxdate = 0
|
||||
filename = "%s/%s,%s,%d" % (dirname, basename, hostname, ver)
|
||||
while os.path.exists(filename):
|
||||
maxdate = max(os.stat(filename)[ST_MTIME], maxdate)
|
||||
ver = ver + 1
|
||||
filename = "%s/%s,%s,%d" % (dirname, basename, hostname, ver)
|
||||
if ver >= maxfiles:
|
||||
return None, None
|
||||
return maxdate, filename
|
||||
|
||||
def formatpar(string, l=76, indent=2):
|
||||
words = split(string)
|
||||
res = ""
|
||||
ll = 0
|
||||
first = 1
|
||||
|
||||
for word in words:
|
||||
if first == 1:
|
||||
res = word
|
||||
first = 0
|
||||
ll = len(word)
|
||||
else:
|
||||
if ll + len(word) > l:
|
||||
res = res + "\n"+" "*indent+word
|
||||
ll = len(word) + indent
|
||||
else:
|
||||
res = res+" "+word
|
||||
ll = ll + len(word) + 1
|
||||
|
||||
return res+"\n"
|
||||
|
||||
def store_message(message, filename):
|
||||
outfile = open(filename, "w")
|
||||
outfile.write(message.as_string())
|
||||
outfile.close()
|
||||
return
|
||||
|
||||
def write_part(outfile, part):
|
||||
charset = part.get_content_charset()
|
||||
payload = part.get_payload(decode=True)
|
||||
|
||||
if charset is None:
|
||||
charset = "latin1"
|
||||
try:
|
||||
msg = payload.decode(charset, "ignore")
|
||||
except:
|
||||
msg = payload
|
||||
charset = None
|
||||
try:
|
||||
utf8 = msg.encode("utf-8", "ignore")
|
||||
outfile.write(utf8)
|
||||
except:
|
||||
outfile.write(msg)
|
||||
return False
|
||||
outfile.write("\n");
|
||||
return True
|
||||
|
||||
def copy_orders(message, filename, sender):
|
||||
# print the header first
|
||||
if writeheaders:
|
||||
from os.path import split
|
||||
dirname, basename = split(filename)
|
||||
dirname = dirname + '/headers'
|
||||
if not os.path.exists(dirname): os.mkdir(dirname)
|
||||
outfile = open(dirname + '/' + basename, "w")
|
||||
for name, value in message.items():
|
||||
outfile.write(name + ": " + value + "\n")
|
||||
outfile.close()
|
||||
|
||||
found = False
|
||||
outfile = open(filename, "w")
|
||||
if message.is_multipart():
|
||||
for part in message.get_payload():
|
||||
content_type = part.get_content_type()
|
||||
logger.debug("found content type %s for %s" % (content_type, sender))
|
||||
if content_type=="text/plain":
|
||||
if write_part(outfile, part):
|
||||
found = True
|
||||
else:
|
||||
charset = part.get_content_charset()
|
||||
logger.error("could not write text/plain part (charset=%s) for %s" % (charset, sender))
|
||||
|
||||
else:
|
||||
if write_part(outfile, message):
|
||||
found = True
|
||||
else:
|
||||
charset = message.get_content_charset()
|
||||
logger.error("could not write text/plain message (charset=%s) for %s" % (charset, sender))
|
||||
outfile.close()
|
||||
return found
|
||||
|
||||
# create a file, containing:
|
||||
# game=0 locale=de file=/path/to/filename email=rcpt@domain.to
|
||||
def accept(game, locale, stream, extend=None):
|
||||
global rootdir, orderbase, gamedir, gamename, sender
|
||||
if extend is not None:
|
||||
orderbase = orderbase + ".pre-" + extend
|
||||
savedir = os.path.join(gamedir, orderbase)
|
||||
# check if it's one of the pre-sent orders.
|
||||
# create the save-directories if they don't exist
|
||||
if not os.path.exists(gamedir): os.mkdir(gamedir)
|
||||
if not os.path.exists(savedir): os.mkdir(savedir)
|
||||
# parse message
|
||||
message = Parser().parse(stream)
|
||||
email = get_sender(message)
|
||||
logger = logging.getLogger(email)
|
||||
# write syslog
|
||||
if email is None or valid_email(email)==0:
|
||||
logger.warning("invalid email address: " + str(email))
|
||||
return -1
|
||||
logger.info("received orders from " + email)
|
||||
# get an available filename
|
||||
lock_file(gamedir + "/orders.queue")
|
||||
maxdate, filename = available_file(savedir, prefix + email)
|
||||
if filename is None:
|
||||
logger.warning("more than " + str(maxfiles) + " orders from " + email)
|
||||
return -1
|
||||
# copy the orders to the file
|
||||
text_ok = copy_orders(message, filename, email)
|
||||
unlock_file(gamedir + "/orders.queue")
|
||||
|
||||
warning, msg, fail = None, "", False
|
||||
maildate = message.get("Date")
|
||||
if maildate != None:
|
||||
turndate = mktime_tz(parsedate_tz(maildate))
|
||||
os.utime(filename, (turndate, turndate))
|
||||
logger.debug("mail date is '%s' (%d)" % (maildate, turndate))
|
||||
if turndate < maxdate:
|
||||
logger.warning("inconsistent message date " + email)
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["maildate-" + locale] % (ctime(maxdate),ctime(turndate)), 76, 2) + "\n"
|
||||
else:
|
||||
logger.warning("missing message date " + email)
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["nodate-" + locale], 76, 2) + "\n"
|
||||
|
||||
if not text_ok:
|
||||
warning = " (" + messages["error-" + locale] + ")"
|
||||
msg = msg + formatpar(messages["multipart-" + locale], 76, 2) + "\n"
|
||||
logger.warning("rejected - no text/plain in orders from " + email)
|
||||
os.unlink(filename)
|
||||
savedir = savedir + "/rejected"
|
||||
if not os.path.exists(savedir): os.mkdir(savedir)
|
||||
lock_file(gamedir + "/orders.queue")
|
||||
maxdate, filename = available_file(savedir, prefix + email)
|
||||
store_message(message, filename)
|
||||
unlock_file(gamedir + "/orders.queue")
|
||||
fail = True
|
||||
|
||||
if sendmail and warning is not None:
|
||||
subject = gamename + " " + messages["subject-"+locale] + warning
|
||||
mail = "Subject: %s\nFrom: %s\nTo: %s\n\n" % (subject, sender, email) + msg
|
||||
from smtplib import SMTP
|
||||
server = SMTP("localhost")
|
||||
server.sendmail(sender, email, mail)
|
||||
server.close()
|
||||
|
||||
if not sendmail:
|
||||
print text_ok, fail, email
|
||||
print filename
|
||||
|
||||
if not fail:
|
||||
lock_file(gamedir + "/orders.queue")
|
||||
queue = open(gamedir + "/orders.queue", "a")
|
||||
queue.write("email=%s file=%s locale=%s game=%s\n" % (email, filename, locale, game))
|
||||
queue.close()
|
||||
unlock_file(gamedir + "/orders.queue")
|
||||
|
||||
logger.info("done - accepted orders from " + email)
|
||||
|
||||
return 0
|
||||
|
||||
# the main body of the script:
|
||||
try:
|
||||
os.mkdir(os.path.join(rootdir, 'log'))
|
||||
except:
|
||||
pass # already exists?
|
||||
LOG_FILENAME=os.path.join(rootdir, 'log/orders.log')
|
||||
logging.basicConfig(level=logging.DEBUG, filename=LOG_FILENAME)
|
||||
logger = logging
|
||||
delay=None # TODO: parse the turn delay
|
||||
locale = sys.argv[2]
|
||||
infile = stdin
|
||||
if len(sys.argv)>3:
|
||||
infile = open(sys.argv[3], "r")
|
||||
retval = accept(game, locale, infile, delay)
|
||||
if infile!=stdin:
|
||||
infile.close()
|
||||
sys.exit(retval)
|
||||
|
|
|
@ -1,242 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
#!/bin/sh
|
||||
python process-orders.py "$@"
|
||||
|
||||
from os import unlink, symlink, rename, popen, tmpfile
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import ConfigParser
|
||||
from re import compile, IGNORECASE
|
||||
from string import split, join, upper, strip
|
||||
from sys import argv, exit
|
||||
from time import sleep, time, ctime
|
||||
from syslog import openlog, closelog, syslog
|
||||
|
||||
from epasswd import EPasswd
|
||||
|
||||
def pwd_get_email(faction, pwd, pwdfile=None):
|
||||
return None
|
||||
|
||||
def split_filename(filename):
|
||||
return os.path.split(filename)
|
||||
|
||||
def unlock_file(filename):
|
||||
try:
|
||||
unlink(filename+".lock")
|
||||
except:
|
||||
print "could not unlock %s.lock, file not found" % filename
|
||||
raise
|
||||
|
||||
def lock_file(filename):
|
||||
i = 0
|
||||
wait = 1
|
||||
if not os.path.exists(filename):
|
||||
file=open(filename, "w")
|
||||
file.close()
|
||||
while True:
|
||||
try:
|
||||
symlink(filename, filename+".lock")
|
||||
return
|
||||
except:
|
||||
i = i+1
|
||||
if i == 5:
|
||||
raise
|
||||
sleep(wait)
|
||||
wait = wait*2
|
||||
|
||||
messages = {
|
||||
"subject-de": "Befehle angekommen",
|
||||
"subject-en": "orders received",
|
||||
|
||||
"validate-en": "Validating",
|
||||
"validate-de": "Verarbeite",
|
||||
|
||||
"faction-en": "Faction",
|
||||
"faction-de": "Partei",
|
||||
|
||||
"unknown-de": "WARNUNG: Die Partei ist nicht bekannt, oder das Passwort falsch!",
|
||||
"unknown-en": "WARNING: This faction is unknown, or the password is incorrect!",
|
||||
|
||||
"warning-de": "Warnung",
|
||||
"warning-en": "Warning",
|
||||
|
||||
"error-de": "Fehler",
|
||||
"error-en": "Error",
|
||||
}
|
||||
|
||||
game = int(sys.argv[1])
|
||||
echeck_cmd = "/home/eressea/echeck/echeck.sh"
|
||||
maxlines = 25
|
||||
|
||||
# base directory for all your games:
|
||||
install_dir = "/home/eressea/eressea"
|
||||
if 'ERESSEA' in os.environ:
|
||||
install_dir = os.environ['ERESSEA']
|
||||
elif 'HOME' in os.environ:
|
||||
install_dir = os.path.join(os.environ['HOME'], '/eressea')
|
||||
if not os.path.isdir(install_dir):
|
||||
print "please set the ERESSEA environment variable to the install path"
|
||||
sys.exit(1)
|
||||
|
||||
game_dir = os.path.join(install_dir, "game-%d" % (game, ))
|
||||
frommail = 'eressea-server@kn-bremen.de'
|
||||
gamename = 'Eressea'
|
||||
sender = '%s Server <%s>' % (gamename, frommail)
|
||||
|
||||
inifile = os.path.join(game_dir, 'eressea.ini')
|
||||
if not os.path.exists(inifile):
|
||||
print "no such file: " . inifile
|
||||
else:
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.read(inifile)
|
||||
if config.has_option('game', 'email'):
|
||||
frommail = config.get('game', 'email')
|
||||
if config.has_option('game', 'name'):
|
||||
gamename = config.get('game', 'name')
|
||||
if config.has_option('game', 'sender'):
|
||||
sender = config.get('game', 'sender')
|
||||
else:
|
||||
sender = "%s Server <%s>" % (gamename, frommail)
|
||||
config = None
|
||||
|
||||
queue_file = os.path.join(game_dir, "orders.queue")
|
||||
if not os.path.exists(queue_file):
|
||||
exit(0)
|
||||
|
||||
# regular expression that finds the start of a faction
|
||||
fact_re = compile("^\s*(eressea|partei|faction)\s+([a-zA-Z0-9]+)\s+\"?([^\"]*)\"?", IGNORECASE)
|
||||
|
||||
def check_pwd(filename, email, pw_data):
|
||||
results = []
|
||||
try:
|
||||
file = open(filename, "r")
|
||||
except:
|
||||
print "could not open file", filename
|
||||
return results
|
||||
for line in file.readlines():
|
||||
mo = fact_re.search(strip(line))
|
||||
if mo != None:
|
||||
fact_nr = str(mo.group(2))
|
||||
fact_pw = str(mo.group(3))
|
||||
if pw_data.fac_exists(fact_nr):
|
||||
if not pw_data.check(fact_nr, fact_pw):
|
||||
game_email = pw_data.get_email(fact_nr)
|
||||
results = results + [ (fact_nr, game_email, False, fact_pw) ]
|
||||
else:
|
||||
game_email = pw_data.get_email(fact_nr)
|
||||
results = results + [ (fact_nr, game_email, True, fact_pw) ]
|
||||
else:
|
||||
results = results + [ (fact_nr, None, False, fact_pw) ]
|
||||
return results
|
||||
|
||||
def echeck(filename, locale, rules):
|
||||
dirname, filename = split_filename(filename)
|
||||
stream = popen("%s %s %s %s %s" % (echeck_cmd, locale, filename, dirname, rules), 'r')
|
||||
lines = stream.readlines()
|
||||
if len(lines)==0:
|
||||
stream.close()
|
||||
return None
|
||||
if len(lines)>maxlines:
|
||||
mail = join(lines[:maxlines-3] + ["...", "\n"] + lines[-3:], '')
|
||||
else:
|
||||
mail = join(lines[:maxlines], '')
|
||||
stream.close()
|
||||
return mail
|
||||
|
||||
# parse the queue file -
|
||||
#print "connecting to SMTP..."
|
||||
from smtplib import SMTP
|
||||
try:
|
||||
server = SMTP("localhost")
|
||||
except:
|
||||
print "could not connect to SMTP server"
|
||||
exit(0)
|
||||
|
||||
#print "reading password file..."
|
||||
pw_data = EPasswd(os.path.join(game_dir,"passwd"))
|
||||
|
||||
#print "reading orders.queue..."
|
||||
# move the queue file to a save space while locking it:
|
||||
try:
|
||||
lock_file(queue_file)
|
||||
except:
|
||||
exit(0)
|
||||
queuefile = open(queue_file, "r")
|
||||
lines = queuefile.readlines()
|
||||
queuefile.close()
|
||||
|
||||
# copy to a temp file
|
||||
|
||||
tname="/tmp/orders.queue.%s" % str(time())
|
||||
try:
|
||||
lock_file(tname)
|
||||
except:
|
||||
exit(0)
|
||||
tmpfile=open(tname, "w")
|
||||
for line in lines:
|
||||
tmpfile.write(line)
|
||||
tmpfile.close()
|
||||
|
||||
openlog("orders")
|
||||
|
||||
unlink(queue_file)
|
||||
try:
|
||||
unlock_file(queue_file)
|
||||
except:
|
||||
pass
|
||||
|
||||
for line in lines:
|
||||
tokens = split(line[:-1], ' ')
|
||||
dict = {}
|
||||
for token in tokens:
|
||||
name, value = split(token, '=')
|
||||
dict[name] = value
|
||||
|
||||
email = dict["email"]
|
||||
locale = dict["locale"]
|
||||
game = int(dict["game"])
|
||||
infile = dict["file"]
|
||||
gamename='[E%d]' % game
|
||||
rules='e%d' % game
|
||||
warning = ""
|
||||
failed = True
|
||||
results = check_pwd(infile, email, pw_data)
|
||||
logfile = open(os.path.join(game_dir, "zug.log"), "a")
|
||||
dirname, filename = split_filename(infile)
|
||||
msg = messages["validate-"+locale] + " " + infile + "\n\n"
|
||||
for faction, game_email, success, pwd in results:
|
||||
msg = msg + messages["faction-"+locale] + " " + faction + "\n"
|
||||
if success: failed = False
|
||||
else: msg = msg + messages["unknown-"+locale] + "\n"
|
||||
msg = msg + "\n"
|
||||
logfile.write("%s:%s:%s:%s:%s:%s\n" % (ctime(time()), email, game_email, faction, pwd, success))
|
||||
logfile.close()
|
||||
|
||||
if failed:
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
syslog("failed - no valid password in " + infile)
|
||||
else:
|
||||
result = None
|
||||
if os.path.exists(echeck_cmd):
|
||||
result = echeck(infile, locale, rules)
|
||||
if result is None:
|
||||
# echeck did not finish
|
||||
msg = msg + "Echeck is broken. Your turn was accepted, but could not be verified.\n"
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
syslog("process - echeck broken, " + infile)
|
||||
else:
|
||||
msg = msg + result
|
||||
syslog("process - checked orders in " + infile)
|
||||
|
||||
subject = gamename + " " + messages["subject-" + locale] + warning
|
||||
msg = "Subject: %s\nFrom: %s\nTo: %s\nContent-Type: text/plain; charset=utf-8\n\n" % (subject, sender, email) + msg
|
||||
try:
|
||||
server.sendmail(sender, email, msg)
|
||||
except:
|
||||
syslog("failed - cannot send to " + email)
|
||||
|
||||
server.close()
|
||||
|
||||
closelog()
|
||||
unlink(tname)
|
||||
unlock_file(tname)
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from os import unlink, symlink, rename, popen, tmpfile
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import ConfigParser
|
||||
import subprocess
|
||||
from re import compile, IGNORECASE
|
||||
from string import split, join, upper, strip
|
||||
from sys import argv, exit
|
||||
from time import sleep, time, ctime
|
||||
from syslog import openlog, closelog, syslog
|
||||
|
||||
from epasswd import EPasswd
|
||||
|
||||
def pwd_get_email(faction, pwd, pwdfile=None):
|
||||
return None
|
||||
|
||||
def split_filename(filename):
|
||||
return os.path.split(filename)
|
||||
|
||||
def unlock_file(filename):
|
||||
try:
|
||||
unlink(filename+".lock")
|
||||
except:
|
||||
print "could not unlock %s.lock, file not found" % filename
|
||||
raise
|
||||
|
||||
def lock_file(filename):
|
||||
i = 0
|
||||
wait = 1
|
||||
if not os.path.exists(filename):
|
||||
file=open(filename, "w")
|
||||
file.close()
|
||||
while True:
|
||||
try:
|
||||
symlink(filename, filename+".lock")
|
||||
return
|
||||
except:
|
||||
i = i+1
|
||||
if i == 5:
|
||||
raise
|
||||
sleep(wait)
|
||||
wait = wait*2
|
||||
|
||||
messages = {
|
||||
"subject-de": "Befehle angekommen",
|
||||
"subject-en": "orders received",
|
||||
|
||||
"validate-en": "Validating",
|
||||
"validate-de": "Verarbeite",
|
||||
|
||||
"faction-en": "Faction",
|
||||
"faction-de": "Partei",
|
||||
|
||||
"unknown-de": "WARNUNG: Die Partei ist nicht bekannt, oder das Passwort falsch!",
|
||||
"unknown-en": "WARNING: This faction is unknown, or the password is incorrect!",
|
||||
|
||||
"warning-de": "Warnung",
|
||||
"warning-en": "Warning",
|
||||
|
||||
"error-de": "Fehler",
|
||||
"error-en": "Error",
|
||||
}
|
||||
|
||||
game = int(sys.argv[1])
|
||||
echeck_cmd = "/home/eressea/echeck/echeck.sh"
|
||||
maxlines = 25
|
||||
|
||||
# base directory for all your games:
|
||||
install_dir = "/home/eressea/eressea"
|
||||
if 'ERESSEA' in os.environ:
|
||||
install_dir = os.environ['ERESSEA']
|
||||
elif 'HOME' in os.environ:
|
||||
install_dir = os.path.join(os.environ['HOME'], 'eressea')
|
||||
if not os.path.isdir(install_dir):
|
||||
print "please set the ERESSEA environment variable to the install path"
|
||||
sys.exit(1)
|
||||
|
||||
game_dir = os.path.join(install_dir, "game-%d" % (game, ))
|
||||
gamename = 'Eressea'
|
||||
|
||||
inifile = os.path.join(game_dir, 'eressea.ini')
|
||||
queue_file = os.path.join(game_dir, "orders.queue")
|
||||
if not os.path.exists(queue_file):
|
||||
exit(0)
|
||||
|
||||
# regular expression that finds the start of a faction
|
||||
fact_re = compile("^\s*(eressea|partei|faction)\s+([a-zA-Z0-9]+)\s+\"?([^\"]*)\"?", IGNORECASE)
|
||||
|
||||
def check_pwd(filename, email, pw_data):
|
||||
results = []
|
||||
try:
|
||||
file = open(filename, "r")
|
||||
except:
|
||||
print "could not open file", filename
|
||||
return results
|
||||
for line in file.readlines():
|
||||
mo = fact_re.search(strip(line))
|
||||
if mo != None:
|
||||
fact_nr = str(mo.group(2))
|
||||
fact_pw = str(mo.group(3))
|
||||
if pw_data.fac_exists(fact_nr):
|
||||
if not pw_data.check(fact_nr, fact_pw):
|
||||
game_email = pw_data.get_email(fact_nr)
|
||||
results = results + [ (fact_nr, game_email, False, fact_pw) ]
|
||||
else:
|
||||
game_email = pw_data.get_email(fact_nr)
|
||||
results = results + [ (fact_nr, game_email, True, fact_pw) ]
|
||||
else:
|
||||
results = results + [ (fact_nr, None, False, fact_pw) ]
|
||||
return results
|
||||
|
||||
def echeck(filename, locale, rules):
|
||||
dirname, filename = split_filename(filename)
|
||||
stream = popen("%s %s %s %s %s" % (echeck_cmd, locale, filename, dirname, rules), 'r')
|
||||
lines = stream.readlines()
|
||||
if len(lines)==0:
|
||||
stream.close()
|
||||
return None
|
||||
if len(lines)>maxlines:
|
||||
mail = join(lines[:maxlines-3] + ["...", "\n"] + lines[-3:], '')
|
||||
else:
|
||||
mail = join(lines[:maxlines], '')
|
||||
stream.close()
|
||||
return mail
|
||||
|
||||
#print "reading password file..."
|
||||
pw_data = EPasswd(os.path.join(game_dir,"passwd"))
|
||||
|
||||
#print "reading orders.queue..."
|
||||
# move the queue file to a save space while locking it:
|
||||
try:
|
||||
lock_file(queue_file)
|
||||
except:
|
||||
exit(0)
|
||||
queuefile = open(queue_file, "r")
|
||||
lines = queuefile.readlines()
|
||||
queuefile.close()
|
||||
|
||||
# copy to a temp file
|
||||
|
||||
tname="/tmp/orders.queue.%s" % str(time())
|
||||
try:
|
||||
lock_file(tname)
|
||||
except:
|
||||
exit(0)
|
||||
tmpfile=open(tname, "w")
|
||||
for line in lines:
|
||||
tmpfile.write(line)
|
||||
tmpfile.close()
|
||||
|
||||
openlog("orders")
|
||||
|
||||
unlink(queue_file)
|
||||
try:
|
||||
unlock_file(queue_file)
|
||||
except:
|
||||
pass
|
||||
|
||||
for line in lines:
|
||||
tokens = split(line[:-1], ' ')
|
||||
dict = {}
|
||||
for token in tokens:
|
||||
name, value = split(token, '=')
|
||||
dict[name] = value
|
||||
|
||||
email = dict["email"]
|
||||
locale = dict["locale"]
|
||||
game = int(dict["game"])
|
||||
infile = dict["file"]
|
||||
gamename='[E%d]' % game
|
||||
rules='e%d' % game
|
||||
warning = ""
|
||||
failed = True
|
||||
results = check_pwd(infile, email, pw_data)
|
||||
logfile = open(os.path.join(game_dir, "zug.log"), "a")
|
||||
dirname, filename = split_filename(infile)
|
||||
msg = messages["validate-"+locale] + " " + infile + "\n\n"
|
||||
for faction, game_email, success, pwd in results:
|
||||
msg = msg + messages["faction-"+locale] + " " + faction + "\n"
|
||||
if success: failed = False
|
||||
else: msg = msg + messages["unknown-"+locale] + "\n"
|
||||
msg = msg + "\n"
|
||||
logfile.write("%s:%s:%s:%s:%s:%s\n" % (ctime(time()), email, game_email, faction, pwd, success))
|
||||
logfile.close()
|
||||
|
||||
if failed:
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
syslog("failed - no valid password in " + infile)
|
||||
else:
|
||||
result = None
|
||||
if os.path.exists(echeck_cmd):
|
||||
result = echeck(infile, locale, rules)
|
||||
if result is None:
|
||||
# echeck did not finish
|
||||
msg = msg + "Echeck is broken. Your turn was accepted, but could not be verified.\n"
|
||||
warning = " (" + messages["warning-" + locale] + ")"
|
||||
syslog("process - echeck broken, " + infile)
|
||||
else:
|
||||
msg = msg + result
|
||||
syslog("process - checked orders in " + infile)
|
||||
|
||||
subject = gamename + " " + messages["subject-" + locale] + warning
|
||||
try:
|
||||
sp = subprocess.Popen(['mutt', '-s', subject, email], stdin=subprocess.PIPE)
|
||||
sp.communicate(msg)
|
||||
except:
|
||||
syslog("failed - cannot send to " + email)
|
||||
|
||||
closelog()
|
||||
unlink(tname)
|
||||
unlock_file(tname)
|
Loading…
Reference in New Issue