Problema de codificação imprimível em e-mail python
Pergunta
Estou extraindo e -mails do Gmail usando o seguinte:
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()
No entanto, alguns e-mails que recebo são quase impossíveis para eu extrair datas (usando regex) de chars relacionados à codificação, como '=', aterrissam aleatoriamente no meio de vários campos de texto. Aqui está um exemplo em que ocorre em um intervalo que quero extrair:
Nome: Kirsti E -mail: kirsti@blah.blah Telefone #: + 999 99995192 Total no Partido: 4 Total, 0 Crianças Chegada/Partida: 9 de outubro de 2010 - 13 de outubro de 2010 - 13 de outubro de 2010, 2010
Existe uma maneira de remover esses personagens codificadores?
Solução
Você poderia/deve usar o email.parser
Módulo para decodificar mensagens de correio, por exemplo (exemplo rápido e sujo!):
from email.parser import FeedParser
f = FeedParser()
f.feed("<insert mail message here, including all headers>")
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
# (i.e. content) like so:
rootMessage.get_payload(0).get_payload(decode=True)
Usando o parâmetro "decodificar" de Message.get_payload
, o módulo decodifica automaticamente o conteúdo, dependendo da codificação (por exemplo, imprimíveis citados como em sua pergunta).
Outras dicas
Isso é conhecido como codificação imprimível com citado. Você provavelmente quer usar algo como quopri.decodestring
- http://docs.python.org/library/quapri.html
Se você estiver usando o python3.6 ou posterior, pode usar o email.message.Message.get_content()
Método para decodificar o texto automaticamente. Este método substitui get_payload()
, no entanto get_payload()
Ainda está disponível.
Diga que você tem uma corda s
contendo esta mensagem de email (com base no exemplos nos documentos):
Subject: Ayons asperges pour le =?utf-8?q?d=C3=A9jeuner?=
From: =?utf-8?q?Pep=C3=A9?= Le Pew <pepe@example.com>
To: Penelope Pussycat <penelope@example.com>,
Fabrette Pussycat <fabrette@example.com>
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
Caracteres não-ascii na string foram codificados com o quoted-printable
codificação, conforme especificado no Content-Transfer-Encoding
cabeçalho.
Crie um objeto de email:
import email
from email import policy
msg = email.message_from_string(s, policy=policy.default)
Definir a política é necessária aqui; por outro lado policy.compat32
é usado, que retorna uma instância de mensagem herdada que não possui o método get_content. policy.default
acabará se tornando a política padrão, mas a partir de python3.7 ainda é policy.compat32
.
o get_content()
O método lida com a decodificação automaticamente:
print(msg.get_content())
Salut!
Cela ressemble à un excellent recipie[1] déjeuner.
[1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718
--Pepé
Se você tem uma mensagem de múltiplas, get_content()
precisa ser chamado nas partes individuais, assim:
for part in message.iter_parts():
print(part.get_content())