Fetch pop3 email using Python

# -*- coding: utf-8 -*-
import poplib
import email
import email.Parser
import email.header
import os
import sys
import base64
from optparse import OptionParser

__version__ = u'0.0.1'
__author__ = u'MeaCulpa '
__all__ = [u'fetchmail']

class email_attachment:
    def __init__(self, messagenum, attachmentnum, filename, contents):
        '''
        arguments:
            messagenum - message number of this message in the Inbox
            attachmentnum - attachment number for this attachment
            filename - filename for this attachment
            contents - attachment's contents
        '''
        self.messagenum=messagenum
        self.attachmentnum=attachmentnum
        self.filename=filename
        self.contents=contents
        return

    def save(self, savepath, savefilename=None):
        '''
        Method to save the contents of an attachment to a file
        arguments:
            savepath - path where file is to be saved
            safefilename - optional name (if None will use filename of attachment
        '''

        savefilename=savefilename or self.filename
        f=open(os.path.join(savepath, savefilename),"wb")
        f.write(self.contents)
        f.close()
        return

class email_msg:
    def __init__(self, messagenum, contents):
        self.messagenum=messagenum
        self.contents=contents
        self.attachments_index=0  # Index of attachments for next method
        self.ATTACHMENTS=[]       # List of attachment objects

        self.msglines='\n'.join(contents[1])
        #
        # See if I can parse the message lines with email.Parser
        #
        self.msg=email.Parser.Parser().parsestr(self.msglines)
        if self.msg.is_multipart():
            attachmentnum=0
            for part in self.msg.walk():
                # multipart/* are just containers
                mptype=part.get_content_maintype()
                filename = part.get_filename()
                if mptype == "multipart": continue
                if filename: # Attached object with filename
                    attachmentnum+=1
                    self.ATTACHMENTS.append(email_attachment(messagenum, attachmentnum, filename, part.get_payload(decode=1)))
                    print "Attachment filename=%s" % filename

                else: # Must be body portion of multipart
                    self.body=base64.b64decode(part.get_payload())

        else: # Not multipart, only body portion exists
            self.body=base64.b64decode(self.msg.get_payload())

        return


    def get(self, key):
        try: return self.msg.get(key)
        except:
            emsg="email_msg-Unable to get email key=%s information" % key
            print emsg
            sys.exit(emsg)

    def has_attachments(self):
        return (len(self.ATTACHMENTS) > 0)

    def __iter__(self):
        return self

    def next(self):
        #
        # Try to get the next attachment
        #
        try: ATTACHMENT=self.ATTACHMENTS[self.attachments_index]
        except:
            self.attachments_index=0
            raise StopIteration
        #
        # Increment the index pointer for the next call
        #
        self.attachments_index+=1
        return ATTACHMENT

class pop3_inbox:
    def __init__(self, server, userid, password):
        self._trace=0
        if self._trace: print "pop3_inbox.__init__-Entering"
        self.result=0             # Result of server communication
        self.MESSAGES=[]          # List for storing message objects
        self.messages_index=0     # Index of message for next method
        #
        # See if I can connect using information provided
        #
        try:
            if self._trace: print "pop3_inbox.__init__-Calling poplib.POP3(server)"
            self.connection=poplib.POP3(server)
            if self._trace: print "pop3_inbox.__init__-Calling connection.user(userid)"
            self.connection.user(userid)
            if self._trace: print "pop3_inbox.__init__-Calling connection.pass_(password)"
            self.connection.pass_(password)

        except:
            if self._trace: print "pop3_inbox.__init__-Login failure, closing connection"
            self.result=1
            self.connection.quit()

        #
        # Get count of messages and size of mailbox
        #
        if self._trace: print "pop3_inbox.__init__-Calling connection.stat()"
        self.msgcount, self.size=self.connection.stat()
        #
        # Loop over all the messages processing each one in turn
        #
        for msgnum in range(1, self.msgcount+1):
            self.MESSAGES.append(email_msg(msgnum, self.connection.retr(msgnum)))

        if self._trace: print "pop3_inbox.__init__-Leaving"
        return

    def close(self):
        self.connection.quit()
        return

    def remove(self, msgnumorlist):
        if isinstance(msgnumorlist, int): self.connection.dele(msgnumorlist)
        elif isinstance(msgnumorlist, (list, tuple)):
            map(self.connection.dele, msgnumorlist)
        else:
            emsg="pop3_inbox.remove-msgnumorlist must be type int, list, or tuple, not %s" % type(msgnumorlist)
            print emsg
            sys.exit(emsg)

        return

    def __iter__(self):
        return self

    def next(self):
        #
        # Try to get the next attachment
        #
        try: MESSAGE=self.MESSAGES[self.messages_index]
        except:
            self.messages_index=0
            raise StopIteration
        #
        # Increment the index pointer for the next call
        #
        self.messages_index+=1
        return MESSAGE

if __name__=="__main__":
    
    # parse commandline options
    optparse = OptionParser(version=__version__)
                        
    optparse.add_option('-s', '--server',
                        dest = 'server',
                        default = '',
                        help = 'smtp server')
                        
    optparse.add_option('-u', '--userid',
                        dest = 'userid',
                        default = '',
                        help = 'smtp userid')   

    optparse.add_option('-p', '--password',
                        dest = 'password', 
                        default = '',
                        help = 'smtp password')

    opts, args = optparse.parse_args()

    if args:
        optparse.error(u'invalid arguments')
        sys.exit()

    #if in-sufficient option print help
    if len(sys.argv) < 3:
        optparse.print_help()
        sys.exit()

    inbox=pop3_inbox(opts.server, opts.userid, opts.password)
    if inbox.result:
        emsg="Failure connecting to pop3_inbox"
        print emsg
        sys.exit(emsg)

    print "Message count=%i, Inbox size=%i" % (inbox.msgcount, inbox.size)

    counter=0
    for m in inbox:
        counter+=1
        print "Subject: %s" % email.header.decode_header(m.get('subject'))[0][0]
        print "-------------Message (%i) body lines---------------" % counter
        print m.body
        print "-------------End message (%i) body lines-----------" % counter
        if m.has_attachments():
            acounter=0
            for a in m:
                acounter+=1
                print "-------------Message (%i) attachments-------------" % counter
                print "%i: %s" % (acounter, a.filename)
                print "-------------End message (%i) attachments---------" % counter
                a.save(os.path.join(os.getcwd(), u'tmp'))

        else: print "-------------Message has no attachments----------"

    inbox.close()

0 comments:

Post a Comment

| More

Twitter Updates