search criteria of IMAP protocol search command

Question:

I read from here:

http://docs.python.org/2/library/imaplib.html
IMAP4.search(charset, criterion[, ...])

that imaplib has the search method for me to search mails from my mail boxes.

But I don’t understand what criterion are available, or is it that I can enter anything for it?

I searched that page,, but didn’t get a clue.

Asked By: Jilin

||

Answers:

I’m not sure how Python expects the criteria but I’m assuming it’s the same as plain IMAP. Refer to the SEARCH command documentation (as larsks already suggested) and use a combination of keywords depending on what you want to retrieve. Examples of criteria:

SUBJECT Christmas

…retrieves messages containing "Christmas" in the subject line.

SUBJECT "New York"

…retrieves messages containing "New York" (without quotes) in the subject line.

OR TO boss SUBJECT resignation

…is to be read as (TO boss) OR (SUBJECT resignation) and will retrieve messages that either have "boss" in the "To" field or contain "resignation" in the subject line.

As you can see above, IMAP Search uses a prefix notation in its criteria that may at first be confusing. You can reason about them using brackets or else by graphically drawing a tree of criteria – especially useful when you get nested ANDs or ORs.

There is a fair amount of different criteria you can use. Refer to the RFC for the whole list.

It may be helpful to interact with IMAP manually (e.g. using telnet) to get used to the structure of SEARCH requests before you spend time coding it.

Answered By: Gigi

You may use imap_tools package:
https://pypi.org/project/imap-tools/

Implemented the search logic described in rfc3501.

from imap_tools import Q, AND, OR, NOT
# base
mailbox.fetch('TEXT "hello"')  # str
mailbox.fetch(b'TEXT "xd1x8f"')  # bytes
mailbox.fetch(Q(subject='weather'))  # query, the str-like object
# AND
Q(text='hello', new=True)  # 'TEXT "hello" NEW'
# OR
OR(text='hello', date=datetime.date(2000, 3, 15))  # '(OR TEXT "hello" ON 15-Mar-2000)'
# NOT
NOT(text='hello', new=True)  # '(NOT TEXT "hello" NEW)'
# complex:
# 'TO "[email protected]" (OR FROM "[email protected]" TEXT "\"the text\"") (NOT (OR UNANSWERED NEW))')
Q(OR(from_='[email protected]', text='"the text"'), NOT(OR(Q(answered=False), Q(new=True))), to='[email protected]')
# encoding
mailbox.fetch(Q(subject='привет'), charset='utf8')  # 'привет' will be encoded by MailBox._criteria_encoder

see docs for more info.

Answered By: Vladimir

You can find the list of available criteria here: https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4

I’m the author of Red Box (IMAP library) and I wrote the options down here as well: https://red-box.readthedocs.io/en/stable/tutorials/query_fields.html

If you wish to use Red Box for the problem, here’s how it works. First configure the email box:

from redbox import EmailBox

# Create email box instance
box = EmailBox(
    host="imap.example.com", 
    port=993,
    username="[email protected]",
    password="<PASSWORD>"
)

# Select an email folder
inbox = box["INBOX"]

Then search for messages:

from redbox.query import SEEN, FROM

# Search and process messages
for msg in inbox.search(SEEN & (FROM("[email protected]") | SUBJECT("[email protected]"))):
    # Process the message
    print(msg)

You can also pass the raw search query as string if you prefer that. More about querying here and more about manipulating the messages.

Links:

Answered By: miksus
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.