ValueError: There may be at most 1 To headers in a message

ValueError: There may be at most 1 To headers in a message

我正在尝试编写一个非常基本的电子邮件发送脚本。这是我的代码..

import smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg.set_content("Test message.")
msg['Subject'] = "Test Subject!!!"
msg['From'] = "myemail@gmail.com"

email_list = ["xyz@gmail.com", "abc@gmail.com"]

for email in email_list:
    msg['To'] = email
    server = smtplib.SMTP(host='smtp.gmail.com', port=587)
    server.starttls()
    server.login("myemail@gmail.com", "mypassword")
    server.send_message(msg)
    server.quit()

脚本应该将邮件发送给多个收件人,所以我需要在遍历循环时更改 msg['To'] 字段但是我在回溯波纹管中收到以下错误。

Traceback (most recent call last):
  File "exp.py", line 66, in <module>
    msg['To'] = email
  File "/usr/lib/python3.8/email/message.py", line 407, in __setitem__
    raise ValueError("There may be at most {} {} headers "
ValueError: There may be at most 1 To headers in a message

我该如何解决?请帮忙。谢谢..

清除消息的 'To' 属性。

for email in email_list:
    msg['To'] = email
    server = smtplib.SMTP(host='smtp.gmail.com', port=587)
    server.starttls()
    server.login("myemail@gmail.com", "mypassword")
    server.send_message(msg)
    server.quit()
    del msg['To]

下面是抛出异常的代码:(\Python385\Lib\email\message.py)

def __setitem__(self, name, val):
    """Set the value of a header.

    Note: this does not overwrite an existing header with the same field
    name.  Use __delitem__() first to delete any existing headers.
    """
    max_count = self.policy.header_max_count(name)
    if max_count:
        lname = name.lower()
        found = 0
        for k, v in self._headers:
            if k.lower() == lname:
                found += 1
                if found >= max_count:
                    raise ValueError("There may be at most {} {} headers "
                                     "in a message".format(max_count, name))
    self._headers.append(self.policy.header_store_parse(name, val))

不知道 EmailMessage class 的内部工作原理,我可以假设每次调用 __setitem__ 都会写入电子邮件消息的头部,因此通过循环调用它, header 被多次写入,我建议您为要发送的每封电子邮件制作一封电子邮件,但只创建一个服务器:

server = smtplib.SMTP(host='smtp.gmail.com', port=587)
server.starttls()
server.login("myemail@gmail.com", "mypassword")
email_list = ["xyz@gmail.com", "abc@gmail.com"]
for email in email_list:
    msg = EmailMessage()
    msg.set_content("Test message.")
    msg['Subject'] = "Test Subject!!!"
    msg['From'] = "myemail@gmail.com"
    msg['To'] = email
    server.send_message(msg)
server.quit()

仅当您需要单独发送消息时。如果你想同时向所有人发送相同的消息,你可以这样做

msg['To'] = ', '.join(email_list)

如果您有一个地址列表,其中一些包含 name/title,那么我认为这是正确的做法。请注意,可能不需要 parseaddr + formataddr 对,但 parseaddr 可以纠正一些格式错误的收件人。

from email.header import Charset
from email.message import EmailMessage, MIMEPart
from email.utils import formataddr, parseaddr

test_recipients = [
        "Mr. John Doe <johndoe@example.com>",
        "Mr. Jane Doe <janedoe@example.com>",
        "somebody@example.com"
]
to_header= []
for raw_address in (test_recipients):
    # Parse and recreate
    title, email = parseaddr(raw_address)
    if title and email:
        to_header.append(f"{title} <{email}>")
    elif email:
        to_header.append(email)
# Encode after join
message.add_header("To", Charset("utf-8").header_encode(", ".join(to_header)))

如果你只是删除 server.quit() 来自循环 并添加 删除消息['to'] 那么就没有错误了