Excellent examples: Email via IMAP using Telent
To connect with Telnet …
telnet <hostname> 143
or to connect with SSL (recommended) …
openssl s_client -connect <hostname>:993
* OK Domino IMAP4 Server Release 10.0.1FP1 ready Wed, 24 Nov 2010 08:22:03 -0800 C A0001 LOGIN user@domain password S A0001 OK LOGIN completed C A0002 EXAMINE INBOX S * 507 EXISTS S * 0 RECENT S * OK [UNSEEN 344] Message 344 is first unseen S * OK [UIDVALIDITY 405] UIDs valid S * OK [UIDNEXT 596] Predicted next UID S * FLAGS (\Flagged \Seen \Answered \Deleted \Draft) S * OK [PERMANENTFLAGS ()] No permanent flags permitted S A0002 OK [READ-ONLY] EXAMINE completed
Legend: 'C' = data sent by client, 'S' = data sent by server
Notes:
CONNECT <hostname> command: mail = imaplib.IMAP4_SSL(hostname) object: <imaplib.IMAP4_SSL instance at 0x02586AD0> state: NONAUTH LOGIN <username> <password> Notes: username is user@domain command: typ, data = mail.login(username, getpass.getpass()) Password: typ: OK data: ['LOGIN completed'] state: AUTH EXAMINE Inbox command: typ, data = mbox.select(mailbox_name, True) typ: OK data: ['344'] state: SELECTED SEARCH All typ: OK data: ['1 2 3'] state: SELECTED FETCH 1 RFC2822 typ: OK data: [...] state: SELECTED CLOSE typ: OK data: ['CLOSE completed'] state: AUTH LOGOUT typ: BYE data: ['logging out'] state: LOGOUT
Set imaplib.Debug = 5 prior to creating an IMAP4 instance to see commands sent to the server, the responses and how the responses are parsed.
| imaplib.IMAP4([host[, port]]) | Connect to IMAP server, default port=123 |
| imaplib.IMAP4_SSL([host[, port[, keyfile[, certfile]]]]) | Connect to IMAP server over SSL, default port=993 |
| LOGIN | IMAP4.login(user, password) or IMAP4.login_cram_md5(user, password) | login with user@domain |
| AUTHENTICATE | IMAP4.authenticate(mechanism, authobject) | Indicates a SASL authentication mechanism on server (1) |
| STARTTLS | Not supported |
(1) If you don't know, then don't use the authenticate command, just LOGIN.
Browse, Select, Subscribe and CRUD for mailboxes.
| SELECT | IMAP4.select([mailbox]]) | Returns number of messages found in mailbox, to get the remaining information view IMAP4. # Exists |
| EXAMINE | IMAP4.select(mailbox, True) | |
| STATUS | IMAP4.status(mailbox, names) | |
| LIST | IMAP4.list([directory[, pattern]]) | |
| LSUB | IMAP4.lsub([directory[, pattern]]) | |
| CREATE | IMAP4.create(mailbox) | |
| DELETE | IMAP4.delete(mailbox) | |
| RENAME | IMAP4.rename(oldmailbox, newmailbox) | |
| SUBSCRIBE | IMAP4.subscribe(mailbox) | |
| UNSUBSCRIBE | IMAP4.unsubscribe(mailbox) |
pattern: supports wildcards * = match any character & descend path, % = match any character in current path
| FLAGS | Defined flags in mailbox |
| EXISTS | Number of messages in mailbox |
| RECENT | Number of messages with \Recent flag set |
| UNSEEN | Message number of first unseen message |
| PERMANENT FLAGS | A list of messages flags that client can change permanently |
| UIDNEXT | Next UID |
| UIDVALIDITY | UID validity value |
| CLOSE | IMAP4.close() |
| SEARCH | IMAP4.search(charset, criterion[, …]) |
| FETCH | IMAP4.fetch(message_set, message_parts) or IMAP4.partial(message_num, message_part, start, length) |
| STORE | IMAP4.store(message_set, command, flag_list) |
| EXPUNGE | IMAP4.expunge() |
| COPY | IMAP4.copy(message_set, new_mailbox) |
| CHECK | IMAP4.check() |
| UID | IMAP4.uid(command, arg[, …]) |
| LOGOUT | IMAP4.logout() |
| CAPABILITY | |
| NOOP |
imaplib requires that you enclose your search criterion in parentheses. '*' can be used as wildcard characters. Example IMAP4.search('(FROM “*yahoo.com”)') will search for all email from yahoo.com Returns message numbers matching the specified search criteria.
| ALL | Return all message numbers |
| OR search-key1 search-key2 | Return messages that match either search-key |
| NOT search-key | Exclude messages containing string |
| search-key1 search-key2 … | Equivalent to search-key1 AND search-key2 |
| TO <str> | Return messages with string in “To” header field |
| FROM <str> | Return messages with string in “From” header field |
| CC <str> | Return messages with string in “CC” header field |
| BCC <str> | Return messages with string in “BCC” header field |
| SUBJECT <str> | Return messages with string in “Body” of message |
| BODY <str> | Return messages with string in “Body” of message |
| TEXT <str> | Return messages with string in “Body” or any of the above header fields |
| Flag set | Flag NOT set | Description |
|---|---|---|
| ANSWERED | UNANSWERED | Return messages that have been replied to |
| DELETED | UNDELETED | Return deleted messages |
| DRAFT | UNDRAFT | Return draft message |
| FLAGGED | UNFLAGGED | Return flagged messages |
| NEW | OLD | Return recent messages |
| SEEN | UNSEEN | Return read messages |
Date Format: %d-%b-%Y Time Format: %H:%M:%S %z
| BEFORE <datet> | Return messages with an internal date before specified date |
| ON <date> | Return messages with an internal date on specified date |
| SINCE <date> | Return messages with an internal date on or after specified date |
| SENTBEFORE <date> | Return messages sent before specified date |
| SENTON <date> | Return messages sent on specified date/time |
| SENTSINCE <date> | Return messages sent on or after specified date/time |
| SMALLER <n> | Smaller than specified number of octets |
| LARGER <n> | Larger than specified number of octets |
Search flagged since 1-Feb-1994 NOT FROM "Smith"
Use “UID FETCH” if you want to fetch UID's instead of message sequence numbers.
| BODYSTRUCTURE | Perl BODYSTRUCTURE parser | |
| ENVELOPE | ||
| FLAGS | ||
| INTERNALDATE | internal date, not the sent date | |
| BODY [section] partial | Message body | |
| BODY.PEEK[section] partial | Does not set the \Seen flag, i.e. BODY.PEEK[2.1] | |
| ALL | same as FLAGS INTERNALDATE RFC822.SIZE ENVELOPE | |
| FAST | same as FLAGS INTERNALDATE RFC822.SIZE | |
| RFC822 | same as BODY[] | |
| RFC822.TEXT | same as BODY[TEXT] | |
| RFC822.HEADER | same as BODY.PEEK[HEADER] | headers = email.parser.HeaderParser().parsestr(data), treat headers like a dictionary |
| RFC822.SIZE | size of the message |
| data.walk() | will iterate through |
| get_filename() | |
| get_content_type() |
>>> for part in msg.walk(): ... print part.get_content_type() multipart/report text/plain message/delivery-status text/plain text/plain message/rfc822
Example:
FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)]) FETCH 1,3 BODY[2.MIME]
Sample body structure:
(158 (BODYSTRUCTURE (("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 17355 290 NIL NIL NIL)("image" "gif" ("name" "graycol.
"filename" "graycol.gif")) NIL)("image" "gif" ("name" "ecblank.gif") "<4__=07BBFD21DFC942328f98a93@domain.org>" "ecblank.gif" "base64" 64 NIL ("in
A60A5CDD5EFaocsvrmbx01jc_" "type" "text/plain") NIL ("en-US")))