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-8decoding (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. getpassis 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:
- Copies each processed email to the folder
INBOX.Processed. - Marks the email as deleted from Inbox.
- Permanently removes them with
expunge().
- Copies each processed email to the folder
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()