Python et IMAP : Exemples concrets

Commençons par nous connecter à la boîte de messagerie :

from imaplib import IMAP4_SSL as IMAP
from socket import gaierror

# Configuration
server = "mail.gandi.net"
user = "username@domain"
password = "password"

# Connexion au serveur
try:
    conn = IMAP(server)
    conn.login(user, password)
    conn.select()
except gaierror:
    # Le serveur est erroné ou injoignable
    raise
except IMAP.error:
    # Problème d'identification !
    # L'utilisateur et mot de passe sont-ils corrects ?
    raise

Astuce

imaplib.IMAP4.select() permet de sélectionner le dossier où sont stockés les messages. Par défaut, on ne passe aucun argument, mais pour Gmail, on pourrait utiliser conn.select("Inbox").

Nous allons maintenant récupérer les identifiants des messages non lus. Pour faire les choses correctement, nous utiliserons la commande imaplib.IMAP4.uid() qui fonctionne avec des identifiants uniques pour chaque message.

ret, data = conn.uid("search", "", "(UNSEEN)")
if ret == "OK":
    uids = data[0].split()

uids contiendra, par exemple, [b'9263', b'9264', b'9265'].

Pour finir, avec ces identifiants, téléchargeons le contenu des messages :

for uid in uids:
    ret, data = conn.uid("fetch", uid, "(BODY[TEXT])")
    if ret == "OK":
        body = data[0][1]

Attention

Du moment que la commande imaplib.IMAP4.fetch() est utilisée, le message concerné est marqué comme lu.


Commandes en Vrac

Marquer un message comme lu

conn.uid("store", uid, "+FLAGS", "(\\Seen)")

Marquer plusieurs messages comme lus

conn.uid("store", ",".join(uids), "+FLAGS", "(\\Seen)")

Marquer un message comme non lu

conn.uid("store", uid, "-FLAGS", "(\\Seen)")

Récupérer les messages non lus et ayant un sujet particulier

ret, data = conn.uid("search", "", '(UNSEEN SUBJECT "Foo bar")')
if ret == "OK":
    uids = data[0].split()

Récupérer les messages d’un certain émetteur

ret, data = conn.uid("search", "", '(FROM "alice@example.org")')
if ret == "OK":
    uids = data[0].split()

Récupérer les messages pour un certain destinataire

ret, data = conn.uid("search", "", '(TO "bob@example.org")')
if ret == "OK":
    uids = data[0].split()

Récupérer les messages d’un certain émetteur pour un certain destinataire

ret, data = conn.uid("search", "", '(FROM "alice@example.org" TO "bob@example.org")')
if ret == "OK":
    uids = data[0].split()

Récupérer les messages à partir d’une certaine date et ayant un sujet particulier

from datetime import datetime

day = "2016-09-06"
since = datetime.strptime(day, "%Y-%m-%d").astimezone().strftime("%d-%b-%Y")
look_for = f'(SENTSINCE {since} SUBJECT "Foo bar")'
ret, data = conn.uid("search", "", look_for)
if ret == "OK":
    uids = data[0].split()

Gmail : récupérer les messages contenant une pièce jointe

ret, data = conn.uid("search", "", '(X-GM-RAW "has:attachment")')
if ret == "OK":
    uids = data[0].split()

Supprimer un ou plusieurs messages

conn.uid("store", uids, "+FLAGS", "\\Deleted")
conn.expunge()

Copier un ou plusieurs messages

folder = "archives-personal"
conn.uid("copy", uids, folder)

Déplacer un ou plusieurs messages

La commande MOVE n’existe pas ; pour l’émuler, if faut faire une copie puis supprimer les originaux :

folder = "archives-personal"
conn.uid("copy", uids, folder)
conn.uid("store", uids, "+FLAGS", "\\Deleted")
conn.expunge()

🎣 Sources

📜 Historique

2024-02-01

Déplacement de l’article depuis le blog.

2018-09-23

Ajout de l’exemple Supprimer un ou plusieurs messages.

Ajout de l’exemple Copier un ou plusieurs messages.

Ajout de l’exemple Déplacer un ou plusieurs messages.

2016-09-06

Ajout de l’exemple Marquer plusieurs messages comme lus.

Ajout de l’exemple Récupérer les messages d’un certain émetteur.

Ajout de l’exemple Récupérer les messages pour un certain destinataire.

Ajout de l’exemple Récupérer les messages d’un certain émetteur pour un certain destinataire.

Ajout de l’exemple Récupérer les messages à partir d’une certaine date et ayant un sujet particulier.

Ajout de l’exemple Gmail : récupérer les messages contenant une pièce jointe.

2016-01-21

Premier jet.