Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 101 additions & 25 deletions Doc/library/imaplib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,10 @@ enclosed with either parentheses or double quotes) each string is quoted.
However, the *password* argument to the ``LOGIN`` command is always quoted. If
you want to avoid having an argument string quoted (eg: the *flags* argument to
``STORE``) then enclose the string in parentheses (eg: ``r'(\Deleted)'``).
In general, pass arguments unquoted and let the module quote them as needed.
An argument that is already enclosed in double quotes is left unchanged,
so that code which quotes arguments itself keeps working.
Or you can quote the string yourself;
an argument that is already enclosed in double quotes is left unchanged.
In general, however, it is better to pass arguments unquoted
and let the module quote them as needed.

Mailbox names are encoded as modified UTF-7 (:rfc:`3501`, section 5.1.3),
so a mailbox name containing non-ASCII characters can be passed as an
Expand All @@ -211,11 +212,70 @@ or mandated results from the command. Each *data* is either a ``bytes``, or a
tuple. If a tuple, then the first part is the header of the response, and the
second part contains the data (ie: 'literal' value).

The *message_set* options to commands below is a string specifying one or more
messages to be acted upon. It may be a simple message number (``'1'``), a range
of message numbers (``'2:4'``), or a group of non-contiguous ranges separated by
commas (``'1:3,6:9'``). A range can contain an asterisk to indicate an infinite
upper bound (``'3:*'``).
The *message_set* options to the commands below can be a string specifying
one or more messages to be acted upon.
It may be a simple message number (``'1'``),
a range of message numbers (``'2:4'``),
or a group of non-contiguous ranges separated by commas (``'1:3,6:9'``).
A range can contain an asterisk
to indicate an infinite upper bound (``'3:*'``).

Alternatively it can be specified using integers and :class:`range` objects.
It may be a single message number or a sequence.
The sequence items may be integers, ``(start, stop)`` tuples
(where ``None`` or ``'*'`` stands for the last message),
or :class:`range` objects.
For example, ``[1, (3, 5), 8]`` and ``[range(1, 6), 8]``
are both equivalent to ``'1,3:5,8'``.

.. versionchanged:: next
Added support for the structured *message_set*.

Command arguments that are parenthesized lists of atoms ---
such as the *flag_list* argument of :meth:`~IMAP4.store` and the *flags*
argument of :meth:`~IMAP4.append`,
the *names* argument of :meth:`~IMAP4.status`,
the *sort_criteria* argument of :meth:`~IMAP4.sort`,
or the *message_parts* argument of :meth:`~IMAP4.fetch` ---
can be passed as a sequence of strings instead of a single preformatted string.
For example, ``[r'\Seen', r'\Answered']``
is equivalent to ``(\Seen \Answered)``.

.. versionchanged:: next
Added support for passing these arguments as a sequence.

.. _imap4-params:

The value-bearing arguments of the search and fetch commands
can be quoted by hand, but this is error prone.
Instead, they may contain ``?`` placeholders that are substituted, and quoted
Comment thread
serhiy-storchaka marked this conversation as resolved.
as required, from a *params* keyword argument,
in the manner of :mod:`sqlite3` parameter substitution::

# SEARCH FROM me@example.com SUBJECT "trip report"
M.search(None, 'FROM ? SUBJECT ?', params=['me@example.com', 'trip report'])

# FETCH 1:5 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])
M.fetch('1:5', 'FLAGS BODY[HEADER.FIELDS ?]', params=[['DATE', 'FROM']])

The placeholders are:

* ``?`` --- an ``astring``: a string (which will be quoted if necessary),
an integer, or a list of integers and/or strings
(which will be sent as a parenthesized list);
* ``?f`` --- a flag or a list of flags, sent verbatim without quoting;
* ``?s`` --- a *message_set* in the structured form described above.

``??`` stands for a literal ``?``.

Substitution is only performed when *params* is given;
if no *params* are given, an argument containing a literal ``?`` is unchanged.
The *params* keyword is accepted by :meth:`~IMAP4.search`,
:meth:`~IMAP4.fetch`, :meth:`~IMAP4.sort`, :meth:`~IMAP4.thread` and
:meth:`~IMAP4.uid`.

.. versionadded:: next
The *params* keyword argument.

An :class:`IMAP4` instance has the following methods:

Expand Down Expand Up @@ -324,7 +384,7 @@ An :class:`IMAP4` instance has the following methods:
Added the *message_set* and *uid* parameters.


.. method:: IMAP4.fetch(message_set, message_parts, *, uid=False)
.. method:: IMAP4.fetch(message_set, message_parts, *, uid=False, params=None)

Fetch (parts of) messages. *message_parts* should be a string of message part
names enclosed within parentheses, eg: ``"(UID BODY[TEXT])"``. Returned data
Expand All @@ -333,8 +393,11 @@ An :class:`IMAP4` instance has the following methods:
If *uid* is true, *message_set* is a set of UIDs and the message numbers in
the response are UIDs (``UID FETCH``).

If *params* is given, ``?`` placeholders in *message_parts* are substituted
with the quoted parameters (see :ref:`the placeholders <imap4-params>`).

.. versionchanged:: next
Added the *uid* parameter.
Added the *params* and *uid* parameters.


.. method:: IMAP4.getacl(mailbox)
Expand Down Expand Up @@ -598,7 +661,7 @@ An :class:`IMAP4` instance has the following methods:
code, instead of the usual type.


