IMAPCLIENT(7)

๐Ÿ“ฆ
version 3.1.0 ยท 2 versions
, in ubuntu resolute, ubuntu stonking

๐Ÿ’– IMAPCLIENT(7) ๐Ÿ’–

okay bestie, welcome to imapclient(7) โ€” the official IMAPClient documentation, but make it a group chat. everything factual is still here, i promise, i just wrapped it in glitter. let's go ๐Ÿ’…


โœจ NAME โœจ

imapclient โ€” IMAPClient Documentation ๐Ÿฆ‹


๐ŸŒˆ INTRODUCTION ๐ŸŒˆ

IMAPClient is an easy-to-use, Pythonic and complete IMAP client library. it's giving โœจmain character energyโœจ for email code, no cap.

so here's the tea: IMAPClient actually uses the imaplib module from the Python standard library under the hood โ€” but it serves a different API. instead of making you, the caller, do a bunch of extra parsing work, the return values come back fully parsed, readily usable, using sensible Python types. and when problems happen? it raises exceptions. so you don't have to sit there error-checking every return value like it's 2004. ๐Ÿ™ˆ

IMAPClient is straightforward to use, but honestly it helps a lot to have at least a general understanding of the IMAP protocol. RFC 3501 <https://datatracker.ietf.org/doc/html/rfc3501.html> explains IMAP in detail. other RFCs also apply to various extensions to the base protocol, and those get referenced in the documentation below wherever they're relevant. iykyk ๐Ÿ“š

Python versions 3.8 through 3.14 are officially supported. periodt.


๐Ÿš€ GETTING STARTED ๐Ÿš€

install IMAPClient:

$ pip install imapclient

