Problema de encoding imprimible entre el correo electrónico de Python

Estoy extrayendo correos electrónicos de Gmail utilizando lo siguiente:

def getMsgs(): try: conn = imaplib.IMAP4_SSL("imap.gmail.com", 993) except: print 'Failed to connect' print 'Is your internet connection working?' sys.exit() try: conn.login(username, password) except: print 'Failed to login' print 'Is the username and password correct?' sys.exit() conn.select('Inbox') # typ, data = conn.search(None, '(UNSEEN SUBJECT "%s")' % subject) typ, data = conn.search(None, '(SUBJECT "%s")' % subject) for num in data[0].split(): typ, data = conn.fetch(num, '(RFC822)') msg = email.message_from_string(data[0][1]) yield walkMsg(msg) def walkMsg(msg): for part in msg.walk(): if part.get_content_type() != "text/plain": continue return part.get_payload() 

Sin embargo, algunos correos electrónicos que recibo son casi imposibles para mí de extraer fechas (utilizando expresiones regulares) de caracteres relacionados con la encoding, como ‘=’, que aparecen aleatoriamente en medio de varios campos de texto. Aquí hay un ejemplo donde ocurre en un rango de fechas que quiero extraer:

Nombre: KIRSTI Correo electrónico: kirsti@blah.blah Teléfono: + 999 99995192 Total en la fiesta: 4 en total, 0 niños Llegada / Salida: 9 de octubre =, 2010 – 13 de octubre de 2010 – 13 de octubre de 2010

¿Hay alguna manera de eliminar estos caracteres de encoding?

Podría / debería usar el módulo email.parser para decodificar mensajes de correo, por ejemplo (¡ejemplo rápido y sucio!):

 from email.parser import FeedParser f = FeedParser() f.feed("") rootMessage = f.close() # Now you can access the message and its submessages (if it's multipart) print rootMessage.is_multipart() # Or check for errors print rootMessage.defects # If it's a multipart message, you can get the first submessage and then its payload # (ie content) like so: rootMessage.get_payload(0).get_payload(decode=True) 

Usando el parámetro “deencoding” de Message.get_payload , el módulo descodifica automáticamente el contenido, dependiendo de su encoding (por ejemplo, imprimibles citados como en su pregunta).

Eso se conoce como encoding imprimible entre comillas. Probablemente quiera usar algo como quopri.decodestringhttp://docs.python.org/library/quopri.html

Si está utilizando Python3.6 o posterior, puede usar el método email.message.Message.get_content() para decodificar el texto automáticamente. Este método reemplaza a get_payload() , aunque get_payload() todavía está disponible.

Supongamos que tiene una cadena que contiene este mensaje de correo electrónico (según los ejemplos en los documentos):

 Subject: Ayons asperges pour le =?utf-8?q?d=C3=A9jeuner?= From: =?utf-8?q?Pep=C3=A9?= Le Pew  To: Penelope Pussycat , Fabrette Pussycat  Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Salut! Cela ressemble =C3=A0 un excellent recipie[1] d=C3=A9jeuner. [1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718 --Pep=C3=A9 =20 

Los caracteres que no son ASCII en la cadena se han codificado con la encoding impresa entre quoted-printable , como se especifica en el encabezado Content-Transfer-Encoding .

Crear un objeto de correo electrónico:

 import email from email import policy msg = email.message_from_string(s, policy=policy.default) 

Aquí es necesario establecer la política; de lo policy.compat32 se usa policy.compat32 , que devuelve una instancia de Mensaje heredada que no tiene el método get_content. policy.default eventualmente se convertirá en la política predeterminada, pero a partir de Python3.7 sigue siendo policy.compat32 .

El método get_content() maneja la deencoding automáticamente:

 print(msg.get_content()) Salut! Cela ressemble à un excellent recipie[1] déjeuner. [1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718 --Pepé 

Si tiene un mensaje de get_content() partes, debe llamarse a get_content() en las partes individuales, como esto:

 for part in message.iter_parts(): print(part.get_content())