.. method:: IMAP4.search(charset, criterion[, ...], *, uid=False)
.. method:: IMAP4.search(charset, criterion[, ...], *, uid=False, params=None)

Search mailbox for matching messages. *charset* may be ``None``, in which case
no ``CHARSET`` will be specified in the request to the server. The IMAP
Expand All @@ -617,18 +680,22 @@ An :class:`IMAP4` instance has the following methods:
When *charset* is ``None`` (as it must be under ``UTF8=ACCEPT``),
the criterion is sent using the connection's encoding instead.

If *params* is given, ``?`` placeholders in the criteria are substituted
with the quoted parameters (see :ref:`the placeholders <imap4-params>`).

Example::

# M is a connected IMAP4 instance...
typ, msgnums = M.search(None, 'FROM', '"LDJ"')
typ, msgnums = M.search(None, 'FROM', '"John Smith"')

# or:
typ, msgnums = M.search(None, '(FROM "LDJ")')
typ, msgnums = M.search(None, '(FROM "John Smith")')

.. versionchanged:: next
Added the *uid* parameter.
# or, letting the module quote the value (this is recommended):
typ, msgnums = M.search(None, 'FROM ?', params=['John Smith'])

.. versionchanged:: next
Added the *params* and *uid* parameters.
``str`` search criteria are encoded to *charset*.


Expand Down Expand Up @@ -675,7 +742,7 @@ An :class:`IMAP4` instance has the following methods:
Returns socket instance used to connect to server.


.. method:: IMAP4.sort(sort_criteria, charset, search_criterion[, ...], *, uid=False)
.. method:: IMAP4.sort(sort_criteria, charset, search_criterion[, ...], *, uid=False, params=None)

The ``sort`` command is a variant of ``search`` with sorting semantics for the
results. Returned data contains a space separated list of matching message
Expand All @@ -696,12 +763,13 @@ An :class:`IMAP4` instance has the following methods:
a *search_criterion* passed as :class:`str` is encoded to *charset*;
pass :class:`bytes` to send one already encoded.

This is an ``IMAP4rev1`` extension command.
If *params* is given, ``?`` placeholders in the search criteria are
substituted with the quoted parameters (see :ref:`the placeholders <imap4-params>`).

.. versionchanged:: next
Added the *uid* parameter.
This is an ``IMAP4rev1`` extension command.

.. versionchanged:: next
Added the *params* and *uid* parameters.
``str`` search criteria are encoded to *charset*.


Expand Down Expand Up @@ -745,7 +813,7 @@ An :class:`IMAP4` instance has the following methods:

typ, data = M.search(None, 'ALL')
for num in data[0].split():
M.store(num, '+FLAGS', '\\Deleted')
M.store(num, '+FLAGS', r'\Deleted')
M.expunge()

.. note::
Expand All @@ -768,7 +836,7 @@ An :class:`IMAP4` instance has the following methods:
Subscribe to new mailbox.


.. method:: IMAP4.thread(threading_algorithm, charset, search_criterion[, ...], *, uid=False)
.. method:: IMAP4.thread(threading_algorithm, charset, search_criterion[, ...], *, uid=False, params=None)

The ``thread`` command is a variant of ``search`` with threading semantics for
the results. Returned data contains a space separated list of thread members.
Expand All @@ -793,22 +861,30 @@ An :class:`IMAP4` instance has the following methods:
a *search_criterion* passed as :class:`str` is encoded to *charset*;
pass :class:`bytes` to send one already encoded.

This is an ``IMAP4rev1`` extension command.
If *params* is given, ``?`` placeholders in the search criteria are
substituted with the quoted parameters (see :ref:`the placeholders <imap4-params>`).

.. versionchanged:: next
Added the *uid* parameter.
This is an ``IMAP4rev1`` extension command.

.. versionchanged:: next
Added the *params* and *uid* parameters.
``str`` search criteria are encoded to *charset*.


.. method:: IMAP4.uid(command, arg[, ...])
.. method:: IMAP4.uid(command, arg[, ...], *, params=None)

Execute command args with messages identified by UID, rather than message
number. Returns response appropriate to command. At least one argument must be
supplied; if none are provided, the server will return an error and an exception
will be raised.

If *params* is given, ``?`` placeholders in the ``SEARCH``, ``SORT`` and
``THREAD`` criteria or in the ``FETCH`` parts are substituted with the quoted
parameters (see :ref:`the placeholders <imap4-params>`).

.. versionchanged:: next
Added the *params* parameter.


.. method:: IMAP4.unsubscribe(mailbox)

Expand Down
11 changes: 11 additions & 0 deletions Doc/whatsnew/3.16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,17 @@ imaplib
the criteria are sent using the connection encoding instead.
(Contributed by Serhiy Storchaka in :gh:`153494`.)

* Command methods now accept structured arguments,
so the module takes care of quoting instead of the caller.
A *message_set* and lists of flags or other atoms
can be passed as sequences instead of preformatted strings,
and the :meth:`~imaplib.IMAP4.search`, :meth:`~imaplib.IMAP4.fetch`,
:meth:`~imaplib.IMAP4.sort`, :meth:`~imaplib.IMAP4.thread` and
:meth:`~imaplib.IMAP4.uid` methods accept a *params* keyword argument
that substitutes and quotes ``?`` placeholders,
in the manner of :mod:`sqlite3` parameter substitution.
(Contributed by Serhiy Storchaka in :gh:`153521`.)


ipaddress
---------
Expand Down
Loading
Loading