#!/usr/bin/python # later_mail.py - A automated mail responder # Copyright (C) 2000 Erik Forsberg # forsberg@lysator.liu.se # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program, see the file COPYING; if not, write # to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, # MA 02139, USA. import getopt, rfc822, mailbox, sys, time, string, smtplib, pwd, getpass import socket, shelve, os FALSE = 0 TRUE = 1 # Some global varables delaytime = 12*60*60 mtype = "UnixMailbox" template = None verbose = FALSE defsenderaddr = None smtphost = 'localhost' smtpserver = None version = "0.01" donothing = FALSE sentdb = shelve.open(os.environ['HOME'] + '/.later_mailheaders') def notInDatabase(msgId): try: sentdb[msgId] if (verbose): print "Message was already in database" return FALSE except KeyError: sentdb[msgId] = time.time() if (verbose): print "Message was not in database, sending message" return TRUE defmessage = """From: #FROMADDR# Subject: Automated response from #USER# To: #TOADDR# [English version below] ---In Swedish--- Hej! Det här är ett automatiskt meddelande om att #USER# har placerat ditt meddelande med ärendet \"#SUBJECT#\" och datum \"#DATE#\" i sin Att-svaras-på-box. Det betyder att ditt mail kommer att svaras på, men inte just nu. Hav tålamod! ---In English--- Hi! This is a automated response telling you that #USER# has put your message with subject \"#SUBJECT#\" and date \"#DATE#\" in his to-be-answered-later-box. This means your mail will be answered, though not right now. Be patient! -- Message produced with later_mail.py v%s """ % version def sendMail(msg): message = None if template != None: fp = open(template, 'r') message = fp.read() fp.close() else: message = defmessage userinfo = pwd.getpwnam(getpass.getuser()) to = msg.getaddr('From') senderaddr = defsenderaddr if defsenderaddr == None: senderaddr = getpass.getuser() + "@" + \ socket.gethostbyaddr(socket.gethostname())[0] try: message = string.replace(message, '#USER#', userinfo[0]) message = string.replace(message, '#SUBJECT#', msg.getheader('Subject')) message = string.replace(message, '#DATE#', msg.getheader('Date')) message = string.replace(message, '#FROMADDR#', senderaddr) message = string.replace(message, '#TOADDR#', to[1]) except TypeError: print "Malformed message" return if(verbose): print message if(verbose): print "Sending message from %s to %s" % (senderaddr, to[1]) if not donothing: smtpserver.sendmail(senderaddr, [to[1]], message) def printUsage(): print "Usage: AnswerLater.py" +\ " [-t MailBoxType][-d DelayTime][-f template][-v]\n" +\ " [-F fromaddr][-s smtphost] " print "-t\tSpecify the type of the mailbox. Recognized types are " + \ "\n\tUnixMailbox (default), MmdfMailbox, MHMailbox, \n\tMaildir" +\ " and BabylMailbox" print "-d\tSpecify how long time should pass before message is sent" print "-f\tSpecify a template for how the message should look." print "-F\tSpecify default sender address in mails sent" print "-s\tSpecify smtp host, localhost is default." print "-n\tDo nothing, just simulate. Best used with -v" print "-v\tBe verbose" def openMailbox(mbox, mtype): if mtype == "UnixMailbox" or mtype == "MmdfMailbox": try: fp = open(mbox, 'r') except IOError: print "Couldn't open file %s for input" % mbox sys.exit(1) if mtype == "UnixMailbox": return mailbox.UnixMailbox(fp) else: return mailbox.MmdfMailbox(fp) elif mtype == "MHMailbox": return mailbox.MHMailbox(mbox) elif mtype == "Maildir": return mailbox.maildir(mbox) elif mtype == "BabylMailbox": return mailbox.BabylMailbox(mbox) else: print "I don't understand the mailbox type %s" % mtype printUsage() sys.exit(1) def getDate(msg): recv = msg.getallmatchingheaders('Received') datepart = string.split(recv[len(recv)-1], ';')[1] print datepart return rfc822.parsedate(datepart) try: optlist, args = getopt.getopt(sys.argv[1:], 't:d:f:vhF:s:n') except getopt.error, error_cause: print error_cause sys.exit(1) for opt in optlist: if opt[0] == '-t': mtype = str(opt[1]) elif opt[0] == '-d': delaytime = int(opt[1])*3600 elif opt[0] == '-f': template = str(opt[1]) elif opt[0] == '-v': verbose = TRUE elif opt[0] == '-h': printUsage() sys.exit(0) elif opt[0] == '-F': defsenderaddr = str(opt[1]) elif opt[0] == '-s': smtphost = str(opt[1]) elif opt[0] == '-n': donothing = TRUE if len(args) < 1: printUsage() sys.exit(1) if(verbose): print "Operating on %s of type %s" % (args[0], mtype) print "Will use delay of %d hours" % (delaytime / 3600) mb = openMailbox(args[0], mtype) smtpserver = smtplib.SMTP(smtphost) allMsgIds = [] while 1: msg = mb.next() if msg == None: break mtime = msg.getdate('Date') if (verbose): print msg.getheader('Date') try: mailtime = time.mktime(mtime) except TypeError: print "Message date format unparsable - skipping" continue if (time.time() - mailtime) > delaytime: msgId = msg.getheader('Message-Id') allMsgIds = allMsgIds + [msgId] if notInDatabase(msgId): if (verbose): print "Too old!" sendMail(msg) else: if(verbose): print "Not too old.." keys = sentdb.keys() for key in keys: try: for mId in allMsgIds: if key == mId: StillInSpool = "Message still valid" raise StillInSpool except StillInSpool: continue del sentdb[key]