Skip to main content
03 September, 2025
# Topics

Python: Connect to Mailbox, Download Email Attachments and move email to different folder

03 September, 2025

The script connects to an IMAP email inbox, searches through all emails, and downloads attachments from each message. It then organizes the attachments into folders based on the sender’s address. Finally, after processing, it moves the emails to a Processed folder and deletes them from the inbox.

Benefits / Use Cases

  • Automatically saves email attachments to a local folder.
  • Organizes attachments by sender.
  • Keeps inbox clean by moving processed emails to a “Processed” folder.
  • Helps with workflows where multiple people send in files (e.g., clients sending forms, reports, or invoices).

Notes / Limitations

  • The SMTP server needs to be updated.
  • Only processes the Inbox (ignores other folders).
  • Relies on utf-8 decoding (may break on non-UTF emails).
  • Assumes every attachment should be downloaded — no filtering by type/size.

Detailed Breakdown

1. Setup & Imports

import imaplib, ssl, email, os
from pathlib import Path
from getpass import getpass
  • Uses Python’s standard libraries for IMAP email (imaplib), SSL security, parsing emails, and filesystem handling.
  • getpass is used so the password isn’t shown in plain text when typed.

2. Configuration

FOLDER_PATH = r'J:\Folder\Location'
  • This is the base directory where email attachments will be downloaded.

3. User Login

email_user = input('Email:') 
email_pass = getpass()
  • Asks the user to enter their email and password interactively.
mail = imaplib.IMAP4_SSL("smtp.server.com", port=993, ssl_context=context)
mail.login(email_user, email_pass)
  • Connects to the email server securely using IMAP over SSL.
  • Logs into the mailbox.

4. Select Inbox & Get Messages

mail.select('Inbox')
type, data = mail.search(None, 'ALL')
  • Selects the Inbox.
  • Searches for all messages (ALL).

5. Process Each Email

for id in data[0].split():
    type, data = mail.fetch(id, '(RFC822)')
    raw_email = data[0][1]
    raw_email_string = raw_email.decode('utf-8')
    email_message = email.message_from_string(raw_email_string)
  • Iterates through each email.
  • Downloads the entire message (RFC822).
  • Converts the raw bytes into a readable email object.

6. Download Attachments

for part in email_message.walk():
    if part.get_content_maintype() == 'multipart': continue
    if part.get('Content-Disposition') is None: continue
    fileName = part.get_filename()
  • Walks through each part of the email.
  • Skips parts that aren’t attachments.
  • Extracts the filename if there’s an attachment.
sender = email_message['From'] 
sender = sender.replace('<', '').replace('>', '')
tpath = FOLDER_PATH + '\\' + str(sender)
Path(tpath).mkdir(parents=True, exist_ok=True)
  • Creates a subfolder named after the sender’s email address.
filePath = os.path.join(tpath, fileName)
if not os.path.isfile(filePath):
    with open(filePath, 'wb') as fp:
        fp.write(part.get_payload(decode=True))
  • If the attachment isn’t already saved, it writes it to disk.
subject = str(email_message).split("Subject: ", 1)[1].split("\nTo:", 1)[0]
print('Downloaded "{file}" from email titled "{subject}".'.format(file=fileName, subject=subject))
  • Prints a confirmation message with the attachment filename and email subject.

7. Move Processed Emails

for i in mylist:
    mail.copy(i, 'INBOX.Processed')
    mail.store(i, '+FLAGS', '\\Deleted')            
mail.expunge()
  • After processing, the script:
    1. Copies each processed email to the folder INBOX.Processed.
    2. Marks the email as deleted from Inbox.
    3. Permanently removes them with expunge().

Python Script:

import imaplib, ssl, email, os
from pathlib import Path
from getpass import getpass


# Set folder where email attachments are to donwload
FOLDER_PATH = r'J:\Folder\location'

#Inbox details for email
email_user = input('Email:') 
email_pass = getpass()
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
mail = imaplib.IMAP4_SSL("smtp.server.com", port=993,ssl_context=context)

# Login to email
mail.login(email_user, email_pass)

#Select Inbox Folder
mail.select('Inbox')

type, data = mail.search(None, 'ALL')
mail_ids = data[0]
id_list = mail_ids.split()
mylist = []

for id in data[0].split():
    type, data = mail.fetch(id, '(RFC822)' )
    raw_email = data[0][1]
    #convert byte literal to string removing b'
    raw_email_string = raw_email.decode('utf-8')
    email_message = email.message_from_string(raw_email_string)
    #download attachments
    for part in email_message.walk():
        if part.get_content_maintype() == 'multipart':
            continue
        if part.get('Content-Disposition') is None:
            continue
        fileName = part.get_filename()
        if id in mylist:
            pass
        else:
            mylist.append(id)
        if bool(fileName):
            sender = email_message['From'] 
            sender = sender.replace('<', '').replace('>', '')
            tpath = FOLDER_PATH + '\\' + str(sender) #Set folder with sender name and email
            Path(tpath).mkdir(parents=True, exist_ok=True)
            filePath = os.path.join(tpath, fileName)
            if not os.path.isfile(filePath):
                fp = open(filePath, 'wb')
                fp.write(part.get_payload(decode=True))
                fp.close()
            subject = str(email_message).split("Subject: ", 1)[1].split("\nTo:", 1)[0]
            print('Downloaded "{file}" from email titled "{subject}".'.format(file=fileName, subject=subject))

#Move emails to Processed folder
for i in mylist:
    mail.copy(i, 'INBOX.Processed')
    mail.store(i, '+FLAGS', '\\Deleted')            
mail.expunge()