9

I am trying to access POP3 email server. I will be polling messages and downloading attachments for each one of them. I can successfully login and get the messages but cannot figure out how to actually get the attachment, which I would need to parse later. I'm thinking I could save to tmp dir until I process it.

Here's what I got so far:

pop = poplib.POP3_SSL(server)
pop.user(usr)
pop.pass_(pwd)

f = open(file_dir, 'w')
num_msgs = len(pop.list()[1])
for msg_list in range(num_msgs):
    for msg in pop.retr(msg_list+1)[1]:
        mail = email.message_from_string(msg)
        for part in mail.walk():
            f.write(part.get_payload(decode=True))
f.close()

This is code I pieced together from the examples I found online but no solid example of actually getting the attachment. The file I'm writing to is empty. What am I missing here?

faintsignal
  • 1,828
  • 3
  • 22
  • 30
t0x13
  • 351
  • 2
  • 10
  • 24
  • I'm curious if you found the answer to your problem? – bogeymin Dec 22 '11 at 00:59
  • @bogeymin I did find the answer. If you need it I can dig up the file for ya :) – t0x13 Feb 22 '12 at 04:30
  • I knew the answer, and would have added it here if you hadn't found the problem. But the question was old, so I didn't know if it needed an answer. – bogeymin Feb 22 '12 at 11:52
  • 1
    Hi, I would like to know the anwser, is there anyone who can tell me at this time? :P – Felix Yan Jun 23 '12 at 03:27
  • [This](https://stackoverflow.com/questions/8307809/save-email-attachment-python3-pop3-ssl-gmail/8308429#8308429) answer helped me. It looks like your code except that it has some checks to skip over content that doesn't include the attachment. Also, it's common courtesy to edit your question with a solution once you've found one. – Minh Tran Jan 16 '19 at 14:34

2 Answers2

6

Please see a complete example below.

Import poplib and parser

import poplib from email import parser

A function to return a connection to the pop server:

def mail_connection(server='pop.mymailserver.com'):
    pop_conn = poplib.POP3(server)
    pop_conn.user('someuser@server')
    pop_conn.pass_('password')
    return pop_conn

A function to fetch the mail:

def fetch_mail(delete_after=False):
    pop_conn = mail_connection() 
    messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
    messages = ["\n".join(mssg[1]) for mssg in messages]
    messages = [parser.Parser().parsestr(mssg) for mssg in messages]
    if delete_after == True:
        delete_messages = [pop_conn.dele(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
    pop_conn.quit()
    return messages

Then a function to save the attachments as files. NB, the allowed mimetypes; you could have a list of them, such as:

allowed_mimetypes = ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]

and so on.

def get_attachments():
    messages = fetch_mail()
    attachments = []
    for msg in messages:
        for part in msg.walk():
            if part.get_content_type() in allowed_mimetypes:
                name = part.get_filename()
                data = part.get_payload(decode=True)
                f = open(name,'wb')
                f.write(data)
                f.close()
                attachments.append(name)
    return attachments
Danilo Toro
  • 569
  • 2
  • 15
torrange
  • 81
  • 1
  • 5
3

I know this is an old question, but just in case: The value you're passing to email.message_from_string is actually a list of the contents of the email, where each element is a line. You need to join it up to get a string representation of that email:

mail = email.message_from_string("".join(msg))
Harel
  • 1,989
  • 3
  • 26
  • 44