Question

Je veux être en mesure de déplacer un e-mail dans GMail de la boîte de réception dans un autre dossier en utilisant Python. J'utilise imaplib et ne peut pas comprendre comment le faire.

Était-ce utile?

La solution

Il n'y a pas de commande de mouvement explicite pour IMAP. Vous devrez exécuter un COPY suivi d'un STORE (avec le drapeau approprié pour indiquer la suppression) et enfin expunge. L'exemple ci-dessous a travaillé pour le déplacement des messages d'une étiquette à l'autre. Vous aurez probablement envie d'ajouter le contrôle d'erreur si.

import imaplib, getpass, re
pattern_uid = re.compile('\d+ \(UID (?P<uid>\d+)\)')

def connect(email):
    imap = imaplib.IMAP4_SSL("imap.gmail.com")
    password = getpass.getpass("Enter your password: ")
    imap.login(email, password)
    return imap

def disconnect(imap):
    imap.logout()

def parse_uid(data):
    match = pattern_uid.match(data)
    return match.group('uid')

if __name__ == '__main__':
    imap = connect('<your mail id>')
    imap.select(mailbox = '<source folder>', readonly = False)
    resp, items = imap.search(None, 'All')
    email_ids  = items[0].split()
    latest_email_id = email_ids[-1] # Assuming that you are moving the latest email.

    resp, data = imap.fetch(latest_email_id, "(UID)")
    msg_uid = parse_uid(data[0])

    result = imap.uid('COPY', msg_uid, '<destination folder>')

    if result[0] == 'OK':
        mov, data = imap.uid('STORE', msg_uid , '+FLAGS', '(\Deleted)')
        imap.expunge()

    disconnect(imap)

Autres conseils

En ce qui concerne Gmail, basé sur son api travail avec des étiquettes , la seule chose que vous puissiez faire est d'ajouter l'étiquette dest et la suppression de l'étiquette src:

import imaplib
obj = imaplib.IMAP4_SSL('imap.gmail.com', 993)
obj.login('username', 'password')
obj.select(src_folder_name)
typ, data = obj.uid('STORE', msg_uid, '+X-GM-LABELS', desti_folder_name)
typ, data = obj.uid('STORE', msg_uid, '-X-GM-LABELS', src_folder_name)

Je suppose que l'on a un uid de l'e-mail qui va être déplacé.

import imaplib
obj = imaplib.IMAP4_SSL('imap.gmail.com', 993)
obj.login('username', 'password')
obj.select(src_folder_name)
apply_lbl_msg = obj.uid('COPY', msg_uid, desti_folder_name)
if apply_lbl_msg[0] == 'OK':
    mov, data = obj.uid('STORE', msg_uid , '+FLAGS', '(\Deleted)')
    obj.expunge()

Aucune des solutions précédentes travaillé pour moi. Je ne pouvais pas supprimer un message du dossier sélectionné, et incapable de retirer l'étiquette du dossier lorsque l'étiquette était le dossier sélectionné. Voici ce qui a fini par travailler pour moi:

import email, getpass, imaplib, os, sys, re

user = "user@example.com"
pwd = "password" #getpass.getpass("Enter your password: ")

m = imaplib.IMAP4_SSL("imap.gmail.com")
m.login(user,pwd)

from_folder = "Notes"
to_folder = "food"

m.select(from_folder, readonly = False)

response, emailids = imap.search(None, 'All')
assert response == 'OK'

emailids = emailids[0].split()

errors = []
labeled = []
for emailid in emailids:
    result = m.fetch(emailid, '(X-GM-MSGID)')
    if result[0] != 'OK':
        errors.append(emailid)
        continue

    gm_msgid = re.findall(r"X-GM-MSGID (\d+)", result[1][0])[0]

    result = m.store(emailid, '+X-GM-LABELS', to_folder)

    if result[0] != 'OK':
        errors.append(emailid)
        continue

    labeled.append(gm_msgid)

m.close()
m.select(to_folder, readonly = False)

errors2 = []

for gm_msgid in labeled:
    result = m.search(None, '(X-GM-MSGID "%s")' % gm_msgid)

    if result[0] != 'OK':
        errors2.append(gm_msgid)
        continue

    emailid = result[1][0]
    result = m.store(emailid, '-X-GM-LABELS', from_folder)

    if result[0] != 'OK':
        errors2.append(gm_msgid)
        continue

m.close()
m.logout()

if errors: print >>sys.stderr, len(errors), "failed to add label", to_folder
if errors2: print >>sys.stderr, len(errors2), "failed to remove label", from_folder

