imap-tools Python Library

repository·master·Indexed 21 days ago

https://github.com/ikvk/imap_tools

A high-level Python library for the IMAP protocol that simplifies message manipulation, folder management, and complex email searching. It requires Python 3.8+ and features a query builder for logical searches, IDLE support for real-time updates, and a MailBox client supporting various authentication methods including login and xoauth2. Key capabilities include fetching MailMessage objects, managing folder status, and performing actions like copying, moving, and deleting emails without external dependencies.

Tokens
2.3K
Snippets
7
Records
9
Agent score
24%

What's inside imap-tools

  1. Overview of imap-tools capabilities

    master

    imap-tools is a high-level Python library for working with email via the IMAP protocol. It requires Python 3.8+ and has no external dependencies.

    Key Features:

    • Message Operations: Fetching messages, working with UIDs and sequence numbers, and accessing parsed email attributes.
    • Query Building: A builder for constructing complex search criteria.
    • Email Actions: Copy, delete, flag, move, and append messages.
    • Folder Management: List, set, get, create, check existence, rename, subscribe, delete, and get status of folders.
    • IDLE Support: Start, poll, stop, and wait for IDLE commands.
    • Error Handling: Specific exceptions for failed IMAP operations.
  2. Build search queries with the Query Builder

    master

    The query builder allows for complex logical searches using AND (alias A), OR (alias O), and NOT (alias N).

    Logical Classes:

    • AND / A: Combine conditions with logical AND.
    • OR / O: Combine conditions with logical OR.
    • NOT / N: Invert a logical expression.
    • Header / H: Search by header key and value.
    • UidRange / U: Search within a UID range.

    Important Note: You cannot nest a NOT inside an A call like A(text='a', NOT(subject='b')). Instead, pass the NOT as a positional argument: A(NOT(subject='b'), text='a').

    Common Search Keys:

    • seen (bool): SEEN/UNSEEN flag.
    • subject (str*): Subject substring (case-insensitive).
    • text (str*): Search in header or body.
    • from_ (str*): Envelope FROM field.
    • date (datetime.date*): Internal date match.
    • size_gt / size_lt (int): Size comparison.
    • header (H(str, str)*): Specific header key/value match.
    from imap_tools import MailBox, A, OR, NOT
    
    with MailBox('imap.mail.com').login('user', 'pwd') as mailbox:
        # AND: subject contains 'cat' AND message is unseen
        mailbox.fetch(A(subject='cat', seen=False))
    
        # OR: header or body contains 'hello' OR date is 2000-3-15
        mailbox.fetch(OR(text='hello', date=datetime.date(2000, 3, 15)))
    
        # NOT: date not in the list
        mailbox.fetch(NOT(OR(date=[dt1, dt2])))
  3. Connect to a mailbox using MailBox

    master

    Use MailBox to create an IMAP client. It supports context manager usage for automatic login and logout. You can use MailBox, MailBoxStartTls, or MailBoxUnencrypted depending on your connection requirements.

    Common authentication methods include login, login_utf8, and xoauth2.

    from imap_tools import MailBox
    
    # Basic usage with context manager
    with MailBox('imap.mail.com').login('test@mail.com', 'pwd') as mailbox:
        # perform actions
        pass
  4. Use the IDLE workflow for real-time updates

    master

    The mailbox.idle manager allows you to wait for real-time mailbox updates.

    Methods:

    • start(): Switch on IDLE mode.
    • poll(timeout=None): Poll for responses.
    • stop(): Switch off IDLE mode.
    • wait(timeout=None): Switch on IDLE, poll for responses, then switch off. Returns responses if any occur within the timeout.
    from imap_tools import MailBox, A
    
    with MailBox('imap.my.moon').login('acc', 'pwd', 'INBOX') as mailbox:
        # Wait for up to 60 seconds for new unseen messages
        responses = mailbox.idle.wait(timeout=60)
        if responses:
            for msg in mailbox.fetch(A(seen=False)):
                print(msg.subject)
        else:
            print('no updates')
  5. Perform email actions (Copy, Move, Delete, Flag, Append)

    master

    Use these methods to manipulate messages. For large numbers of messages, use the chunks argument to avoid server-side command size limits.

    • copy(uid_list, destination_folder): Copy messages.
    • move(uid_list, destination_folder, chunks=None): Move messages.
    • delete(uid_list): Delete messages.
    • flag(uid_list, flags, set_flag=True): Set or unset flags.
    • append(msg, folder, dt=None, flag_set=None): Add a MailMessage to a folder.

    uid_list can be a comma-separated string or a sequence of UIDs.

    from imap_tools import MailBox, A
    
    with MailBox('imap.mail.com').login('user', 'pwd') as mailbox:
        # MOVE all messages to a folder in chunks of 100
        mailbox.move(mailbox.uids(), 'INBOX/folder2', chunks=100)
    
        # DELETE messages containing 'cat' in HTML
        mailbox.delete([msg.uid for msg in mailbox.fetch() if 'cat' in msg.html])
    
        # FLAG unseen messages
        mailbox.flag(mailbox.uids(A(seen=False)), ('\Seen', '\Flagged'), True)
  6. Manage folders with BaseMailBox.folder

    master

    The folder manager provides access to folder operations:

    • list(folder): List subfolders.
    • set(folder): Select a folder.
    • get(): Get the currently selected folder.
    • create(folder): Create a new folder.
    • exists(folder): Check if a folder exists.
    • rename(old_name, new_name): Rename a folder.
    • delete(folder): Delete a folder.
    • status(folder): Get folder status (messages, recent, etc.).
    • subscribe(folder, status=True): Subscribe/unsubscribe.
    with MailBox('imap.mail.com').login('user', 'pwd') as mailbox:
        # Check if folder exists
        if mailbox.folder.exists('INBOX|folder1'):
            # Rename it
            mailbox.folder.rename('INBOX|folder1', 'INBOX|folder2')
    
        # Get status
        stat = mailbox.folder.status('INBOX')
        print(stat) # {'MESSAGES': 41, ...}
  7. Fetch emails using BaseMailBox.fetch

    master

    The fetch() method searches for email UIDs based on criteria and yields MailMessage objects.

    Arguments:

    • criteria: Search criteria (e.g., 'ALL', a query builder object, or a string).
    • charset: Charset for search criteria strings (default: 'US-ASCII').
    • limit: Limit the number of read emails. Can be an int or a slice.
    • mark_seen: If True, marks emails as seen upon fetching (default: True).
    • reverse: If True, returns messages from largest date to smallest (client-side).
    • headers_only: If True, fetches only headers (no text, html, or attachments).
    • bulk: Controls fetch efficiency. False (default) fetches separately (low memory, slow); True fetches all in one command (high memory, fast); int fetches in chunks of the specified size.
    • sort: Server-side sort criteria using SortCriteria constants.
    • uid_list: A specific list of UIDs to fetch. If provided, criteria, charset, and sort are ignored.
    from imap_tools import MailBox
    
    with MailBox('imap.mail.com').login('test@mail.com', 'pwd') as mailbox:
        for msg in mailbox.fetch(limit=10, mark_seen=False):
            print(msg.subject)
  8. Access MailMessage attributes

    master

    When iterating over mailbox.fetch(), you receive MailMessage objects. Key attributes include:

    • uid: Unique identifier (str | None).
    • subject: Email subject.
    • from_: Sender address.
    • to, cc, bcc, reply_to: Tuples of recipient addresses.
    • date: datetime.datetime object.
    • text: Plain text body.
    • html: HTML body.
    • flags: Tuple of flags (e.g., '\Seen', '\Flagged').
    • headers: Dict-like object of email headers.
    • size: Total size of the received message in bytes.
    • attachments: List of MailAttachment objects.

    MailAttachment attributes:

    • filename: Name of the attachment.
    • payload: Attachment content as bytes.
    • content_type: MIME type.
    • size: Size in bytes.

    EmailAddress objects: Fields like from_values, to_values, etc., return EmailAddress objects which have a .full property (e.g., 'Ya <im@ya.ru>').