Como respondo a um email usando o python iMaplib e incluo a mensagem original?
Pergunta
Estou usando atualmente imaplib
Para buscar mensagens de email de um servidor e processar o conteúdo e os anexos.
Gostaria de responder às mensagens com uma mensagem de status/erro e links para o conteúdo gerado resultante no meu site, se eles puderem ser processados. Isso deve incluir a mensagem original, mas deve soltar qualquer anexo (que será grande) e, de preferência, substitua -os apenas por seus nomes de arquivos/tamanhos.
Como já estou andando nas peças da mensagem MIME, estou assumindo o que preciso fazer é criar uma nova árvore de mensagens MIME contendo uma cópia da mensagem original e excluir/substituir os nós de anexo.
Antes de começar esse caminho, eu esperava que alguém pudesse me dar algumas dicas. Existe algum tipo de função da biblioteca para fazer isso? Qualquer tipo de comportamento padrão que eu deveria manter?
Atualmente eu conheço/estou usando o imaplib
, smtplib
e email
módulos e, mas pode ter perdido algo óbvio lá. Isso também está sendo executado em Django, então pode usar qualquer coisa em django.core.email
Se isso facilita.
Solução
A estrutura de árvore mímica original da mensagem de entrada é a seguinte (usando email.iterators._structure(msg)
):
multipart/mixed
text/html (message)
application/octet-stream (attachment 1)
application/octet-stream (attachment 2)
Responder via Gmail resulta na seguinte estrutura:
multipart/alternative
text/plain
text/html
Ou seja, eles não estão sendo tão inteligentes quanto eu pensava, apenas descartando os anexos (bons) e fornecendo versões de texto e HTML que reestruturam explicitamente o "conteúdo citado".
Estou começando a pensar que é tudo o que eu deveria fazer também, basta responder com uma mensagem simples, pois depois de descartar os anexos, não há muito sentido em manter a mensagem original.
Ainda assim, poderia muito bem responder à minha pergunta original, pois eu descobri como agora.
Primeiro, substitua todos os anexos na mensagem original por texto/espaço livre comum:
import email
original = email.message_from_string( ... )
for part in original.walk():
if (part.get('Content-Disposition')
and part.get('Content-Disposition').startswith("attachment")):
part.set_type("text/plain")
part.set_payload("Attachment removed: %s (%s, %d bytes)"
%(part.get_filename(),
part.get_content_type(),
len(part.get_payload(decode=True))))
del part["Content-Disposition"]
del part["Content-Transfer-Encoding"]
Em seguida, crie uma mensagem de resposta:
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.message import MIMEMessage
new = MIMEMultipart("mixed")
body = MIMEMultipart("alternative")
body.attach( MIMEText("reply body text", "plain") )
body.attach( MIMEText("<html>reply body text</html>", "html") )
new.attach(body)
new["Message-ID"] = email.utils.make_msgid()
new["In-Reply-To"] = original["Message-ID"]
new["References"] = original["Message-ID"]
new["Subject"] = "Re: "+original["Subject"]
new["To"] = original["Reply-To"] or original["From"]
new["From"] = "me@mysite.com"
Em seguida, anexe o objeto de mensagem MIME original e envie:
new.attach( MIMEMessage(original) )
s = smtplib.SMTP()
s.sendmail("me@mysite.com", [new["To"]], new.as_string())
s.quit()
A estrutura resultante é:
multipart/mixed
multipart/alternative
text/plain
text/html
message/rfc822
multipart/mixed
text/html
text/plain
text/plain
Ou é um pouco mais simples usando Django:
from django.core.mail import EmailMultiAlternatives
from email.mime.message import MIMEMessage
new = EmailMultiAlternatives("Re: "+original["Subject"],
"reply body text",
"me@mysite.com", # from
[original["Reply-To"] or original["From"]], # to
headers = {'Reply-To': "me@mysite.com",
"In-Reply-To": original["Message-ID"],
"References": original["Message-ID"]})
new.attach_alternative("<html>reply body text</html>", "text/html")
new.attach( MIMEMessage(original) ) # attach original message
new.send()
O resultado termina (pelo menos no Gmail) mostrando a mensagem original como "---- Mensagem encaminhada ----", o que não é exatamente o que eu estava procurando, mas a ideia geral funciona e espero Descubra como mexer com mensagens MIME.