Je sais que cela est une question très ancienne, mais aucune façon. La solution proposée par Manoj Govindan fonctionne probablement parfaitement (je ne l'ai pas testé, mais il semble que ça. Le problème Je rencontre et je devais résoudre est comment copier / déplacer plus d'un e-mail !!!

Alors je suis venu avec une solution, peut-être quelqu'un d'autre à l'avenir pourrait avoir le même problème.

Les étapes sont simples, je me connecte à mon e-mail (GMAIL) compte choisir le dossier à traiter (par exemple INBOX) chercher tous uids, au lieu du courrier électronique (s) numéro de la liste. Ce point est crucial de remarquer ici. Si nous allés chercher le numéro de la liste des e-mails, puis nous avons traité la liste, nous finirons avec un problème. Lorsque nous nous déplaçons un e-mail le processus est simple (copie au dossier de destination et le courrier électronique de suppression à partir de chaque emplacement actuel). Le problème apparaît si vous avez une liste d'e-mails par exemple 4 e-mails à l'intérieur de la boîte de réception et nous traitons le 2ème e-mail à l'intérieur de la liste puis le numéro 3 et 4 sont différents, ils ne sont pas les e-mails que nous avons pensé qu'ils seraient, ce qui se traduira en une erreur, car le nombre d'élément de liste 4 il ne sera pas existe depuis la liste déplacée d'une position vers le bas parce que la position 2 était vide.

Alors la seule solution possible à ce problème est d'utiliser UIDs. Quelles sont les numéros uniques pour chaque e-mail. Donc, peu importe la façon dont sera binded l'e-mail va changer ce numéro avec l'e-mail.

Ainsi, dans l'exemple ci-dessous, je récupérer les UIDs sur la première étape, vérifiez si le dossier est vide aucun point de traitement du dossier autre itérer pour tous les e-mails trouvés dans le dossier. chercher Suivant chaque e-mail en-tête. Les en-têtes nous aideront à aller chercher le sujet et comparer le sujet de l'email avec celui que nous recherchons. Si les matches de sujet, puis continuer à copier et supprimer l'e-mail. Ensuite, vous avez terminé. Aussi simple que cela.

#!/usr/bin/env python

import email
import pprint
import imaplib

__author__ = 'author'


def initialization_process(user_name, user_password, folder):
    imap4 = imaplib.IMAP4_SSL('imap.gmail.com')  # Connects over an SSL encrypted socket
    imap4.login(user_name, user_password)
    imap4.list()  # List of "folders" aka labels in gmail
    imap4.select(folder)  # Default INBOX folder alternative select('FOLDER')
    return imap4


def logout_process(imap4):
    imap4.close()
    imap4.logout()
    return


def main(user_email, user_pass, scan_folder, subject_match, destination_folder):
    try:
        imap4 = initialization_process(user_email, user_pass, scan_folder)
        result, items = imap4.uid('search', None, "ALL")  # search and return uids
        dictionary = {}
        if items == ['']:
            dictionary[scan_folder] = 'Is Empty'
        else:
            for uid in items[0].split():  # Each uid is a space separated string
                dictionary[uid] = {'MESSAGE BODY': None, 'BOOKING': None, 'SUBJECT': None, 'RESULT': None}
                result, header = imap4.uid('fetch', uid, '(UID BODY[HEADER])')
                if result != 'OK':
                    raise Exception('Can not retrieve "Header" from EMAIL: {}'.format(uid))
                subject = email.message_from_string(header[0][1])
                subject = subject['Subject']
                if subject is None:
                    dictionary[uid]['SUBJECT'] = '(no subject)'
                else:
                    dictionary[uid]['SUBJECT'] = subject
                if subject_match in dictionary[uid]['SUBJECT']:
                    result, body = imap4.uid('fetch', uid, '(UID BODY[TEXT])')
                    if result != 'OK':
                        raise Exception('Can not retrieve "Body" from EMAIL: {}'.format(uid))
                    dictionary[uid]['MESSAGE BODY'] = body[0][1]
                    list_body = dictionary[uid]['MESSAGE BODY'].splitlines()
                    result, copy = imap4.uid('COPY', uid, destination_folder)
                    if result == 'OK':
                        dictionary[uid]['RESULT'] = 'COPIED'
                        result, delete = imap4.uid('STORE', uid, '+FLAGS', '(\Deleted)')
                        imap4.expunge()
                        if result == 'OK':
                            dictionary[uid]['RESULT'] = 'COPIED/DELETED'
                        elif result != 'OK':
                            dictionary[uid]['RESULT'] = 'ERROR'
                            continue
                    elif result != 'OK':
                        dictionary[uid]['RESULT'] = 'ERROR'
                        continue
                else:
                    print "Do something with not matching emails"
                    # do something else instead of copy
            dictionary = {scan_folder: dictionary}
    except imaplib.IMAP4.error as e:
        print("Error, {}".format(e))
    except Exception as e:
        print("Error, {}".format(e))
    finally:
        logout_process(imap4)
        return dictionary

if __name__ == "__main__":
    username = 'example.email@gmail.com'
    password = 'examplePassword'
    main_dictionary = main(username, password, 'INBOX', 'BOKNING', 'TMP_FOLDER')
    pprint.pprint(main_dictionary)
    exit(0)

Informations utiles concernant imaplib Python - imaplib exemple IMAP avec Gmail et imaplib documentation .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top