经过大量的搜索,我无法找到如何使用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()

当前回答

几个月前我发现了这一点,并在博客上发表了相关文章。总结如下:

如果您想使用smtplib向多个收件人发送电子邮件,请使用email. message。add_header('To', eachRecipientAsString)来添加它们,然后当您调用sendmail方法时,使用email.Message.get_all('To')将消息发送给所有它们。抄送和密送收件人也是如此。

其他回答

这里有很多答案在技术上或部分上是正确的。在阅读了每个人的答案后,我想出了这个更可靠/通用的电子邮件功能。我已经确认它的工作,你可以通过HTML或纯文本的主体。注意,此代码不包括附件代码:

import smtplib
import socket

# Import the email modules we'll need
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

#
# @param [String] email_list
# @param [String] subject_line
# @param [String] error_message
def sendEmailAlert(email_list="default@email.com", subject_line="Default Subject", error_message="Default Error Message"):
    hostname = socket.gethostname()
    # Create message
    msg = MIMEMultipart()
    msg['Subject'] = subject_line
    msg['From'] = f'no-reply@{hostname}'
    msg['To'] = email_list
    msg.attach(MIMEText(error_message, 'html'))
    # Send the message via SMTP server
    s = smtplib.SMTP('localhost') # Change for remote mail server!
    # Verbose debugging
    s.set_debuglevel(2)
    try:
        s.sendmail(msg['From'], msg['To'].split(","), msg.as_string())
    except Exception as e:
        print(f'EMAIL ISSUE: {e}')
    s.quit()

这显然可以修改为使用本机Python日志记录。我只是提供了一个坚实的核心功能。我也不能强调这一点,sendmail()需要一个列表,而不是一个字符串!函数适用于Python3.6+

我提出了这个可导入模块函数。本例中使用的邮件服务器为gmail。它分为头和消息,所以你可以清楚地看到发生了什么:

import smtplib

def send_alert(subject=""):

    to = ['email@one.com', 'email2@another_email.com', 'a3rd@email.com']
    gmail_user = 'me@gmail.com'
    gmail_pwd = 'my_pass'
    smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
    smtpserver.ehlo()
    smtpserver.starttls()
    smtpserver.ehlo
    smtpserver.login(gmail_user, gmail_pwd)
    header = 'To:' + ", ".join(to) + '\n' + 'From: ' + gmail_user + '\n' + 'Subject: ' + subject + '\n'
    msg = header + '\n' + subject + '\n\n'
    smtpserver.sendmail(gmail_user, to, msg)
    smtpserver.close()

这个方法对我没用。我不知道,也许这是一个Python3(我使用3.4版本)或gmail相关的问题,但经过一些尝试,对我有效的解决方案是行

s.send_message(msg)

而不是

s.sendmail(sender, recipients, 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())

尝试声明一个包含所有收件人和cc_收件人的列表变量为字符串,而不是循环遍历它们,如下所示:

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

recipients = ["malcom@example.com","reynolds@example.com", "firefly@example.com"]
cc_recipients=["serenity@example.com", "inara@example.com"]
msg = MIMEMultipart()
msg["Subject"] = "Example"
msg["From"] = "me@example.com"
msg["To"] = ', '.join(recipients)
msg["Cc"] = ', '.join(cc_recipients)
body = MIMEText("example email body")
msg.attach(body)
smtp = smtplib.SMTP("mailhost.example.com", 25)
for recipient in recipients:
    smtp.sendmail(msg["From"], recipient, msg.as_string())
for cc_recipient in cc_recipients:
    smtp.sendmail(msg["From"], cc_recipient, msg.as_string())
smtp.quit()