Mover un correo electrónico en GMail con Python e imaplib


Quiero poder mover un correo electrónico en GMail desde la bandeja de entrada a otra carpeta usando Python. Estoy usando imaplib y no puedo averiguar cómo hacerlo.

Author: Manoj Govindan, 2010-08-20

5 answers

No hay un comando de movimiento explícito para IMAP. Tendrá que ejecutar un COPY seguido de un STORE (con la bandera adecuada para indicar la eliminación) y finalmente expunge. El ejemplo dado a continuación funcionó para mover mensajes de una etiqueta a la otra. Sin embargo, es probable que desee agregar más comprobación de errores.

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)
 36
Author: Manoj Govindan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-20 07:04:45

En cuanto a Gmail, basado en su api trabajando con etiquetas , lo único que puedes hacer es agregar la etiqueta dest y eliminar la etiqueta 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)
 5
Author: scraplesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-16 05:22:12

Supongo que uno tiene un uid del correo electrónico que se va a mover.

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()
 4
Author: Avadhesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-25 00:38:37

Ninguna de las soluciones anteriores funcionó para mí. Yo era incapaz de eliminar un mensaje de la carpeta seleccionada, y no se puede quitar la etiqueta de la carpeta cuando la etiqueta de la carpeta seleccionada. Esto es lo que terminó funcionando para mí:

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

user = "[email protected]"
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
 3
Author: Neal Young,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-07 04:03:55

Sé que esta es una pregunta muy antigua, pero de cualquier manera. La solución propuesta por Manoj Govindan probablemente funciona perfectamente (no la he probado, pero parece que sí. El problema que me encuentro y tuve que resolver es cómo copiar/mover más de un correo electrónico!!!

Así que se me ocurrió la solución, tal vez alguien más en el futuro podría tener el mismo problema.

Los pasos son simples, me conecto a mi cuenta de correo electrónico (GMAIL) elija la carpeta para procesar (por ejemplo, BANDEJA de ENTRADA) , en lugar de correo electrónico (s) número de lista. Este es un punto crucial a tener en cuenta aquí. Si obtuvimos el número de la lista de correos electrónicos y luego procesamos la lista, terminaríamos con un problema. Cuando movemos un correo electrónico el proceso es simple (copiar en la carpeta de destino y eliminar el correo electrónico de cada ubicación actual). El problema aparece si tiene una lista de correos electrónicos, por ejemplo, 4 correos electrónicos dentro de la bandeja de entrada y procesamos el segundo correo electrónico dentro de la lista, luego el número 3 y 4 son diferentes, no son los correos electrónicos que pensó que lo serían, lo que dará lugar a un error porque el elemento de la lista número 4 no existirá ya que la lista se movió una posición hacia abajo porque la posición 2 estaba vacía.

Así que la única solución posible a este problema era usar UIDs. Que son números únicos para cada correo electrónico. Así que no importa cómo cambie el correo electrónico, este número se vinculará con el correo electrónico.

Así que en el ejemplo a continuación, obtengo los UIDs en el primer paso, verifique si la carpeta está vacía no hay punto de procesamiento carpeta else iterar para todos los correos electrónicos que se encuentran en la carpeta. A continuación, obtenga cada encabezado de correo electrónico. Los encabezados nos ayudarán a buscar el Asunto y comparar el asunto del correo electrónico con el que estamos buscando. Si el asunto coincide, continúe copiando y borrando el correo electrónico. Entonces has terminado. Así de simple.

#!/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 = '[email protected]'
    password = 'examplePassword'
    main_dictionary = main(username, password, 'INBOX', 'BOKNING', 'TMP_FOLDER')
    pprint.pprint(main_dictionary)
    exit(0)

Información útil sobre imaplib Python - imaplib Ejemplo IMAP con Gmaily la documentación imaplib.

 0
Author: Thanos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-10 01:59:21