杰瑞科技汇

Python imaplib如何高效操作邮箱?

Of course! Using Python's built-in imaplib library is the standard way to interact with IMAP (Internet Message Access Protocol) email servers. It allows you to programmatically check, search, fetch, and manage emails in your inbox.

Python imaplib如何高效操作邮箱?-图1
(图片来源网络,侵删)

This guide will walk you through the process step-by-step, from connecting to the server to fetching and parsing emails.

What is IMAP?

First, a quick primer:

  • IMAP (Internet Message Access Protocol) is a protocol for accessing email on a remote server.
  • Unlike POP3 (which downloads emails to your local machine and often deletes them from the server), IMAP keeps emails on the server and allows you to manage them (read, delete, move, flag) from multiple devices.
  • This makes it ideal for Python scripts that need to interact with a live mailbox.

Step 1: The Essentials - Connecting and Logging In

Before you can do anything, you need to establish a secure connection to your email provider's IMAP server and authenticate.

Important: Always use SSL/TLS to secure your connection. Most providers now require this.

Python imaplib如何高效操作邮箱?-图2
(图片来源网络,侵删)

Common IMAP Server Ports:

  • SSL/TLS (Recommended): Port 993
  • STARTTLS (Less common now): Port 143

Here's a basic connection and login template:

import imaplib
import email
from email.header import decode_header
# --- Configuration ---
# Replace with your email provider's IMAP server
IMAP_SERVER = "imap.gmail.com"  # Example for Gmail
IMAP_PORT = 993
# Replace with your credentials
# For Gmail, you might need to use an "App Password" if 2FA is enabled
EMAIL_ACCOUNT = "your_email@gmail.com"
EMAIL_PASSWORD = "your_app_password_or_real_password"
def connect_to_mailbox():
    """Connects to the IMAP server and logs in."""
    try:
        # Create an IMAP4_SSL object to connect securely
        mail = imaplib.IMAP4_SSL(IMAP_SERVER, IMAP_PORT)
        # Login to your account
        mail.login(EMAIL_ACCOUNT, EMAIL_PASSWORD)
        print("Successfully logged in!")
        # Select the mailbox you want to work with (e.g., 'INBOX')
        mail.select('inbox')
        return mail
    except imaplib.IMAP4.error as e:
        print(f"IMAP Error: {e}")
        return None
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
        return None
# --- Usage ---
if __name__ == "__main__":
    my_mail = connect_to_mailbox()
    if my_mail:
        # Don't forget to logout when you're done!
        my_mail.logout()

Step 2: Searching for Emails

IMAP has a powerful search mechanism. You can search by criteria like sender, subject, date, and whether an email has been read.

The mail.search(None, 'criteria') method is used.

  • The first argument is usually None or imaplibCharset.
  • The second argument is the search criteria.

Common Search Criteria:

  • 'UNSEEN': Unread emails.
  • 'SEEN': Read emails.
  • 'FROM "sender@example.com"': From a specific sender.
  • 'SUBJECT "your keyword"': Emails with a specific keyword in the subject.
  • 'BEFORE "01-Jan-2025"': Emails received before a certain date.
  • 'SINCE "01-Jan-2025"': Emails received after a certain date.
  • '(UNSEEN FROM "boss@company.com")': Combining criteria (AND logic).

Note: The search returns a byte string of email UIDs, separated by spaces.

Python imaplib如何高效操作邮箱?-图3
(图片来源网络,侵删)
def search_emails(mail, search_criteria):
    """Searches for emails based on the given criteria."""
    status, data = mail.search(None, search_criteria)
    if status != 'OK':
        print("Email search failed.")
        return []
    # data[0] is a byte string of space-separated UIDs
    # We split it to get a list of UIDs
    email_ids = data[0].split()
    print(f"Found {len(email_ids)} emails matching the criteria.")
    return email_ids
# --- Usage ---
if __name__ == "__main__":
    my_mail = connect_to_mailbox()
    if my_mail:
        # Find all unread emails
        unread_ids = search_emails(my_mail, 'UNSEEN')
        # Find emails from a specific sender
        # sender_ids = search_emails(my_mail, 'FROM "news@python.org"')
        my_mail.logout()

