leer - Mueve un correo electrónico en GMail con Python e imaplib
python imaplib append example (5)
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.
En cuanto a Gmail, basado en su api que trabaja con etiquetas , lo único que puede 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)
Ninguna de las soluciones anteriores funcionó para mí. No pude eliminar un mensaje de la carpeta seleccionada, y no pude eliminar la etiqueta de la carpeta cuando la etiqueta era la carpeta seleccionada. Esto es lo que terminó trabajando 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
Sé que esta es una pregunta muy antigua, pero de cualquier manera. La solución propuesta por probablemente funciona a la perfección (no la he probado, pero parece que sí. ¡El problema que encuentro y que tuve que resolver es cómo copiar / mover más de un correo electrónico!)
Así que se me ocurrió una 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) y selecciono la carpeta para procesar (por ejemplo, INBOX) para obtener todos los números de usuario, en lugar del número de lista de correo electrónico. Este es un punto crucial para notar aquí. Si obtuviéramos el número de la lista de correos electrónicos y luego procesáramos 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, los números 3 y 4 son diferentes, no son los correos electrónicos que pensamos que serían, lo que resultará en un error porque la lista número de elemento 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. Cuales son los 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.
Entonces, en el ejemplo a continuación, obtengo los UID en el primer paso, compruebo si la carpeta está vacía, no tiene sentido procesar la carpeta; de lo contrario, repase todos los correos electrónicos encontrados en la carpeta. A continuación, busque 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 eliminando el correo electrónico. Entonces has terminado. Simple como eso.
#!/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 Ejemplo de Python - imaplib IMAP con Gmail y la documentación de imaplib .
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()
No hay un comando de movimiento explícito para IMAP. Deberá ejecutar una COPY
seguida de una STORE
(con un indicador adecuado para indicar la eliminación) y, finalmente, expunge
. El siguiente ejemplo sirve para mover mensajes de una etiqueta a otra. Sin embargo, es probable que desees agregar más comprobaciones 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)