(see Installation <#installation> for more details ๐Ÿ’–)

the core of the IMAPClient API is the IMAPClient class. instantiating this class creates a connection to an IMAP account. then calling methods on your IMAPClient instance interacts with the server. literally that simple.

the following example shows a simple interaction with an IMAP server. it displays the message ID, subject and date of the message for all messages in the INBOX folder:

>>> from imapclient import IMAPClient
>>> server = IMAPClient('imap.mailserver.com', use_uid=True)
>>> server.login('someuser', 'somepassword')
b'[CAPABILITY IMAP4rev1 LITERAL+ SASL-IR [...] LIST-STATUS QUOTA] Logged in'

>>> select_info = server.select_folder('INBOX')
>>> print('%d messages in INBOX' % select_info[b'EXISTS'])
34 messages in INBOX

>>> messages = server.search(['FROM', 'best-friend@domain.com'])
>>> print("%d messages from our best friend" % len(messages))
5 messages from our best friend

>>> for msgid, data in server.fetch(messages, ['ENVELOPE']).items():
>>>     envelope = data[b'ENVELOPE']
>>>     print('ID #%d: "%s" received %s' % (msgid, envelope.subject.decode(), envelope.date))
ID #62: "Our holidays photos" received 2017-07-20 21:47:42
ID #55: "Re: did you book the hotel?" received 2017-06-26 10:38:09
ID #53: "Re: did you book the hotel?" received 2017-06-25 22:02:58
ID #44: "See that fun article about lobsters in Pacific ocean!" received 2017-06-09 09:49:47
ID #46: "Planning for our next vacations" received 2017-05-12 10:29:30

>>> server.logout()
b'Logging out'

ate. ๐Ÿ’…


๐Ÿ“– USER GUIDE ๐Ÿ“–

this section describes how IMAPClient works and gives some examples to help you start. ๐Ÿซถ

๐Ÿ’พ Installation ๐Ÿ’พ

Pip ๐ŸŽ€

IMAPClient can easily be installed with pip:

$ pip install imapclient

From Source ๐Ÿงš

IMAPClient is developed on GitHub โ€” you can find the code at mjs/imapclient <https://github.com/mjs/imapclient>.

you can clone the public repository:

$ git clone https://github.com/mjs/imapclient.git

once you have the sources, simply install IMAPClient with:

$ cd imapclient
$ pip install -e .

Other versions ๐ŸŒธ

the source distributions of all IMAPClient versions are available at <http://menno.io/projects/IMAPClient/>. alternatively you can also use the PyPI page at <https://pypi.python.org/pypi/IMAPClient/>. so many options bestie, choose your fighter โœจ


๐Ÿง  IMAPClient Concepts ๐Ÿง 

๐Ÿ”ข Message Identifiers ๐Ÿ”ข

in the IMAP protocol, messages are identified using an integer. these message ids are specific to a given folder. keep that in mind, it matters.

there are two types of message identifiers in the IMAP protocol:

  • one type is the message sequence number, where the messages in a folder are numbered from 1 to N, where N is the number of messages in the folder. these numbers don't persist between sessions and may be reassigned after some operations such as an expunge. ๐Ÿ˜ญ so fragile.
  • a more convenient approach is Unique Identifiers (UIDs). Unique Identifiers are integers assigned to each message by the IMAP server that will persist across sessions. they do not change when folders are expunged. almost all IMAP servers support UIDs. slay. ๐Ÿ‘‘

each call to the IMAP server can use either message sequence numbers or UIDs in the command arguments and return values. the client specifies to the server which type of identifier should be used. you can set whether IMAPClient should use UIDs or message sequence number via the use_uid argument passed when an IMAPClient instance is created, and via the use_uid attribute. the use_uid attribute can be used to change the message id type between calls to the server. IMAPClient uses UIDs by default. ๐Ÿ’–

any method that accepts message ids takes either:

  • a sequence containing message ids (eg. [1,2,3]), or
  • a single message id integer, or
  • a string representing sets and ranges of messages as supported by the IMAP protocol (e.g. '50-65', '2:*' or '2,4:7,9,12:*').

๐Ÿท๏ธ Message Flags ๐Ÿท๏ธ

an IMAP server keeps zero or more flags for each message. these indicate certain properties of the message, or they can be used by IMAP clients to keep track of data related to a message.

the IMAPClient package has constants for a number of commonly used flags:

DELETED = br'\Deleted'
SEEN = br'\Seen'
ANSWERED = br'\Answered'
FLAGGED = br'\Flagged'
DRAFT = br'\Draft'
RECENT = br'\Recent'         # This flag is read-only
heads up bestie: RECENT is read-only. don't try to set it, it's not that kind of flag ๐Ÿ’€

any method that accepts message flags takes either a sequence containing message flags (eg. [DELETED, 'foo', 'Bar']) or a single message flag (eg. 'Foo').

๐Ÿ”ค Folder Name Encoding ๐Ÿ”ค

any method that takes a folder name will accept a standard string or a unicode string. unicode strings will be transparently encoded using modified UTF-7 as specified by RFC 3501 Section 5.1.3 <https://datatracker.ietf.org/doc/html/rfc3501.html#section-5.1.3>. this allows for arbitrary unicode characters (eg. non-English characters) to be used in folder names. ๐ŸŒโœจ

the ampersand character ("&") has special meaning in IMAP folder names. IMAPClient automatically escapes and unescapes this character so that the caller doesn't have to. we love not having to do things manually ๐Ÿซถ

automatic folder name encoding and decoding can be enabled or disabled with the folder_encode attribute. it defaults to True.

  • if folder_encode is True, all folder names returned by IMAPClient are always returned as unicode strings.
  • if folder_encode is False, folder names are returned as str (Python 2) or bytes (Python 3).

๐Ÿ“ฌ Working With Fetched Messages ๐Ÿ“ฌ

the IMAP protocol gives access to a limited amount of information about emails stored on the server. in-depth analysis of a message usually requires downloading the full message and parsing its content. ๐Ÿ˜ค

the email <https://docs.python.org/3/library/email.html> package of the Python standard library provides a reliable way to transform a raw email into a convenient object:

# Download unread emails and parse them into standard EmailMessage objects
import email

from imapclient import IMAPClient

HOST = "imap.host.com"
USERNAME = "someuser"
PASSWORD = "secret"

with IMAPClient(HOST) as server:
    server.login(USERNAME, PASSWORD)
    server.select_folder("INBOX", readonly=True)

    messages = server.search("UNSEEN")
    for uid, message_data in server.fetch(messages, "RFC822").items():
        email_message = email.message_from_bytes(message_data[b"RFC822"])
        print(uid, email_message.get("From"), email_message.get("Subject"))

๐Ÿ” TLS/SSL ๐Ÿ”

IMAPClient uses sensible TLS parameter defaults for encrypted connections, and it also allows for a high level of control of TLS parameters if you need it. it uses the built-in ssl package, provided since Python 2.7.9 and 3.4.

TLS parameters are controlled by passing a ssl.SSLContext when creating an IMAPClient instance (or to the starttls method when the STARTTLS is used). when ssl=True is used without passing a SSLContext, a default context is used. the default context avoids the use of known insecure ciphers and SSL protocol versions, with certificate verification and hostname verification turned on. the default context will use system installed certificate authority trust chains, if available. ๐Ÿ’…

when constructing a custom context it is usually best to start with the default context, created by the ssl module, and modify it to suit your needs.

the following example shows how to disable certification verification and certificate host name checks if required:

# Establish an encrypted connection to a server without checking its
# certificate. This setup is insecure, DO NOT USE to connect to servers
# over the Internet.

import ssl

from imapclient import IMAPClient

HOST = "imap.host.com"
USERNAME = "someuser"
PASSWORD = "secret"

ssl_context = ssl.create_default_context()

# don't check if certificate hostname doesn't match target hostname
ssl_context.check_hostname = False

# don't check if the certificate is trusted by a certificate authority
ssl_context.verify_mode = ssl.CERT_NONE

with IMAPClient(HOST, ssl_context=ssl_context) as server:
    server.login(USERNAME, PASSWORD)
    # ...do something...
๐Ÿšจ bestie, listen to me: that setup is insecure. DO NOT USE it to connect to servers over the Internet. i'm serious. ๐Ÿ™…โ€โ™€๏ธ

the next example shows how to create a context that will use a custom CA certificate. this is required to perform verification of a self-signed certificate used by the IMAP server:

# Establish a secure connection to a server that does not have a certificate
# signed by a trusted certificate authority (CA).

import ssl

from imapclient import IMAPClient

HOST = "imap.host.com"
USERNAME = "someuser"
PASSWORD = "secret"

ssl_context = ssl.create_default_context(cafile="/path/to/cacert.pem")

with IMAPClient(HOST, ssl_context=ssl_context) as server:
    server.login(USERNAME, PASSWORD)
    # ...do something...

if your operating system comes with an outdated list of CA certificates, you can use the certifi <https://pypi.python.org/pypi/certifi> package that provides an up-to-date set of trusted CAs:

import certifi

ssl_context = ssl.create_default_context(cafile=certifi.where())

if the server supports it, you can also authenticate using a client certificate:

import ssl
ssl_context = ssl.create_default_context()
ssl_context.load_cert_chain("/path/to/client_certificate.crt")

ok so those are some of the most common TLS parameter customisations bestie, but the way that there are many other tweaks possible?? ๐Ÿฆ‹ it's giving options galore. Consult the Python 3 ssl package documentation for further options, she ate fr fr ๐Ÿ’…


Logging ๐ŸŒธ

IMAPClient logs debug lines using the standard Python logging module. Its logger prefix is imapclient. โ€” that's the little name tag she wears at the party ๐ŸŽ€

One way to see debug messages from IMAPClient is to set up logging like this:

import logging

logging.basicConfig(
    format='%(asctime)s - %(levelname)s: %(message)s',
    level=logging.DEBUG
)

For advanced usage, please refer to the documentation logging module. (iykyk โ€” the logging module docs are right there when you need the deep lore ๐Ÿ“š)


Advanced Usage ๐Ÿ‘‘

This document covers some more advanced features and tips for handling specific usages. Main character energy only, bestie โœจ

Cleaning Up Connections ๐Ÿงน

To communicate with the server, IMAPClient establishes a TCP connection. It is important for long-lived processes to always close connections at some point to avoid leaking memory and file descriptors ๐Ÿ˜ญ โ€” no cap, this one matters. This is usually done with the logout method:

import imapclient

c = imapclient.IMAPClient(host="imap.foo.org")
c.login("bar@foo.org", "passwd")
c.select_folder("INBOX")
c.logout()

However if an error is raised when selecting the folder, the connection may be left open ๐Ÿ™ˆ โ€” not slay. So:

IMAPClient may be used as a context manager that automatically closes connections when they are not needed any more:

import imapclient

with imapclient.IMAPClient(host="imap.foo.org") as c:
    c.login("bar@foo.org", "passwd")
    c.select_folder("INBOX")

periodt. clean. iconic. ๐Ÿ’–

Watching a Mailbox Using IDLE ๐Ÿ’ค

The IDLE extension allows an IMAP server to notify a client when something changes in a mailbox. It can be used as an alternative to polling to receive new messages. (polling is so 2010, we do push notifications now bestie ๐Ÿ’…)

The concept is simple: the client connects to the server, selects a mailbox and enters the IDLE mode. At this point the server sends notifications whenever something happens in the selected mailbox until the client ends the IDLE mode by issuing a DONE command. This is explained in RFC 2177 (https://datatracker.ietf.org/doc/html/rfc2177.html). ๐Ÿฆ‹

# Open a connection in IDLE mode and wait for notifications from the
# server.

from imapclient import IMAPClient

HOST = "imap.host.com"
USERNAME = "someuser"
PASSWORD = "password"

server = IMAPClient(HOST)
server.login(USERNAME, PASSWORD)
server.select_folder("INBOX")

# Start IDLE mode
server.idle()
print("Connection is now in IDLE mode, send yourself an email or quit with ^c")

while True:
    try:
        # Wait for up to 30 seconds for an IDLE response
        responses = server.idle_check(timeout=30)
        print("Server sent:", responses if responses else "nothing")
    except KeyboardInterrupt:
        break

server.idle_done()
print("\nIDLE mode done")
server.logout()
heads up bestie ๐Ÿšจ Note that IMAPClient does not handle low-level socket errors that can happen when maintaining long-lived TCP connections. Users are advised to renew the IDLE command every 10 minutes to avoid the connection from being abruptly closed. ๐Ÿ’€ don't let your connection ghost you.

Interactive Sessions ๐ŸŽฎ

When developing program using IMAPClient is it sometimes useful to have an interactive shell to play with. IMAPClient ships with a module that lets you fire up an interactive shell with an IMAPClient instance connected to an IMAP server. it's giving sandbox, it's giving playground, we love her ๐ŸŒˆ

Start a session like this:

python -m imapclient.interact -H <host> -u <user> ...

Various options are available to specify the IMAP server details. See the help (--help) for more details. You'll be prompted for a username and password if one isn't provided on the command line. ๐Ÿซถ

It is also possible to pass connection details as a configuration file like this:

python -m imapclient.interact -f <config file>

See below for details of the configuration file format. ๐Ÿ“

If installed, IPython will be used as the embedded shell. Otherwise the basic built-in Python shell will be used. (either way you're eating good โœจ)

The connected IMAPClient instance is available as the variable "c". Here's an example session:

$ python -m imapclient.interact -H <host> -u <user> ...
Connecting...
Connected.

IMAPClient instance is "c"
In [1]: c.select_folder('inbox')
Out[1]:
{b'EXISTS': 2,
 b'FLAGS': (b'\\Answered',
     b'\\Flagged',
     b'\\Deleted',
     b'\\Seen',
     b'\\Draft'),
 b'PERMANENTFLAGS': (b'\\Answered',
     b'\\Flagged',
     b'\\Deleted',
     b'\\Seen',
     b'\\Draft'),
 b'READ-WRITE': True,
 b'RECENT': 0,
 b'UIDNEXT': 1339,
 b'UIDVALIDITY': 1239278212}

In [2]: c.search()
Out[2]: [1123, 1233]

In [3]: c.logout()
Out[3]: b'Logging out'

Configuration File Format ๐Ÿ“„

Both the IMAPClient interactive shell and the live tests take configuration files which specify how to to connect to an IMAP server. The configuration file format is the same for both. one format to rule them all, iconic behavior ๐Ÿ‘‘

Configuration files use the INI format and must always have a section called DEFAULT. Here's a simple example:

[DEFAULT]
host = imap.mailserver.com
username = bob
password = sekret
ssl = True

don't forget the DEFAULT section bestie, she's mandatory ๐Ÿ’–

The supported options are:

  • host โ€” string โ€” the IMAP hostname to connect to. ๐Ÿฆ‹
  • username โ€” string โ€” the username to authenticate as.
  • password โ€” string โ€” the password to use with username.
  • port โ€” int โ€” server port to connect to. Defaults to 143 unless ssl is True.
  • ssl โ€” bool โ€” use SSL/TLS to connect. ๐Ÿ”’
  • starttls โ€” bool โ€” use STARTTLS to connect.
  • ssl_check_hostname โ€” bool โ€” if true and SSL is in use, check that certificate matches the hostname (defaults to true).
  • ssl_verify_cert โ€” bool โ€” if true and SSL is in use, check that the certificate is valid (defaults to true).
  • ssl_ca_file โ€” string โ€” if SSL is true, use this to specify certificate authority certs to validate with.
  • timeout โ€” int โ€” time out I/O operations after this many seconds. โฐ
  • oauth2 โ€” bool โ€” if true, use OAUTH2 to authenticate (username and password are ignored).
  • oauth2_client_id โ€” string โ€” OAUTH2 client id.
  • oauth2_client_secret โ€” string โ€” OAUTH2 client secret. ๐Ÿคซ
  • oauth2_refresh_token โ€” string โ€” OAUTH2 token for refreshing the secret.

Acceptable boolean values are "1", "yes", "true", and "on", for true; and "0", "no", "false", and "off", for false. Memorise these, bestie, they're literally the vibe check for every bool in this whole thing. ๐Ÿ’…


๐ŸŒˆ API REFERENCE ๐ŸŒˆ

This section describes public functions and classes of IMAPClient library. Public means it's for you โ€” go off, touch it, use it. โœจ

๐ŸŽ€ IMAPClient Class ๐ŸŽ€

The primary class used by the imapclient package is the IMAPClient class. All interaction with a remote IMAP server is performed via an IMAPClient instance. Every. Single. One. She's the main character, fr fr. ๐Ÿ‘‘

class imapclient.IMAPClient(host: str, port: int = None, use_uid: bool = True, ssl: bool = True, stream: bool = False, ssl_context: SSLContext | None = None, timeout: float | None = None)

A connection to the IMAP server specified by host is made when this class is instantiated. Yes, the moment you make her, she's already knocking on the server's door. ๐Ÿšช

port defaults to 993, or 143 if ssl is False.

If use_uid is True unique message UIDs be used for all calls that accept message ids (defaults to True).

If ssl is True (the default) a secure connection will be made. Otherwise an insecure connection over plain text will be established. Insecure = plain text = everyone in the middle can read your lil secrets. Just so you know. ๐Ÿ˜ญ

If ssl is True the optional ssl_context argument can be used to provide an ssl.SSLContext instance used to control SSL/TLS connection parameters. If this is not provided a sensible default context will be used.

If stream is True then host is used as the command to run to establish a connection to the IMAP server (defaults to False). This is useful for exotic connection or authentication setups. Fancy. Unhinged, even. We love a niche setup. ๐Ÿงš

Use timeout to specify a timeout for the socket connected to the IMAP server. The timeout can be either a float number, or an instance of imapclient.SocketTimeout.

  • If a single float number is passed, the same timeout delay applies during the initial connection to the server and for all future socket reads and writes.
  • In case of a SocketTimeout, connection timeout and read/write operations can have distinct timeouts. Two different clocks, two different moods. โฑ๏ธ
  • The default is None, where no timeout is used. She waits forever. Romantic, honestly.

The normalise_times attribute specifies whether datetimes returned by fetch() are normalised to the local system time and include no timezone information (native), or are datetimes that include timezone information (aware). By default normalise_times is True (times are normalised to the local system time). This attribute can be changed between fetch() calls if required.

Can be used as a context manager to automatically close opened connections:

>>> with IMAPClient(host="imap.foo.org") as client:
...     client.login("bar@foo.org", "passwd")

Context manager = she closes herself on the way out. No cleanup drama. Iconic behaviour. ๐Ÿซถ

  • AbortError โ€” alias of abort
  • Error โ€” alias of error
  • ReadOnlyError โ€” alias of readonly

๐Ÿฆ‹ Methods ๐Ÿฆ‹

  • add_flags(messages, flags, silent=False) โ€” add flags to messages in the currently selected folder.

flags should be a sequence of strings.

Returns the flags set for each modified message (see get_flags), or None if silent is true. Silent mode = no receipts, no gossip. ๐Ÿคซ

  • add_gmail_labels(messages, labels, silent=False) โ€” add labels to messages in the currently selected folder.

labels should be a sequence of strings.

Returns the label set for each modified message (see get_gmail_labels), or None if silent is true.

This only works with IMAP servers that support the X-GM-LABELS attribute (eg. Gmail). So don't come crying to her if your server isn't Gmail-y enough. ๐Ÿ’€
  • append(folder, msg, flags=(), msg_time=None) โ€” append a message to folder.

msg should be a string contains the full message including headers.

flags should be a sequence of message flags to set. If not specified no flags will be set.

msg_time is an optional datetime instance specifying the date and time to set on the message. The server will set a time if it isn't specified. If msg_time contains timezone information (tzinfo), this will be honoured. Otherwise the local machine's time zone sent to the server.

Returns the APPEND response as returned by the server.

  • capabilities() โ€” returns the server capability list. ๐ŸŒˆ

If the session is authenticated and the server has returned an untagged CAPABILITY response at authentication time, this response will be returned. Otherwise, the CAPABILITY command will be issued to the server, with the results cached for future calls.

If the session is not yet authenticated, the capabilities requested at connection time will be returned.

Cached = she remembered it so you don't have to ask twice. Efficient queen. โœจ

  • close_folder() โ€” close the currently selected folder, returning the server response string. Bye folder!! Hope you had a good time!! ๐Ÿ‘‹

๐Ÿ’… copy(messages, folder)

Copies one or more messages from the folder you're currently in over to folder. It hands you back the COPY response string the server sent, no cap. โœจ


๐ŸŽ€ create_folder(folder)

Makes folder on the server and returns the server's response string. New folder, who dis. ๐ŸŒธ


๐Ÿ’œ delete_folder(folder)

Yeets folder off the server and returns the server's response string. ๐Ÿ’€


๐Ÿฆ‹ delete_messages(messages, silent=False)

Deletes one or more messages from the folder you've currently got selected. ๐Ÿ—‘๏ธ

It returns the flags set for each modified message (peep get_flags for what that looks like).


๐Ÿ‘‘ enable(*capabilities)

Turns on one or more server-side capability extensions.

Bestie, listen: most capabilities do not need to be enabled. This is only required for extensions that introduce backwards-incompatible behaviour. Two capabilities that might need enable are CONDSTORE and UTF8=ACCEPT.

You get back a list of the requested extensions that got successfully enabled on the server. ๐Ÿซถ

Once enabled, each extension stays active until the IMAP connection is closed. Periodt.

See RFC 5161 https://datatracker.ietf.org/doc/html/rfc5161.html for more details.


๐Ÿ™ˆ expunge(messages=None)

Using the messages argument here is discouraged. Please use the uid_expunge method instead. Like, genuinely. ๐Ÿ™

When no messages are specified, it removes all messages from the currently selected folder that have the \Deleted flag set.

The return value is the server response message followed by a list of expunge responses. For example:

('Expunge completed.',
 [(2, 'EXPUNGE'),
  (1, 'EXPUNGE'),
  (0, 'RECENT')])

So in this case the responses are saying that the messages with sequence numbers 2 and 1 were deleted, leaving no recent messages in the folder.

See RFC 3501 Section 6.4.3 https://datatracker.ietf.org/doc/html/rfc3501.html#section-6.4.3 and RFC 3501 Section 7.4.1 https://datatracker.ietf.org/doc/html/rfc3501.html#section-7.4.1 for more details.

When messages are specified, it removes those specified messages from the selected folder โ€” but only provided those messages also have the \Deleted flag set. In that case the return value is None.

Expunging messages by id(s) requires that use_uid is True for the client. ๐Ÿ”‘

See RFC 4315 Section 2.1 https://datatracker.ietf.org/doc/html/rfc4315.html#section-2.1 for more details.


๐ŸŒˆ fetch(messages, data, modifiers=None)

Retrieves selected data associated with one or more messages in the folder you've currently got selected. โœจ

data should be specified as a sequence of strings, one item per data selector, for example ['INTERNALDATE', 'RFC822'].

modifiers are required for some extensions to the IMAP protocol (eg. RFC 4551 https://datatracker.ietf.org/doc/html/rfc4551.html). These should be a sequence of strings if specified, for example ['CHANGEDSINCE 123'].

A dictionary is returned, indexed by message number. Each item in this dictionary is also a dictionary, with an entry corresponding to each item in data. Returned values will be appropriately typed. For example, integer values come back as Python integers, timestamps come back as datetime instances and ENVELOPE responses come back as Envelope instances. ๐Ÿ”ฅ

String data will generally be returned as bytes (Python 3) or str (Python 2).

On top of an element for each data item, the dict returned for each message also contains a SEQ key holding the sequence number for the message. This is what lets you map between the UID and the sequence number (when the use_uid property is True). iykyk ๐Ÿ’ซ

Example:

>> c.fetch([3293, 3230], ['INTERNALDATE', 'FLAGS'])
{3230: {b'FLAGS': (b'\Seen',),
        b'INTERNALDATE': datetime.datetime(2011, 1, 30, 13, 32, 9),
        b'SEQ': 84},
 3293: {b'FLAGS': (),
        b'INTERNALDATE': datetime.datetime(2011, 2, 24, 19, 30, 36),
        b'SEQ': 110}}

๐Ÿงš find_special_folder(folder_flag)

Tries to locate a special folder, like the Sent or Trash folder. ๐Ÿ—‚๏ธ

>>> server.find_special_folder(imapclient.SENT)
'INBOX.Sent'

This function tries its best to find the correct folder (if any) but uses heuristics when the server is unable to precisely tell where special folders are located. It's giving detective energy. ๐Ÿ”

Returns the name of the folder if found, or None otherwise.


๐Ÿ’– folder_exists(folder)

Returns True if folder exists on the server. Simple as that, bestie.


๐Ÿ“ folder_status(folder, what=None)

Returns the status of folder.

what should be a sequence of status items to query. This defaults to ('MESSAGES', 'RECENT', 'UIDNEXT', 'UIDVALIDITY', 'UNSEEN').

Returns a dictionary of the status items for the folder with keys matching what.


โญ get_flags(messages)

Returns the flags set for each message in messages from the folder you've currently got selected.

The return value is a dictionary structured like this: { msgid1: (flag1, flag2, ... ), }.


๐ŸŽ€ get_gmail_labels(messages)

Returns the label set for each message in messages in the folder you've currently got selected.

The return value is a dictionary structured like this: { msgid1: (label1, label2, ... ), }.

This only works with IMAP servers that support the X-GM-LABELS attribute (eg. Gmail). So if you're not on Gmailโ€ฆ yeah. ๐Ÿ˜ญ


๐Ÿ‘‘ get_quota(mailbox='INBOX')

Gets the quotas associated with a mailbox.

Returns a list of Quota objects.


๐Ÿ’œ get_quota_root(mailbox)

Gets the quota roots for a mailbox.

The IMAP server responds with the quota root and the quotas associated with it, so there's usually no need to call get_quota afterwards. Two-for-one deal, slay. ๐Ÿซถ

See RFC 2087 https://datatracker.ietf.org/doc/html/rfc2087.html for more details.

Returns a tuple of MailboxQuotaRoots and a list of Quota associated.


๐ŸŒธ getacl(folder)

Returns a list of (who, acl) tuples describing the access controls for folder. ๐Ÿ”


๐Ÿฆ‹ gmail_search(query, charset='UTF-8')

Search using Gmail's X-GM-RAW attribute.

query should be a valid Gmail search query string. For example: has:attachment in:unread. The search string may be unicode and will be encoded using the specified charset (defaulting to UTF-8).

This method only works for IMAP servers that support X-GM-RAW, which is only likely to be Gmail.

See https://developers.google.com/gmail/imap_extensions#extension_of_the_search_command_x-gm-raw for more info.


โœจ has_capability(capability)

Returns True if the IMAP server has the given capability. Vibe check on the server, basically. ๐Ÿ’…


๐Ÿ’Œ id_(parameters=None)

Issues the ID command, returning a dict of server implementation fields.

parameters should be specified as a dictionary of field/value pairs, for example: {"name": "IMAPClient", "version": "0.12"}


๐ŸŒˆ idle()

Puts the server into IDLE mode. ๐Ÿ˜ด

In this mode the server will return unsolicited responses about changes to the selected mailbox. This method returns immediately. Use idle_check() to look for IDLE responses and idle_done() to stop IDLE mode.

Note: any other commands issued while the server is in IDLE mode will fail. Don't do it, bestie. ๐Ÿ™ˆ

See RFC 2177 https://datatracker.ietf.org/doc/html/rfc2177.html for more information about the IDLE extension.


๐Ÿ” idle_check(timeout=None)

Checks for any IDLE responses sent by the server.

This method should only be called if the server is in IDLE mode (see idle()).

By default, this method will block until an IDLE response is received. If timeout is provided, the call will block for at most this many seconds while waiting for an IDLE response.

The return value is a list of received IDLE responses. These will be parsed with values converted to appropriate types. For example:

[(b'OK', b'Still here'),
 (1, b'EXISTS'),
 (1, b'FETCH', (b'FLAGS', (b'\NotJunk',)))]

๐Ÿซถ idle_done()

Takes the server out of IDLE mode. Wakey wakey. โฐ

This method should only be called if the server is already in IDLE mode.

The return value is of the form (command_text, idle_responses) where command_text is the text sent by the server when the IDLE command finished (eg. b'Idle terminated') and idle_responses is a list of parsed idle responses received since the last call to idle_check() (if any). These are returned in parsed form as per idle_check().


๐ŸŽ€ list_folders(directory='', pattern='*')

Gets a listing of folders on the server as a list of (flags, delimiter, name) tuples. ๐Ÿ—‚๏ธโœจ

Specifying directory will limit returned folders to the given base directory. The directory and any child directories will be returned.

Passing a pattern is basically a glow-up filter for your folder list ๐Ÿ’… โ€” it limits the folders you get back to only the ones whose names match. Wildcards work inside pattern: * matches zero or more of any character, and % matches 0 or more characters except the folder delimiter (iykyk, it's the separator vibe).

Calling list_folders with no arguments will recursively list every single folder available to the logged-in user. Obsessed, honestly. ๐ŸŽ€

Folder names always come back as unicode strings, decoded from modified UTF-7 โ€” except if folder_decode is not set. Don't forget that one bestie, it's giving sneaky. โœจ

list_sub_folders(directory='', pattern='*')

Returns a list of subscribed folders on the server as (flags, delimiter, name) tuples. ๐ŸŒธ

By default it just lists all the subscribed folders. The directory and pattern arguments work exactly as per list_folders() โ€” same rules, same energy. ๐Ÿซถ

login(username: str, password: str)

Log in using username and password, and it hands you back the server response. Slay. ๐Ÿ”

logout()

Logs out, returning the server response. Byeeee ๐Ÿ‘‹โœจ

move(messages, folder)

Atomically move messages to another folder. No half-moved nonsense, it's all-or-nothing, periodt. ๐Ÿ’…

This requires the MOVE capability, see RFC 6851 <https://datatracker.ietf.org/doc/html/rfc6851.html>. No cap.

Parameters:

  • messages โ€” List of message UIDs to move.
  • folder โ€” The destination folder name. ๐ŸŽฏ

multiappend(folder, msgs)

Appends messages to folder using the MULTIAPPEND feature from RFC 3502 <https://datatracker.ietf.org/doc/html/rfc3502.html>. ๐Ÿฆ‹

msgs must be an iterable. Each item must be either:

  • a string containing the full message including headers, or
  • a dict containing the keys "msg" with the full message as before, "flags" with a sequence of message flags to set, and "date" with a datetime instance specifying the internal date to set.

The keys "flags" and "date" are optional โ€” no pressure bestie. ๐ŸŒˆ

Returns the APPEND response from the server. ๐Ÿ“ฌ

namespace()

Returns the namespace for the account as a (personal, other, shared) tuple. ๐Ÿ‘‘

Each element may be None if no namespace of that type exists, or a sequence of (prefix, separator) pairs.

For convenience the tuple elements may be accessed positionally or using attributes named personal, other and shared. Flexible, iconic, main character energy fr fr.

See RFC 2342 <https://datatracker.ietf.org/doc/html/rfc2342.html> for more details.

noop()

Execute the NOOP command.

This command returns immediately, returning any server side status updates. It can also be used to reset any auto-logout timers. โฐ (lowkey a lifesaver)

The return value is the server command response message followed by a list of status responses. For example:

(b'NOOP completed.',
 [(4, b'EXISTS'),
  (3, b'FETCH', (b'FLAGS', (b'bar', b'sne'))),
  (6, b'FETCH', (b'FLAGS', (b'sne',)))])

oauth2_login(user: str, access_token: str, mech: str = 'XOAUTH2', vendor: str | None = None)

Authenticate using the OAUTH2 or XOAUTH2 methods. ๐Ÿ”‘

Gmail and Yahoo both support the 'XOAUTH2' mechanism, but Yahoo requires the 'vendor' portion in the payload. So if it's Yahoo and it's not workingโ€ฆ yeah that's why bestie. ๐Ÿ™ˆ

oauthbearer_login(identity, access_token)

Authenticate using the OAUTHBEARER method.

This is supported by Gmail and is meant to supersede the non-standard 'OAUTH2' and 'XOAUTH2' mechanisms. It's the glow-up version. โœจ

plain_login(identity, password, authorization_identity=None)

Authenticate using the PLAIN method (requires server support). Simple, classic, does the job. ๐Ÿ’–

remove_flags(messages, flags, silent=False)

Remove one or more flags from messages in the currently selected folder. ๐Ÿงน

flags should be a sequence of strings.

Returns the flags set for each modified message (see get_flags), or None if silent is true.

remove_gmail_labels(messages, labels, silent=False)

Remove one or more labels from messages in the currently selected folder, or None if silent is true. ๐Ÿท๏ธ

labels should be a sequence of strings.

Returns the label set for each modified message (see get_gmail_labels).

โš ๏ธ This only works with IMAP servers that support the X-GM-LABELS attribute (eg. Gmail). No Gmail, no labels, sorry bestie. ๐Ÿ’€

rename_folder(old_name, new_name)

Change the name of a folder on the server. A little rebrand, we love to see it. ๐ŸŽ€

sasl_login(mech_name, mech_callable)

Authenticate using a provided SASL mechanism (requires server support). ๐Ÿ›ก๏ธ

The mech_callable will be called with one parameter (the server challenge as bytes) and must return the corresponding client response (as bytes, or as string which will be automatically encoded).

It will be called as many times as the server produces challenges, which will depend on the specific SASL mechanism. (If the mechanism is defined as "client-first", the server will nevertheless produce a zero-length challenge.)

For example, PLAIN has just one step with empty challenge, so a handler might look like this:

plain_mech = lambda _: "\0%s\0%s" % (username, password)

imap.sasl_login("PLAIN", plain_mech)

A more complex but still stateless handler might look like this:

def example_mech(challenge):
    if challenge == b"Username:"
        return username.encode("utf-8")
    elif challenge == b"Password:"
        return password.encode("utf-8")
    else:
        return b""

imap.sasl_login("EXAMPLE", example_mech)

A stateful handler might look like this:

class ScramSha256SaslMechanism():
    def __init__(self, username, password):
        ...

    def __call__(self, challenge):
        self.step += 1
        if self.step == 1:
            response = ...
        elif self.step == 2:
            response = ...
        return response

scram_mech = ScramSha256SaslMechanism(username, password)

imap.sasl_login("SCRAM-SHA-256", scram_mech)

search(criteria='ALL', charset=None)

Return a list of message ids from the currently selected folder matching criteria. ๐Ÿ”

criteria should be a sequence of one or more criteria items. Each criteria item may be either unicode or bytes. Example values:

[u'UNSEEN']
[u'SMALLER', 500]
[b'NOT', b'DELETED']
[u'TEXT', u'foo bar', u'FLAGGED', u'SUBJECT', u'baz']
[u'SINCE', date(2005, 4, 3)]

IMAPClient will perform conversion and quoting as required. The caller shouldn't do this. Let the library cook. ๐Ÿ‘‘

It is also possible (but not recommended) to pass the combined criteria as a single string. In this case IMAPClient won't perform quoting, allowing lower-level specification of criteria. Examples of this style:

u'UNSEEN'
u'SMALLER 500'
b'NOT DELETED'
u'TEXT "foo bar" FLAGGED SUBJECT "baz"'
b'SINCE 03-Apr-2005'

To support complex search expressions, criteria lists can be nested. IMAPClient will insert parentheses in the right places. The following will match messages that are both not flagged and do not have "foo" in the subject:

['NOT', ['SUBJECT', 'foo', 'FLAGGED']]

charset specifies the character set of the criteria. It defaults to US-ASCII as this is the only charset that a server is required to support by the RFC. UTF-8 is commonly supported however.

Any criteria specified using unicode will be encoded as per charset. Specifying a unicode criteria that can not be encoded using charset will result in an error. ๐Ÿ˜ญ

Any criteria specified using bytes will be sent as-is but should use an encoding that matches charset (the character set given is still passed on to the server).

See RFC 3501 Section 6.4.4 <https://datatracker.ietf.org/doc/html/rfc3501.html#section-6.4.4> for more details.

Note that criteria arguments that are 8-bit will be transparently sent by IMAPClient as IMAP literals to ensure adherence to IMAP standards. โœจ

The returned list of message ids will have a special modseq attribute. This is set if the server included a MODSEQ value to the search response (i.e. if a MODSEQ criteria was included in the search).

select_folder(folder, readonly=False)

Set the current folder on the server. ๐Ÿ“‚

Future calls to methods such as search and fetch will act on the selected folder.

Returns a dictionary containing the SELECT response. At least the b'EXISTS', b'FLAGS' and b'RECENT' keys are guaranteed to exist. An example:

{b'EXISTS': 3,
 b'FLAGS': (b'\Answered', b'\Flagged', b'\Deleted', ... ),
 b'RECENT': 0,
 b'PERMANENTFLAGS': (b'\Answered', b'\Flagged', b'\Deleted', ... ),
 b'READ-WRITE': True,
 b'UIDNEXT': 11,
 b'UIDVALIDITY': 1239278212}

set_flags(messages, flags, silent=False)

Set the flags for messages in the currently selected folder. ๐Ÿšฉ

flags should be a sequence of strings.

Returns the flags set for each modified message (peep get_flags), or None if silent is true. โœจ

  • set_gmail_labels(messages, labels, silent=False) โ€” Set the labels for messages in the currently selected folder.

labels should be a sequence of strings.

Returns the label set for each modified message (see get_gmail_labels), or None if silent is true.

This only works with IMAP servers that support the X-GM-LABELS attribute (eg. Gmail).

  • set_quota(quotas) โ€” Set one or more quotas on resources.

Parameters

  • quotas -- list of Quota objects
  • setacl(folder, who, what) โ€” Set an ACL (what) for user (who) for a folder.

Set what to an empty string to remove an ACL. Returns the server response string. slay, that's the whole thing ๐Ÿ’…

  • shutdown() -> None โ€” Close the connection to the IMAP server (without logging out).

In most cases, logout() should be used instead of this. The logout method also shuts down the connection.

  • socket() โ€” Returns socket used to connect to server.

The socket is provided for polling purposes only. It can be used in, for example, selectors.BaseSelector.register() and asyncio.loop.add_reader() to wait for data.

Warning: All other uses of the returned socket are unsupported. This includes reading from and writing to the socket, as they are likely to break internal bookkeeping of messages. like bestie do NOT touch it, it's a look-don't-touch situation fr fr ๐Ÿ˜ญ
  • sort(sort_criteria, criteria='ALL', charset='UTF-8') โ€” Return a list of message ids from the currently selected folder, sorted by sort_criteria and optionally filtered by criteria.

sort_criteria may be specified as a sequence of strings or a single string. IMAPClient will take care any required conversions. Valid sort_criteria values:

['ARRIVAL']
['SUBJECT', 'ARRIVAL']
'ARRIVAL'
'REVERSE SIZE'

The criteria and charset arguments are as per search().

See RFC 5256 https://datatracker.ietf.org/doc/html/rfc5256.html for full details.

Note that SORT is an extension to the IMAP4 standard so it may not be supported by all IMAP servers. so if your server ghosts you on this one, that's why ๐Ÿ™ˆ

  • starttls(ssl_context=None) โ€” Switch to an SSL encrypted connection by sending a STARTTLS command.

The ssl_context argument is optional and should be a ssl.SSLContext object. If no SSL context is given, a SSL context with reasonable default settings will be used.

You can enable checking of the hostname in the certificate presented by the server against the hostname which was used for connecting, by setting the check_hostname attribute of the SSL context to True. The default SSL context has this setting enabled. glow up your security, we love to see it ๐Ÿซถ

Raises Error if the SSL connection could not be established.

Raises AbortError if the server does not support STARTTLS or an SSL connection is already established.

  • subscribe_folder(folder) โ€” Subscribe to folder, returning the server response string.
  • thread(algorithm='REFERENCES', criteria='ALL', charset='UTF-8') โ€” Return a list of messages threads from the currently selected folder which match criteria.

Each returned thread is a list of messages ids. An example return value containing three message threads:

((1, 2), (3,), (4, 5, 6))

The optional algorithm argument specifies the threading algorithm to use.

The criteria and charset arguments are as per search().

See RFC 5256 https://datatracker.ietf.org/doc/html/rfc5256.html for more details.

  • uid_expunge(messages) โ€” Expunge deleted messages with the specified message ids from the folder.

This requires the UIDPLUS capability.

See RFC 4315 Section 2.1 https://datatracker.ietf.org/doc/html/rfc4315.html#section-2.1 section 2.1 for more details. (yes, the URL literally says section 2.1 and then the sentence says section 2.1 again. iconic behaviour, keeping it โœจ)

  • unselect_folder() โ€” Unselect the current folder and release associated resources.

Unlike close_folder, the UNSELECT command does not expunge the mailbox, keeping messages with Deleted flag set for example. no surprise deletions, we stan a respectful queen ๐Ÿ‘‘

Returns the UNSELECT response string returned by the server.

  • unsubscribe_folder(folder) โ€” Unsubscribe to folder, returning the server response string.
  • property welcome โ€” access the server greeting message hi bestie, the server said hi back ๐Ÿ’–
  • xlist_folders(directory='', pattern='*') โ€” Execute the XLIST command, returning (flags, delimiter, name) tuples.

This method returns special flags for each folder and a localized name for certain folders (e.g. the name of the inbox may be localized and the flags can be used to determine the actual inbox, even if the name has been localized.

A XLIST response could look something like:

[((b'\HasNoChildren', b'\Inbox'), b'/', u'Inbox'),
 ((b'\Noselect', b'\HasChildren'), b'/', u'[Gmail]'),
 ((b'\HasNoChildren', b'\AllMail'), b'/', u'[Gmail]/All Mail'),
 ((b'\HasNoChildren', b'\Drafts'), b'/', u'[Gmail]/Drafts'),
 ((b'\HasNoChildren', b'\Important'), b'/', u'[Gmail]/Important'),
 ((b'\HasNoChildren', b'\Sent'), b'/', u'[Gmail]/Sent Mail'),
 ((b'\HasNoChildren', b'\Spam'), b'/', u'[Gmail]/Spam'),
 ((b'\HasNoChildren', b'\Starred'), b'/', u'[Gmail]/Starred'),
 ((b'\HasNoChildren', b'\Trash'), b'/', u'[Gmail]/Trash')]

This is a deprecated Gmail-specific IMAP extension (See https://developers.google.com/gmail/imap_extensions#xlist_is_deprecated for more information). deprecated means we don't really use it anymore bestie, it's giving โœจvintageโœจ but not in a cute way

The directory and pattern arguments are as per list_folders().


class imapclient.SocketTimeout(connect: float, read: float)

Represents timeout configuration for an IMAP connection. so your code doesn't just sit there waiting forever like me in the group chat ๐Ÿฆ‹

Variables

  • connect -- maximum time to wait for a connection attempt to remote server
  • read -- maximum time to wait for performing a read/write operation

As an example, SocketTimeout(connect=15, read=60) will make the socket timeout if the connection takes more than 15 seconds to establish but read/write operations can take up to 60 seconds once the connection is done.


Fetch Response Types ๐ŸŒˆ

Various types may be used in the data structures returned by IMAPClient.fetch() when certain response types are encountered during parsing. aka these are the lil guys you'll bump into inside your fetched data โœจ

class imapclient.response_types.Address(name: bytes, route: bytes, mailbox: bytes, host: bytes)

Represents electronic mail addresses. Used to store addresses in Envelope.

Variables

  • name -- The address "personal name".
  • route -- SMTP source route (rarely used). basically a fossil, don't worry about it ๐Ÿ’€
  • mailbox -- Mailbox name (what comes just before the @ sign).
  • host -- The host/domain name.

As an example, an address header that looks like:

Mary Smith <mary@foo.com>

would be represented as:

Address(name=u'Mary Smith', route=None, mailbox=u'mary', host=u'foo.com')

See RFC 2822 https://datatracker.ietf.org/doc/html/rfc2822.html for more detail.

See also Envelope for information about handling of "group syntax".

class imapclient.response_types.BodyData(iterable=(), /)

Returned when parsing BODY and BODYSTRUCTURE responses. that's it, that's the whole vibe ๐ŸŽ€

class imapclient.response_types.Envelope(...)

Signature, verbatim so nobody @s me:

Envelope(date: datetime | None, subject: bytes, from_: Tuple[Address <#imapclient.response_types.Address>, ...] | None, sender: Tuple[Address <#imapclient.response_types.Address>, ...] | None, reply_to: Tuple[Address <#imapclient.response_types.Address>, ...] | None, to: Tuple[Address <#imapclient.response_types.Address>, ...] | None, cc: Tuple[Address <#imapclient.response_types.Address>, ...] | None, bcc: Tuple[Address <#imapclient.response_types.Address>, ...] | None, in_reply_to: bytes, message_id: bytes)

Represents envelope structures of messages. Returned when parsing ENVELOPE responses. the main character of fetch responses honestly ๐Ÿ‘‘

Variables

  • date -- A datetime instance that represents the "Date" header.
  • subject -- A string that contains the "Subject" header.
  • from_ -- A tuple of Address objects that represent one or more addresses from the "From" header, or None if header does not exist.
  • sender -- As for from_ but represents the "Sender" header.
  • reply_to -- As for from_ but represents the "Reply-To" header.
  • to -- As for from_ but represents the "To" header.
  • cc -- As for from_ but represents the "Cc" header.
  • bcc -- As for from_ but represents the "Bcc" recipients.
  • in_reply_to -- A string that contains the "In-Reply-To" header.
  • message_id -- A string that contains the "Message-Id" header.

A particular issue to watch out for is IMAP's handling of "group syntax" in address fields. This is often encountered as a recipient header of the form:

undisclosed-recipients:;

but can also be expressed per this more general example:

A group: a@example.com, B <b@example.org>;

This example would yield the following Address tuples:

Address(name=None, route=None, mailbox=u'A group', host=None)
Address(name=None, route=None, mailbox=u'a', host=u'example.com')
Address(name=u'B', route=None, mailbox=u'b', host=u'example.org')
Address(name=None, route=None, mailbox=None, host=None)

okay so bestie, the group tea ๐Ÿซ– that first Address โ€” the one where host is None โ€” marks the start of the group, and its mailbox field is holding the group name, periodt. Then the final Address, where both mailbox and host are None, marks the end of the group. Bookends, no cap ๐ŸŽ€

Wanna go deeper? RFC 3501 Section 7.4.2 lives at https://datatracker.ietf.org/doc/html/rfc3501.html#section-7.4.2 and RFC 2822 lives at https://datatracker.ietf.org/doc/html/rfc2822.html โ€” they've got all the further details ๐Ÿ’…


class imapclient.response_types.SearchIds(*args: Any)

This one's carrying a list of message ids, exactly as IMAPClient.search() hands them back ๐Ÿฆ‹

The modseq attribute is gonna contain the MODSEQ value the server returned โ€” but only if the SEARCH command that went out involved the MODSEQ criteria, iykyk. See RFC 4551 at https://datatracker.ietf.org/doc/html/rfc4551.html for more details โœจ


โœจ Exceptions โœจ

okay so IMAPClient wraps up the exceptions raised by imaplib, so your error handling stays chill ๐Ÿ˜Œ. All the exceptions related to IMAP errors are defined in the imapclient.exceptions module. These are the general ones that may get raised:

  • IMAPClientError โ€” the base class for IMAPClient's exceptions, and honestly the most commonly used error ๐Ÿ’–
  • IMAPClientAbortError โ€” raised if a serious error has occurred that means the IMAP connection is no longer usable. The connection should be dropped without logout if this happens ๐Ÿ’€
  • IMAPClientReadOnlyError โ€” raised if a modifying operation was attempted on a read-only folder ๐Ÿ™ˆ

More specific exceptions exist for common known errors:

  • imapclient.exceptions.CapabilityError โ€” the command tried by the user needs a capability that isn't installed on the IMAP server ๐Ÿšซ
  • imapclient.exceptions.IllegalStateError โ€” the command tried needs a different state to be executed. This means the user is not logged in, or the command needs a folder to be selected ๐Ÿ‘€
  • imapclient.exceptions.InvalidCriteriaError โ€” a command using a search criteria failed, probably due to a syntax error in the criteria string ๐Ÿ˜ญ
  • imapclient.exceptions.LoginError โ€” a connection has been established with the server but an error occurred during the authentication ๐Ÿ”
  • imapclient.exceptions.ProtocolError โ€” the server replied with a response that violates the IMAP protocol. Rude ๐Ÿšฉ

Exceptions from lower layers are possible too, like network errors or unicode malformed exceptions. In particular:

  • socket.error
  • socket.timeout โ€” raised if a timeout was specified when creating the IMAPClient instance and a network operation takes too long โฐ
  • ssl.SSLError โ€” the base class for network or SSL protocol errors when ssl=True or starttls() is used ๐Ÿ”’
  • ssl.CertificateError โ€” raised when TLS certification verification fails. Heads up bestie: this is not a subclass of SSLError ๐ŸŽ€

๐Ÿ›  Utilities ๐Ÿ› 

  • class imapclient.testable_imapclient.MockIMAP4(spec=None, wraps=None, name=None, spec_set=None, parent=None, _spec_state=None, _new_name='', _new_parent=None, _spec_as_instance=False, _eat_self=None, unsafe=False, **kwargs)
  • class imapclient.testable_imapclient.TestableIMAPClient โ€” a wrapper of imapclient.IMAPClient that mocks all interaction with a real IMAP server. This class should only be used in tests, where you can safely interact with imapclient without running commands on a real IMAP account ๐Ÿงช

๐Ÿ” TLS Support ๐Ÿ”

This module contains IMAPClient's functionality related to Transport Layer Security (TLS, a.k.a. SSL) ๐Ÿ’–

class imapclient.tls.IMAP4_TLS(host: str, port: int = 993, ssl_context: SSLContext | None = None, timeout: float | None = None)

The IMAP4 client class for TLS/SSL connections ๐Ÿ”’ Adapted from imaplib.IMAP4_SSL โœจ


๐Ÿงต Thread Safety ๐Ÿงต

Instances of IMAPClient are NOT thread safe. They should not be shared and accessed concurrently from multiple threads. Periodt ๐Ÿšซ

๐ŸŒˆ CONTRIBUTOR GUIDE ๐ŸŒˆ

๐Ÿ’– Contributing to IMAPClient ๐Ÿ’–

The best way to contribute changes to IMAPClient? Fork the official repository on Github, make your changes in a branch in your personal fork, then submit a pull request ๐Ÿซถ

Discussion on Github at https://github.com/mjs/imapclient/discussions before you dive into development is highly encouraged for potentially major changes ๐Ÿ‘‘

It's not essential, but it'll make the project maintainers much happier if your change submissions include appropriate updates to unit tests, live tests and documentation. Please ask if you're unsure how the tests work โ€” they got you ๐Ÿ’…

Please read on if you plan on submitting changes to IMAPClient โœจ

๐Ÿ“‚ Source Code ๐Ÿ“‚

The official source code repository for IMAPClient can be found on Github at: https://github.com/mjs/imapclient

Any major feature work will also be found as branches of this repository ๐ŸŒฟ

๐ŸŒณ Branches ๐ŸŒณ

Development for the next major release happens on the master branch ๐Ÿ‘‘

There's also a branch for each major release series (for example: 1.x). When appropriate and when there will be future releases for a series, changes may be selectively merged between master and a stable release branch ๐Ÿ”€

๐Ÿท Release Tags ๐Ÿท

Each released version is available in the IMAPClient repository as a Git tag (e.g. "0.9.1") ๐ŸŽ€

๐Ÿงช Unit Tests ๐Ÿงช

Running Unit Tests

To run the tests, from the root of the package source run:

python -m unittest --verbose

Testing Against Multiple Python Versions

When submitting a Pull Request to IMAPClient, tests are automatically run against all the supported Python versions ๐Ÿค–

It's also possible to run these tests locally using tox at http://testrun.org/tox/. Once installed, the tox command will use the tox.ini file in the root of the project source and run the unit tests against the Python versions officially supported by IMAPClient (provided these versions of Python are installed!) ๐Ÿ

To avoid having to install all Python versions directly on a host, the tox-all script can be used. It will run the unit tests inside a Docker container which contains all supported Python versions ๐Ÿณ. As long as Docker is installed and your user account can sudo to root, the following should work:

./tox-all

The script passes any arguments on to tox. For example, to run just the tests just against Python 3.10 do:

./tox-all -e py310

Writing Unit Tests

Protocol level unit tests should not act against a real IMAP server but should use canned data instead ๐Ÿฅซ. The IMAPClientTest base class should typically be used as the base class for any tests โ€” it provides a mock IMAPClient instance at self.client. See the tests in tests/test_imapclient.py for examples of how to write unit tests using this approach ๐Ÿ’–

๐Ÿ“– Documentation ๐Ÿ“–

The source for the project's documentation can be found under doc/src in the source distribution ๐Ÿ—‚

In order to build the documentation you'll need to install Sphinx. Running pip install '.[doc]' from the root of the project source will do this โœจ

Once Sphinx is installed, the documentation can be rebuilt using:

python setup.py build_sphinx

๐ŸŒ EXTERNAL DOCUMENTATION ๐ŸŒ

The Unofficial IMAP Protocol Wiki at http://www.imapwiki.org/ is very useful when writing IMAP related software and is highly recommended ๐Ÿ‘‘


๐Ÿ‘‘ AUTHORS ๐Ÿ‘‘

IMAPClient was created by Menno Finlay-Smits <<inbox@menno.io>>. The project is now maintained by Nicolas Le Manchet and Menno Finlay-Smits ๐Ÿซถ

Many thanks go to the following people for their help with this project:

  • Maxime Lorant
  • Mathieu Agopian
  • Chris Arndt
  • Jp Calderone
  • John Louis del Rosario
  • Dave Eckhardt
  • Eben Freeman
  • Helder Guerreiro
  • Mark Hammond
  • Johannes Heckel
  • Thomas Jost
  • Lukasz Mierzwa
  • Naveen Nathan
  • Brian Neal
  • Phil Peterson
  • Aviv Salem
  • Andrew Scheller
  • Thomas Steinacher
  • Zac Witte
  • Hans-Peter Jansen
  • Carson Ip
  • Jonny Hatch
  • Jasper Spaans
  • Fabio Manganiello
  • Samir M
  • Devin Bayer
  • Mantas Mikulฤ—nas
  • @zrose584
  • Michaล‚ Gรณrny
  • Franรงois Deppierraz
  • Jasper Spaans
  • Boni Lindsley
  • Tobias Kรถlling
  • @pinoatrome
  • Shoaib Ahmed
  • John Villalovos
  • Claude Paroz
  • Stefan Wรณjcik
  • Andrzej Bartosiล„ski
  • @axoroll7
  • Sean Whalen
  • Peter Wienemann

๐Ÿ“œ RELEASE HISTORY ๐Ÿ“œ

From release 3.0.0 onwards, release notes are maintained on Github at https://github.com/mjs/imapclient/releases โœจ

Release notes for older versions can be found in these docs <> ๐Ÿฆ‹

Author

Menno Smits

2014, Menno Smits


and that's a wrap on the whole page, bestie! You just read IMAPCLIENT(7) โ€” version 3.1.0, dated Feb 07, 2026 ๐ŸŽ€ now go slay some IMAP ๐Ÿ’…โœจ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from