Step 3: Fetching Email Content

Once you have a list of email UIDs, you can fetch the content of a specific email using mail.fetch(uid, '(RFC822)').

  • 'RFC822' is a standard that fetches the entire raw email message.
  • The result is a complex structure, but the email body is usually in data[0][1].
def fetch_email_by_id(mail, email_id):
    """Fetches and parses a single email by its ID."""
    status, data = mail.fetch(email_id, '(RFC822)')
    if status != 'OK':
        print(f"Failed to fetch email {email_id}.")
        return None
    # The raw email content is in data[0][1]
    raw_email = data[0][1]
    # Parse the raw email string into an email message object
    email_message = email.message_from_bytes(raw_email)
    return email_message
# --- Usage ---
if __name__ == "__main__":
    my_mail = connect_to_mailbox()
    if my_mail:
        unread_ids = search_emails(my_mail, 'UNSEEN')
        if unread_ids:
            # Fetch the first unread email
            first_email_id = unread_ids[0]
            email_msg = fetch_email_by_id(my_mail, first_email_id)
            if email_msg:
                print("\n--- Email Fetched ---")
                print(f"From: {get_email_header(email_msg, 'From')}")
                print(f"Subject: {get_email_header(email_msg, 'Subject')}")
                print(f"Date: {get_email_header(email_msg, 'Date')}")
                print("-" * 20)
                # Get the body
                body = get_email_body(email_msg)
                print("Body:")
                print(body[:500] + "...") # Print first 500 chars
        my_mail.logout()

Step 4: Parsing the Email (The Fun Part)

An email can have a complex structure with multiple parts (plain text, HTML, attachments). The email library is essential here.

Helper Functions for Parsing

Here are some robust helper functions to handle common tasks like decoding headers and extracting the body.

def get_email_header(msg, header):
    """Decodes and returns a specific email header."""
    value = msg.get(header, '')
    decoded_value = decode_header(value)[0][0]
    if isinstance(decoded_value, bytes):
        # Decode bytes to string using UTF-8, with a fallback
        return decoded_value.decode('utf-8', errors='ignore')
    return decoded_value
def get_email_body(msg):
    """Extracts the body text from an email message object."""
    if msg.is_multipart():
        # If it's a multipart email, iterate through its parts
        for part in msg.walk():
            content_type = part.get_content_type()
            content_disposition = str(part.get("Content-Disposition"))
            # Find the plain text part
            if content_type == "text/plain" and "attachment" not in content_disposition:
                try:
                    body = part.get_payload(decode=True).decode()
                    return body
                except:
                    continue
    else:
        # If it's not multipart, just get the payload
        try:
            body = msg.get_payload(decode=True).decode()
            return body
        except:
            pass
    return "Could not decode email body."
def get_email_attachments(msg):
    """Finds and returns a list of attachment filenames."""
    attachments = []
    for part in msg.walk():
        content_disposition = str(part.get("Content-Disposition"))
        if "attachment" in content_disposition:
            filename = part.get_filename()
            if filename:
                attachments.append(filename)
    return attachments

Complete Example: Find and Read an Email

Here is a full script that combines all the steps to find an email from a specific sender, print its subject, and save its attachments.

import imaplib
import email
from email.header import decode_header
import os
# --- Configuration ---
IMAP_SERVER = "imap.gmail.com"
IMAP_PORT = 993
EMAIL_ACCOUNT = "your_email@gmail.com"
EMAIL_PASSWORD = "your_app_password"
SEARCH_SENDER = "news@python.org" # Example: Python.org newsletter
SAVE_ATTACHMENTS_TO = "attachments"
# --- Helper Functions (from above) ---
def get_email_header(msg, header):
    value = msg.get(header, '')
    decoded_value = decode_header(value)[0][0]
    return decoded_value.decode('utf-8', errors='ignore') if isinstance(decoded_value, bytes) else decoded_value
def get_email_body(msg):
    if msg.is_multipart():
        for part in msg.walk():
分享:
扫描分享到社交APP
上一篇
下一篇