经过大量的搜索,我无法找到如何使用smtplib。发送邮件到多个收件人。问题是每次发送邮件时,邮件标题似乎包含多个地址,但实际上只有第一个收件人会收到电子邮件。

问题似乎出在邮件上。Message模块期望与smtplb .sendmail()函数不同的内容。

简而言之,要发送给多个收件人,您应该将标题设置为一串以逗号分隔的电子邮件地址。sendmail()参数to_addr应该是一个电子邮件地址列表。

from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
import smtplib

msg = MIMEMultipart()
msg["Subject"] = "Example"
msg["From"] = "me@example.com"
msg["To"] = "malcom@example.com,reynolds@example.com,firefly@example.com"
msg["Cc"] = "serenity@example.com,inara@example.com"
body = MIMEText("example email body")
msg.attach(body)
smtp = smtplib.SMTP("mailhost.example.com", 25)
smtp.sendmail(msg["From"], msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
smtp.quit()

当前回答

对于那些希望只发送一个“to”报头的消息,下面的代码可以解决这个问题。确保你的接收者变量是一个字符串列表。

# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = title
msg['From'] = f'support@{config("domain_base")}'
msg['To'] =  "me"
message_content += f"""
    <br /><br />
    Regards,<br />
    Company Name<br />
    The {config("domain_base")} team
"""
body = MIMEText(message_content, 'html')
msg.attach(body)

try:
    smtpObj = smtplib.SMTP('localhost')
    for r in receivers:
        del msg['To']
        msg['To'] =  r #"Customer /n" + r
        smtpObj.sendmail(f"support@{config('domain_base')}", r, msg.as_string())
    smtpObj.quit()      
    return {"message": "Successfully sent email"}
except smtplib.SMTPException:
    return {"message": "Error: unable to send email"}

其他回答

我尝试了下面的方法,效果很好:)

rec_list =  ['first@example.com', 'second@example.com']
rec =  ', '.join(rec_list)

msg['To'] = rec

send_out = smtplib.SMTP('localhost')
send_out.sendmail(me, rec_list, msg.as_string())

这对我很管用。

import smtplib
from email.mime.text import MIMEText

s = smtplib.SMTP('smtp.uk.xensource.com')
s.set_debuglevel(1)
msg = MIMEText("""body""")
sender = 'me@example.com'
recipients = 'john.doe@example.com,john.smith@example.co.uk'
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = recipients
s.sendmail(sender, recipients.split(','), msg.as_string())

你需要了解电子邮件的可见地址和发送地址之间的区别。

msg[“To”]本质上是打印在信件上的内容。它实际上没有任何影响。除了你的电子邮件客户端,就像普通的邮政人员一样,会假设这是你想要发送电子邮件的人。

然而,实际的交付可能会有很大的不同。所以你可以把邮件(或副本)投到完全不同的人的邮箱里。

这有很多原因。例如转发。在转发时,To:报头字段不会改变,但电子邮件会被放入不同的邮箱。

smtp。Sendmail命令现在负责实际的传递。电子邮件。信息只是信件的内容,而不是传递方式。

在低级SMTP中,您需要一个接一个地提供接收者,这就是为什么地址列表(不包括姓名!)是合理的API。

对于标头,它还可以包含例如名称,例如To: First Last <email@addr.tld>, Other User <other@mail.tld>。因此,不建议使用您的代码示例,因为它将无法传递此邮件,因为仅通过拆分它,您仍然没有获得有效地址!

这是一个老问题。我发布新答案的主要原因是解释如何用Python 3.6+中的现代电子邮件库解决问题,以及它与旧版本的区别;但首先,让我们回顾一下Anony-Mousse在2012年的回答。

SMTP根本不关心头文件中有什么。您传递给sendmail方法的收件人列表实际上决定了消息将被传递到哪里。

在SMTP术语中,这称为消息的信封。在协议级别上,您连接到服务器,然后告诉它消息来自谁(MAIL from: SMTP动词)以及将消息发送给谁(RCPT to:),然后分别传输消息本身(DATA),其标题和正文作为一个斜向字符串blob。

现代smtplib通过提供send_message方法简化了Python方面的工作,该方法实际发送给消息头中指定的收件人。

现代电子邮件库提供了一个EmailMessage对象,它取代了所有不同的MIME类型,过去您必须使用这些MIME类型从较小的部分组装消息。您可以添加附件,而不需要单独构造它们,如果需要,还可以构建各种更复杂的多部分结构,但通常不必这样做。只需创建一条消息并填充您想要的部分。

注意,下面有大量注释;总的来说,新的EmailMessage API比旧的API更简洁、更通用。

from email.message import EmailMessage

msg = EmailMessage()

# This example uses explicit strings to emphasize that
# that's what these header eventually get turned into
msg["From"] = "me@example.org"
msg["To"] = "main.recipient@example.net, other.main.recipient@example.org"
msg["Cc"] = "secondary@example.com, tertiary@example.eu"
msg["Bcc"] = "invisible@example.int, undisclosed@example.org.au"
msg["Subject"] = "Hello from the other side"

msg.set_content("This is the main text/plain message.")
# You can put an HTML body instead by adding a subtype string argument "html"
# msg.set_content("<p>This is the main text/html message.</p>", "html")

# You can add attachments of various types as you see fit;
# if there are no other parts, the message will be a simple
# text/plain or text/html, but Python will change it into a
# suitable multipart/related or etc if you add more parts
with open("image.png", "rb") as picture:
    msg.add_attachment(picture.read(), maintype="image", subtype="png")

# Which port to use etc depends on the mail server.
# Traditionally, port 25 is SMTP, but modern SMTP MSA submission uses 587.
# Some servers accept encrypted SMTP_SSL on port 465.
# Here, we use SMTP instead of SMTP_SSL, but pivot to encrypted
# traffic with STARTTLS after the initial handshake.
with smtplib.SMTP("smtp.example.org", 587) as server:
    # Some servers insist on this, others are more lenient ...
    # It is technically required by ESMTP, so let's do it
    # (If you use server.login() Python will perform an EHLO first
    # if you haven't done that already, but let's cover all bases)
    server.ehlo()
    # Whether or not to use STARTTLS depends on the mail server
    server.starttls()
    # Bewilderingly, some servers require a second EHLO after STARTTLS!
    server.ehlo()
    # Login is the norm rather than the exception these days
    # but if you are connecting to a local mail server which is
    # not on the public internet, this might not be useful or even possible
    server.login("me.myself@example.org", "xyzzy")

    # Finally, send the message
    server.send_message(msg)

Bcc:标题的最终可见性取决于邮件服务器。如果你真的想确保收件人之间是不可见的,也许根本就不要使用Bcc:头,并且在信封中单独列举信封中的收件人,就像你以前在sendmail中必须做的那样(send_message也允许你这样做,但如果你只是想发送给头中指定的收件人,你就不必这样做)。

This obviously sends a single message to all recipients in one go. That is generally what you should be doing if you are sending the same message to a lot of people. However, if each message is unique, you will need to loop over the recipients and create and send a new message for each. (Merely wishing to put the recipient's name and address in the To: header is probably not enough to warrant sending many more messages than required, but of course, sometimes you have unique content for each recipient in the body, too.)

我使用python 3.6和以下代码为我工作

email_send = 'xxxxx@xxx.xxx,xxxx@xxx.xxx'
server.sendmail(email_user,email_send.split(','),text)