Our Belgian Earthquake Emergency Report System (BEERS) detects abnormal visitor fluxes on the http://www.seismologie.be website and sends emails & SMS whenever some threshold is met. Recently, we have upgraded our sms machinery to FoxBox and for some weird reasons, the whole did not behave normally. The process is simple :
Detection → Send Email to sms server → procmail process the emails and outputs to the FoxBox outgoing box → sms is sent !
The procmail step was buggy, so I replaced the step by piping to a Python script. For this, I installed Miniconda on the box !
#PATH=/usr/bin:/usr/local/bin MAILDIR=$HOME/Maildir # all mailboxes are in .mailspool/ DEFAULT=$HOME/Maildir/cur LOGFILE=/dev/null SHELL=/bin/sh :0 W: | /home/thomas/miniconda/bin/python /home/smsgate/pymail.py
The email is not kept in the Maildir directory (add a “c” to :0 W c: to keep it). The W tells procmail to wait for the exit code of the pipe.
The python code itself is simply processing the emails, checking if the body is multipart (using this snippet). If the subject line contains two or more phone numbers, the same number of temporary files are created in the outbox (using a timestamp as filename for uniqueness reasons). The numbers can be separated by commas or semi-columns.
#!/home/thomas/miniconda/bin/python import sys import email import time import shutil def get_first_text_part(msg): maintype = msg.get_content_maintype() if maintype == 'multipart': for part in msg.get_payload(): if part.get_content_maintype() == 'text': return part.get_payload() elif maintype == 'text': return msg.get_payload() full_msg = sys.stdin.readlines() msg = email.message_from_string(''.join(full_msg)) to = msg['to'] xfrom = msg['from'] subject = msg['subject'] body = get_first_text_part(msg) if subject.count(';') != 0: tos = subject.split(';') elif subject.count(',') != 0: tos = subject.split(',') else: tos = [subject,] for to in tos: fname = "%.3f"%time.time() out = open(fname,'w') out.write("To: %s\n" % to) out.write('\n') out.write(str(body)) out.close() shutil.move(fname, "/mnt/flash/spool/outgoing/"+fname) time.sleep(0.5)
That’s All !