Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
279: Reading Emails with imaplib
A few years ago, I was tasked with automating a data pipeline for a client who relied on a legacy mainframe system. The mainframe couldn't talk to a modern API, but it could send emails. Every morning at 4:00 AM, it would blast out a series of reports as CSV attachments. My job was to grab those files and load them into a database before the business analysts started their day. I spent a whole afternoon trying to find a "modern" library for this, only to realize that the old-school imaplib is still the industry standard for this kind of work. It's a bit clunky, but it's reliable.
Talking to the Mail Server
To get started, you'll need to establish a secure connection. We use imaplib.IMAP4_SSL because, frankly, sending your email password over an unencrypted connection in the 21st century is a disaster waiting to happen. Once connected, you log in and select the folder you want to browse—usually the "INBOX".
The trickiest part is often the search. IMAP uses a specific search syntax that feels more like a query language than Python. If you want to find emails from a specific sender or with a specific keyword in the subject, you pass those criteria into the search() method. Keep in mind that search() returns a list of message IDs, not the emails themselves. You're essentially getting a list of "addresses" for the messages you actually want to read.
import imaplib
import email
# Connect to the server
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('your_email@gmail.com', 'your_app_password')
mail.select('inbox')
# Search for emails from a specific report bot
status, data = mail.search(None, '(FROM "reports@company.com" SUBJECT "Daily Summary")')
mail_ids = data[0].split()
if mail_ids:
# Get the latest email ID
latest_id = mail_ids[-1]
status, data = mail.fetch(latest_id, '(RFC822)')
raw_email = data[0][1]
else:
print("No matching emails found.")
Parsing the Multipart Mess
Here is where most developers get stuck. imaplib fetches the email as a raw byte string. If you print raw_email from the code above, it looks like a nightmare of headers, boundary markers, and encoded text. To make sense of this, we hand that raw data over to the email module.
Emails are often "multipart," meaning they contain a plain text version, an HTML version, and potentially attachments. I always recommend using the walk() method. This allows you to iterate through every part of the email and check the get_content_type(). If you're looking for the body of the message, you're usually hunting for text/plain. If you need a file, you're looking for application/octet-stream or similar.
# Convert raw bytes to a Message object
msg = email.message_from_bytes(raw_email)
# Extract basic headers
print(f"From: {msg['From']}")
print(f"Subject: {msg['Subject']}")
# Iterate through the email parts to find the body
for part in msg.walk():
if part.get_content_type() == 'text/plain':
body = part.get_payload(decode=True).decode()
print(f"Body: {body}")
elif part.get_content_maintype() == 'multipart':
continue
elif part.get_filename():
print(f"Found attachment: {part.get_filename()}")
One quick word of advice: if you're using Gmail or Outlook, you can't just use your regular password. You'll need to generate an "App Password" in your account settings. I've wasted an hour of my life fighting "Authentication Failed" errors only to realize my two-factor authentication was blocking the script. Save yourself that headache.
📋 Practical Task
Project: Automated Invoice Subject Scraper
You have been asked to build a tool that audits an inbox for incoming invoices. Your goal is to create a script that connects to an IMAP server and identifies all emails that have the word "Invoice" in the subject line.
Requirements:
- Connect to your email provider using
imaplib.IMAP4_SSL. - Search the "INBOX" for all messages where the subject contains "Invoice".
- For every matching email found, print the Sender's Email Address and the Date the email was sent.
- Ensure the script handles the case where no matching emails are found without crashing.
Note: Use an App Password if your provider requires two-factor authentication.
There are no comments for now.