imapfwd: forward mail to a main box

I have several email addresses but I want all messages to arrive in a single mailbox. imapfwd connects to an imap server and forward all unread mails to an other address through SMTP. Here are the recognized options:

$ ./imapfwd --help
Usage: imapfwd [options] USERNAME IMAPHOST SMTPHOST DESTINATION

Options:
  -h, --help       show this help message and exit
  --pass=PASSWORD  imap password
  -p PORT          imap port
  --ssl            use SSL for imap
  --prefix=PREFIX  append a string to subject. ex: [box1]

I use the script in a cronjob. To set up the job, type crontab -e and add a line like this (I’ve saved the script in /home/pierre/bin/):

# m    h  dom mon dow   command
 */10  *   *   *   *    /home/pierre/bin/imapfwd --pass or4nge mylogin imap.hmail.com smtp.isp.com mainbox@fmail.com

Here is the script:

[download imapfwd]

#!/usr/bin/env python
 
# Copyright 2009 (C) Pierre Duquesne <stackp@online.fr>
# Licensed under the BSD Revised License.
 
import imaplib
import smtplib
import sys
import optparse
import getpass
import email.parser
 
USAGE="imapfwd [options] USERNAME IMAPHOST SMTPHOST DESTINATION" 
 
def parse_args():
    "Parse command-line arguments."
    parser = optparse.OptionParser(usage=USAGE)
    parser.add_option('--pass', dest='password', default=None,
                      help="imap password")
    parser.add_option('-p', dest='port', type='int', default=None,
                      help="imap port")
    parser.add_option('--ssl', dest='ssl', default=False, 
                      action='store_true',
                      help="use SSL for imap")
    parser.add_option('--prefix', dest='prefix', default=None, 
                      action='store',
                      help="append a string to subject. ex: [box1]")
    options, remainder = parser.parse_args(sys.argv[1:])
    return options, remainder
 
options, args = parse_args()
try:
    username = args[0]
    imaphost = args[1]
    smtphost = args[2]
    destination = args[3]
except:
    print "Error: some arguments are missing. Try --help."
    print USAGE
    sys.exit(1)
 
# connect to imap
print 'Connecting to %s as user %s ...' % (imaphost, username)
if options.ssl: 
    IMAP = imaplib.IMAP4_SSL
else:
    IMAP = imaplib.IMAP4
try:
    if options.port:  
        imap_server = IMAP(imaphost, options.port)
    else:     
        imap_server = IMAP(imaphost)
    if not options.password: 
        options.password = getpass.getpass()
    imap_server.login(username, options.password)
except Exception,e:
        print 'Error:', e;  sys.exit(1)
 
# connect to smtp
try:
    smtp_server = smtplib.SMTP(smtphost)
except Exception, e:
    print 'Could not connect to', smtphost, e.__class__, e
    sys.exit(2)
 
# filter unseen messages
imap_server.select("INBOX")
resp, items = imap_server.search(None, "UNSEEN")
numbers = items[0].split()
 
# forward each message
sender = "%s@%s" % (username, imaphost)
for num in numbers:
    resp, data = imap_server.fetch(num, "(RFC822)")
    text = data[0][1]
    if options.prefix:
        parser = email.parser.HeaderParser()
        msg = parser.parsestr(text)
        msg['Subject'] = options.prefix + msg['Subject']
        text = msg.as_string()
    smtp_server.sendmail(sender, destination, text)
    # Flag message as Seen (may have already been done by the server anyway)
    imap_server.store(num, '+FLAGS', '\\Seen')
 
imap_server.close()
smtp_server.quit()