복붙노트

[PYTHON] imaplib을 사용하여 여러 첨부 파일 다운로드

PYTHON

imaplib을 사용하여 여러 첨부 파일 다운로드

imaplib을 사용하여 단일 메일에서 여러 첨부 파일을 다운로드하려면 어떻게합니까?

전자 메일을 가지고 있는데 그 전자 메일에 첨부 파일이 4 개 있다고 가정 해 봅시다. 첨부 파일을 모두 다운로드하려면 어떻게해야합니까? 아래 코드는 전자 메일에서 단 하나의 첨부 파일 만 다운로드합니다.

detach_dir = 'c:/downloads'
m = imaplib.IMAP4_SSL("imap.gmail.com")
m.login('hello@gmail.com','3323434')
m.select("[Gmail]/All Mail")

resp, items = m.search(None, "(UNSEEN)")
items = items[0].split()

for emailid in items:
    resp, data = m.fetch(emailid, "(RFC822)") 
    email_body = data[0][1] 
    mail = email.message_from_string(email_body) 
    temp = m.store(emailid,'+FLAGS', '\\Seen')
    m.expunge()

    if mail.get_content_maintype() != 'multipart':
        continue

    print "["+mail["From"]+"] :" + mail["Subject"]

    for part in mail.walk():
        if part.get_content_maintype() == 'multipart':
            continue
        if part.get('Content-Disposition') is None:
            continue

        filename = part.get_filename()
        att_path = os.path.join(detach_dir, filename)

        if not os.path.isfile(att_path) :
            fp = open(att_path, 'wb')
            fp.write(part.get_payload(decode=True))
            fp.close()
            return HttpResponse('check folder')

해결법

  1. ==============================

    1.미래의 파이썬 여행자들에게. 다음은 이메일에서 발견 된 첨부 파일을 다운로드하여 특정 위치에 저장하는 클래스입니다.

    미래의 파이썬 여행자들에게. 다음은 이메일에서 발견 된 첨부 파일을 다운로드하여 특정 위치에 저장하는 클래스입니다.

    import email
    import imaplib
    import os
    
    class FetchEmail():
    
        connection = None
        error = None
    
        def __init__(self, mail_server, username, password):
            self.connection = imaplib.IMAP4_SSL(mail_server)
            self.connection.login(username, password)
            self.connection.select(readonly=False) # so we can mark mails as read
    
        def close_connection(self):
            """
            Close the connection to the IMAP server
            """
            self.connection.close()
    
        def save_attachment(self, msg, download_folder="/tmp"):
            """
            Given a message, save its attachments to the specified
            download folder (default is /tmp)
    
            return: file path to attachment
            """
            att_path = "No attachment found."
            for part in msg.walk():
                if part.get_content_maintype() == 'multipart':
                    continue
                if part.get('Content-Disposition') is None:
                    continue
    
                filename = part.get_filename()
                att_path = os.path.join(download_folder, filename)
    
                if not os.path.isfile(att_path):
                    fp = open(att_path, 'wb')
                    fp.write(part.get_payload(decode=True))
                    fp.close()
            return att_path
    
        def fetch_unread_messages(self):
            """
            Retrieve unread messages
            """
            emails = []
            (result, messages) = self.connection.search(None, 'UnSeen')
            if result == "OK":
                for message in messages[0].split(' '):
                    try: 
                        ret, data = self.connection.fetch(message,'(RFC822)')
                    except:
                        print "No new emails to read."
                        self.close_connection()
                        exit()
    
                    msg = email.message_from_bytes(data[0][1])
                    if isinstance(msg, str) == False:
                        emails.append(msg)
                    response, data = self.connection.store(message, '+FLAGS','\\Seen')
    
                return emails
    
            self.error = "Failed to retreive emails."
            return emails
    
        def parse_email_address(self, email_address):
            """
            Helper function to parse out the email address from the message
    
            return: tuple (name, address). Eg. ('John Doe', 'jdoe@example.com')
            """
            return email.utils.parseaddr(email_address)
    
  2. ==============================

    2.코드를 다시 작성하여 기능으로 분해했습니다. 나는 PEEK를 사용하여 전자 메일 메시지의 UNREAD 상태를 변경하지 않습니다.

    코드를 다시 작성하여 기능으로 분해했습니다. 나는 PEEK를 사용하여 전자 메일 메시지의 UNREAD 상태를 변경하지 않습니다.

    @ 존과 비슷한 문제에 대한 필자의 글을 게시하고 있지만 클래스 대신 함수 만 사용합니다.

    import imaplib
    import email
    
    # Connect to an IMAP server
    def connect(server, user, password):
        m = imaplib.IMAP4_SSL(server)
        m.login(user, password)
        m.select()
        return m
    
    # Download all attachment files for a given email
    def downloaAttachmentsInEmail(m, emailid, outputdir):
        resp, data = m.fetch(emailid, "(BODY.PEEK[])")
        email_body = data[0][1]
        mail = email.message_from_string(email_body)
        if mail.get_content_maintype() != 'multipart':
            return
        for part in mail.walk():
            if part.get_content_maintype() != 'multipart' and part.get('Content-Disposition') is not None:
                open(outputdir + '/' + part.get_filename(), 'wb').write(part.get_payload(decode=True))
    
    # Download all the attachment files for all emails in the inbox.
    def downloadAllAttachmentsInInbox(server, user, password, outputdir):
        m = connect(server, user, password)
        resp, items = m.search(None, "(ALL)")
        items = items[0].split()
        for emailid in items:
            downloaAttachmentsInEmail(m, emailid, outputdir)
    
  3. ==============================

    3.fp.close () 바로 다음에 반환 (어쩌면 오타가 아닌)을 제외하고 코드는 괜찮아 보입니다.

    fp.close () 바로 다음에 반환 (어쩌면 오타가 아닌)을 제외하고 코드는 괜찮아 보입니다.

    ...
    fp.write(part.get_payload(decode=True))
    fp.close()
    return HttpResponse('check folder')
    

    첫 번째 첨부 파일을 저장하면 함수에서 반환됩니다. 해당 줄을 주석으로 처리하고 문제가 해결되는지 확인하십시오.

  4. ==============================

    4.

    * You can try following function to get mail attachment
    
    def create_message_attachment(self,msg_str):
            count = 1
            body = ''
            content_id = ''
            for part in msg_str.walk():
                file_name_gl = None
                mptype = part.get_content_maintype()
                file_name_gl = part.get_filename()
                if mptype == "multipart":
                    continue
                elif mptype == "text":
                    if not file_name_gl: continue
                elif mptype == "image":
                    content_id = part.get('Content-ID')
                    if not file_name_gl:
                        file_name_gl = 'image_' + str(count) + '.' + part.get_content_subtype()
                        count = count + 1
    
                body = part.get_payload(decode = True)
                if type(body) <> type(None) :
                    body = body.strip()
                    if body <> "":
                        body = base64.encodestring(body)
    
  5. from https://stackoverflow.com/questions/6225763/downloading-multiple-attachments-using-imaplib by cc-by-sa and MIT license