Hi all,

Answering a FAQ here: using dbmail you can now provide a functional autoreplier with the same features as the famous vacation script.

Since dbmail's autoreply functionality is less than useful, I decided to whip up a script to mimic the vacation functionality without having to provide posix users as required by vacation itself.

howto:
0) make sure you have installed python on your system
1) install the attached script in your path, i.e. /usr/bin/autoreplier
2) run:
        install -d -o dbmail -g root -m 2750 /var/cache/dbmail/
        install -d -o dbmail -g root -m 2750 /var/lib/dbmail/
3) create a reply message file, i.e.
         /var/lib/dbmail/messages/johndoe.msg
this message should be a well-formed email message, including a From and a Subject line.
"""
From: [EMAIL PROTECTED] (J.Doe)
Subject: Out-of-Office message

Hi there,
I'm off for the duration...
please call our office at 0800-12345 for urgent issues.
--
J.Doe.
"""
4) add an alias using dbmail-adduser to activate:
   dbmail-adduser f [EMAIL PROTECTED] "|/usr/bin/autoreplier \
        -u johndoe -a [EMAIL PROTECTED] \
        -m /var/lib/dbmail/johndoe.msg"

Now the reply message will be sent back no more than once a week to the same recipient. Messages from postmaster, mailer-daemon, or daemon are ignored. Only message sent directly to [EMAIL PROTECTED] (To or Cc headers are checked) will be replied to.

5) to deactivate:
   dbmail-adduser x [EMAIL PROTECTED] "|/usr/bin/autoreplier \
        -u johndoe -a [EMAIL PROTECTED] \
        -m /var/lib/dbmail/johndoe.msg"


There are some loose ends in the code:
- extend the options to resemble vacation a bit more.
- add an X-Loop header to prevent unnecessary loops.

Some ideas for additional features I still have:
- control (de)activation through the tool itself
- store the reply message in the dbmail database (use the auto_replies table if possible)


what do you think?


--
  ________________________________________________________________
  Paul Stevens                                  mailto:[EMAIL PROTECTED]
  NET FACILITIES GROUP                     PGP: finger [EMAIL PROTECTED]
  The Netherlands________________________________http://www.nfg.nl
#!/usr/bin/python

#
# Copyright: NFG, Paul Stevens <[EMAIL PROTECTED]>, 2004
# License: GPL
#
# $Id: autoreplier.py,v 1.2 2004/06/30 18:17:40 paul Exp $
#
# Reimplementation of the famous vacation tool for dbmail
#
#

import os,sys,string,email,getopt,shelve,time,re,smtplib


def usage():
    print """autoreplier: dbmail autoreply replacement
    -u <username>   --username=<username>               specify recipient
    -a <alias>      --alias=<alias>                     specify matching destination address
    -m <file>       --message-file=<file>               file containing reply message
    
"""
error='AutoReplyError'

class AutoReplier:
    CACHEDIR="/var/cache/dbmail"
    TIMEOUT=60*24*7
    OUTHOST="localhost"
    OUTPORT=25

    _username=None
    _messagefile=None

    def __init__(self):
        self.setMessage(email.message_from_file(sys.stdin))

    def setUsername(self,_username): self._username=_username
    def getUsername(self): return self._username
        
    def setMessage(self,_message): self._message=_message
    def getMessage(self): return self._message

    def setReply(self,_messagefile): self._messagefile=_messagefile
    def getReply(self): return email.message_from_file(open(self._messagefile))
    
    def setAlias(self,_alias): self._alias=_alias
    def getAlias(self): return self._alias
        
    def openCache(self):
        file=os.path.join(self.CACHEDIR,"%s.db" % self.getUsername())
        self.cache=shelve.open(file,writeback=True)
        
    def closeCache(self): self.cache.close()

    def checkSender(self,bounce_senders=[]):
        for f in ('From',):
            if self.getMessage().has_key(f):
                header=string.lower(self.getMessage()[f])
                for s in bounce_senders:
                    if string.find(header,s) >= 0:
                        return True
        return False
                
    def checkDestination(self):
        for f in ('To','Cc'):
            if self.getMessage().has_key(f):
                header=string.lower(self.getMessage()[f])
                if string.find(header,self.getAlias()) >=0:
                    return True
        return False
        
    def send_message(self,msg):
        server=smtplib.SMTP(self.OUTHOST,self.OUTPORT)
        server.sendmail(msg['From'],msg['To'],msg.as_string())
        server.quit()
                        

    def _reply(self):
        m=self.getMessage()
        u=self.getUsername()
        if m.has_key('Reply-to'): to=m['Reply-to']
        elif m.has_key('From'): to=m['From']
        else: raise error, "No return address"

        if self.checkSender(['daemon','mailer-daemon','postmaster']):
            return
        if not self.checkDestination():
            return 
            
        if not self.cache.has_key(u):
            self.cache[u]={}
        if not self.cache[u].has_key(to) or self.cache[u][to] < int(time.time())-self.TIMEOUT:
            reply=self.getReply()
            del reply['To']
            reply['To']=to
            self.send_message(reply)
            self.cache[u][to]=int(time.time())
        
    def reply(self):
        self.openCache()
        self._reply()
        self.closeCache()

if __name__ == '__main__':
    try:
        opts,args = getopt.getopt(sys.argv[1:],"u:m:a:", 
            ["username=","message-file=","alias="])
    except getopt.GetoptError:
        usage()
        sys.exit(0)
        
    replier=AutoReplier()
    
    for o,a in opts:
        if o in ('-u','--username'):
            replier.setUsername(a)
        if o in ('-a','--alias'):
            replier.setAlias(a)
        if o in ('-m','--message-file'):
            replier.setReply(a)

    replier.reply()

    
    

Reply via email to