用python smtplib转发电子邮件

时间:2021-04-16 18:09:32

I'm trying to put together a script that automatically forwards certain emails that match a specific criteria to another email.

我正在尝试编写一个脚本,自动将符合特定条件的特定电子邮件转发到另一封电子邮件。

I've got the downloading and parsing of messages using imaplib and email working, but I can't figure out how to forward an entire email to another address. Do I need to build a new message from scratch, or can I somehow modify the old one and re-send it?

我使用imaplib下载和解析消息,并使用电子邮件,但我不知道如何将整个电子邮件转发到另一个地址。我是否需要从头构建一个新的消息,或者我是否可以修改旧的消息并重新发送它?

Here's what I have so far (client is an imaplib.IMAP4 connection, and id is a message ID):

这是我目前所拥有的(客户端是imaplib)。IMAP4连接,id为消息id):

import smtplib, imaplib

smtp = smtplib.SMTP(host, smtp_port)
smtp.login(user, passw)

client = imaplib.IMAP4(host)
client.login(user, passw)
client.select('INBOX')

status, data = client.fetch(id, '(RFC822)')
email_body = data[0][1]
mail = email.message_from_string(email_body)

# ...Process message...

# This doesn't work
forward = email.message.Message()
forward.set_payload(mail.get_payload())
forward['From'] = 'source.email.address@domain.com'
forward['To'] = 'my.email.address@gmail.com'

smtp.sendmail(user, ['my.email.address@gmail.com'], forward.as_string())

I'm sure there's something slightly more complicated I need to be doing with regard to the MIME content of the message. Surely there's some simple way of just forwarding the entire message though?

我确信,对于消息的MIME内容,我还需要做一些稍微复杂一点的事情。不过,肯定有什么简单的方法可以转发整个消息吗?

# This doesn't work either, it just freezes...?
mail['From'] = 'source.email.address@domain.com'
mail['To'] = 'my.email.address@gmail.com'
smtp.sendmail(user, ['my.email.address@gmail.com'], mail.as_string())

2 个解决方案

#1


17  

I think the part you had wrong was how to replace the headers in the message, and the fact that you don't need to make a copy of the message, you can just operate directly on it after creating it from the raw data you fetched from the IMAP server.

我认为您的错误之处在于如何替换消息中的头,而且您不需要复制消息,您可以在从IMAP服务器获取原始数据后直接对其进行操作。

You did omit some detail so here's my complete solution with all details spelled out. Note that I'm putting the SMTP connection in STARTTLS mode since I need that and note that I've separated the IMAP phase and the SMTP phase from each other. Maybe you thought that altering the message would somehow alter it on the IMAP server? If you did, this should show you clearly that that doesn't happen.

您确实省略了一些细节,所以这是我的完整的解决方案,所有的细节都说明了。注意,由于需要,我将SMTP连接放在STARTTLS模式中,并注意我已经将IMAP阶段和SMTP阶段彼此分离。也许您认为更改消息会在IMAP服务器上以某种方式更改消息?如果你这么做了,这应该能清楚地告诉你,这不会发生。

import smtplib, imaplib, email

imap_host = "mail.example.com"
smtp_host = "mail.example.com"
smtp_port = 587
user = "xyz"
passwd = "xyz"
msgid = 7
from_addr = "from.me@example.com"
to_addr = "to.you@example.com"

# open IMAP connection and fetch message with id msgid
# store message data in email_data
client = imaplib.IMAP4(imap_host)
client.login(user, passwd)
client.select('INBOX')
status, data = client.fetch(msgid, "(RFC822)")
email_data = data[0][1]
client.close()
client.logout()

# create a Message instance from the email data
message = email.message_from_string(email_data)

# replace headers (could do other processing here)
message.replace_header("From", from_addr)
message.replace_header("To", to_addr)

# open authenticated SMTP connection and send message with
# specified envelope from and to addresses
smtp = smtplib.SMTP(smtp_host, smtp_port)
smtp.starttls()
smtp.login(user, passwd)
smtp.sendmail(from_addr, to_addr, message.as_string())
smtp.quit()

Hope this helps even if this answer comes quite late.

希望这能有所帮助,即使这个答案来得很晚。

#2


0  

In one application I download messages via POP3 (using poplib) and forward them using your second method... That is, I alter To/From on the original Message and send it, and it works.
Have you tried poking inside smtp.sendmail to see where it stops?

在一个应用程序中,我通过POP3(使用poplib)下载消息并使用您的第二个方法转发它们……也就是说,我对原始消息进行修改并发送它,它就工作了。你试过在smtp里面戳吗?寄邮件去看它停在哪里?

#1


17  

I think the part you had wrong was how to replace the headers in the message, and the fact that you don't need to make a copy of the message, you can just operate directly on it after creating it from the raw data you fetched from the IMAP server.

我认为您的错误之处在于如何替换消息中的头,而且您不需要复制消息,您可以在从IMAP服务器获取原始数据后直接对其进行操作。

You did omit some detail so here's my complete solution with all details spelled out. Note that I'm putting the SMTP connection in STARTTLS mode since I need that and note that I've separated the IMAP phase and the SMTP phase from each other. Maybe you thought that altering the message would somehow alter it on the IMAP server? If you did, this should show you clearly that that doesn't happen.

您确实省略了一些细节,所以这是我的完整的解决方案,所有的细节都说明了。注意,由于需要,我将SMTP连接放在STARTTLS模式中,并注意我已经将IMAP阶段和SMTP阶段彼此分离。也许您认为更改消息会在IMAP服务器上以某种方式更改消息?如果你这么做了,这应该能清楚地告诉你,这不会发生。

import smtplib, imaplib, email

imap_host = "mail.example.com"
smtp_host = "mail.example.com"
smtp_port = 587
user = "xyz"
passwd = "xyz"
msgid = 7
from_addr = "from.me@example.com"
to_addr = "to.you@example.com"

# open IMAP connection and fetch message with id msgid
# store message data in email_data
client = imaplib.IMAP4(imap_host)
client.login(user, passwd)
client.select('INBOX')
status, data = client.fetch(msgid, "(RFC822)")
email_data = data[0][1]
client.close()
client.logout()

# create a Message instance from the email data
message = email.message_from_string(email_data)

# replace headers (could do other processing here)
message.replace_header("From", from_addr)
message.replace_header("To", to_addr)

# open authenticated SMTP connection and send message with
# specified envelope from and to addresses
smtp = smtplib.SMTP(smtp_host, smtp_port)
smtp.starttls()
smtp.login(user, passwd)
smtp.sendmail(from_addr, to_addr, message.as_string())
smtp.quit()

Hope this helps even if this answer comes quite late.

希望这能有所帮助,即使这个答案来得很晚。

#2


0  

In one application I download messages via POP3 (using poplib) and forward them using your second method... That is, I alter To/From on the original Message and send it, and it works.
Have you tried poking inside smtp.sendmail to see where it stops?

在一个应用程序中,我通过POP3(使用poplib)下载消息并使用您的第二个方法转发它们……也就是说,我对原始消息进行修改并发送它,它就工作了。你试过在smtp里面戳吗?寄邮件去看它停在哪里?