【问题标题】:python: how to send mail with TO, CC and BCC?python: 如何使用 TO、CC 和 BCC 发送邮件?
【发布时间】:2010-12-05 12:08:00
【问题描述】:

出于测试目的,我需要在数百个电子邮件框中填充各种消息,并为此使用 smtplib。但除其他事项外,我不仅需要能够将消息发送到特定邮箱,还需要抄送和密送它们。 smtplib 似乎不支持在发送电子邮件时进行抄送和密件抄送。

寻找有关如何通过 python 脚本进行 CC 或 BCC 发送消息的建议。

(而且 — 不,我不会创建脚本来向我的测试环境之外的任何人发送垃圾邮件。)

【问题讨论】:

    标签: python email testing


    【解决方案1】:

    TO、CC 和 BCC 之间的区别仅出现在文本标题中。在 SMTP 级别,每个人都是收件人。

    TO - 有一个带有此收件人地址的 TO: 标头

    CC - 有一个带有此收件人地址的 CC: 标头

    密件抄送 - 标题中根本没有提到此收件人,但仍然是收件人。

    如果你有

    TO: abc@company.com
    CC: xyz@company.com
    BCC: boss@company.com
    

    您有三个收件人。电子邮件正文中的标题将仅包含 TO: 和 CC:

    【讨论】:

      【解决方案2】:

      你可以试试 MIMEText

      msg = MIMEText('text')
      msg['to'] = 
      msg['cc'] = 
      

      然后发送 msg.as_string()

      https://docs.python.org/3.6/library/email.examples.html

      【讨论】:

      • 那个例子没有使用 CC
      • 我同意上述链接中的示例不处理密件抄送。这就是@hoju 可能的意思。
      【解决方案3】:

      电子邮件标头对 smtp 服务器无关紧要。发送电子邮件时,只需将 CC 和 BCC 收件人添加到 toaddrs 即可。对于抄送,将它们添加到抄送标题中。

      toaddr = 'buffy@sunnydale.k12.ca.us'
      cc = ['alexander@sunydale.k12.ca.us','willow@sunnydale.k12.ca.us']
      bcc = ['chairman@slayerscouncil.uk']
      fromaddr = 'giles@sunnydale.k12.ca.us'
      message_subject = "disturbance in sector 7"
      message_text = "Three are dead in an attack in the sewers below sector 7."
      message = "From: %s\r\n" % fromaddr
              + "To: %s\r\n" % toaddr
              + "CC: %s\r\n" % ",".join(cc)
              + "Subject: %s\r\n" % message_subject
              + "\r\n" 
              + message_text
      toaddrs = [toaddr] + cc + bcc
      server = smtplib.SMTP('smtp.sunnydale.k12.ca.us')
      server.set_debuglevel(1)
      server.sendmail(fromaddr, toaddrs, message)
      server.quit()
      

      【讨论】:

      • smtplib.SMTP 不发送地址列表。至少在 python 2.7.2 上没有
      • 在这种情况下,RFC 2822 中提到的 BCC 标头没有任何意义。
      • @ABentSpoon 在“主题”之后缺少一个冒号。
      • 不要添加密件抄送标头。看到这个:mail.python.org/pipermail/email-sig/2004-September/000151.html 这个:“”“注意 sendmail() 的第二个参数,收件人,作为一个列表传递。您可以在列表中包含任意数量的地址,以便将消息传递给每个地址反过来。由于信封信息与邮件标头是分开的,您甚至可以通过将其包含在方法参数中而不是在邮件标头中来密送某人。""" from pymotw.com/2/smtplib
      • 这永远不会密件抄送或抄送 - 它永远是收件人
      【解决方案4】:

      不要添加密件抄送标头。

      看到这个:http://mail.python.org/pipermail/email-sig/2004-September/000151.html

      还有这个:"""请注意,sendmail() 的第二个参数,收件人,是作为一个列表传递的。您可以在列表中包含任意数量的地址,以便将邮件依次传递给每个地址。由于信封信息与邮件头分开,您甚至可以通过将某人包含在方法参数中而不是在邮件头中来密送某人。""" 来自http://pymotw.com/2/smtplib

      toaddr = 'buffy@sunnydale.k12.ca.us'
      cc = ['alexander@sunydale.k12.ca.us','willow@sunnydale.k12.ca.us']
      bcc = ['chairman@slayerscouncil.uk']
      fromaddr = 'giles@sunnydale.k12.ca.us'
      message_subject = "disturbance in sector 7"
      message_text = "Three are dead in an attack in the sewers below sector 7."
      message = "From: %s\r\n" % fromaddr
          + "To: %s\r\n" % toaddr
          + "CC: %s\r\n" % ",".join(cc)
          # don't add this, otherwise "to and cc" receivers will know who are the bcc receivers
          # + "BCC: %s\r\n" % ",".join(bcc)
          + "Subject: %s\r\n" % message_subject
          + "\r\n" 
          + message_text
      toaddrs = [toaddr] + cc + bcc
      server = smtplib.SMTP('smtp.sunnydale.k12.ca.us')
      server.set_debuglevel(1)
      server.sendmail(fromaddr, toaddrs, message)
      server.quit()
      

      【讨论】:

      • 为天赋点赞:D
      【解决方案5】:

      关键是在您的 sendmail 调用中将收件人添加为 电子邮件 ID 列表。

      import smtplib
      from email.mime.multipart import MIMEMultipart
      
      me = "user63503@gmail.com"
      to = "someone@gmail.com"
      cc = "anotherperson@gmail.com,someone@yahoo.com"
      bcc = "bccperson1@gmail.com,bccperson2@yahoo.com"
      
      rcpt = cc.split(",") + bcc.split(",") + [to]
      msg = MIMEMultipart('alternative')
      msg['Subject'] = "my subject"
      msg['To'] = to
      msg['Cc'] = cc
      msg.attach(my_msg_body)
      server = smtplib.SMTP("localhost") # or your smtp server
      server.sendmail(me, rcpt, msg.as_string())
      server.quit()
      

      【讨论】:

      • 关闭msg['BCC'] -- 它会显示您的隐藏发件人,并且不会影响消息是否发送给他们(sendmail 的参数会这样做)。
      • 我同意 Erica 和 Julio 的观点。 Bcc 的目的是向其他接收者隐藏接收者。如果它在消息中,那就违背了目的。
      【解决方案6】:

      在我创建之前它对我不起作用:

      #created cc string
      cc = ""someone@domain.com;
      #added cc to header
      msg['Cc'] = cc
      

      然后在收件人 [列表] 中添加 cc,例如:

      s.sendmail(me, [you,cc], msg.as_string())
      

      【讨论】:

        【解决方案7】:

        从 2011 年 11 月发布的 Python 3.2 开始,smtplib 有一个新函数 send_message 而不仅仅是 sendmail,这使得处理 To/CC/BCC 更加容易。从Python official email examples 中提取,稍作修改,我们得到:

        # Import smtplib for the actual sending function
        import smtplib
        
        # Import the email modules we'll need
        from email.message import EmailMessage
        
        # Open the plain text file whose name is in textfile for reading.
        with open(textfile) as fp:
            # Create a text/plain message
            msg = EmailMessage()
            msg.set_content(fp.read())
        
        # me == the sender's email address
        # you == the recipient's email address
        # them == the cc's email address
        # they == the bcc's email address
        msg['Subject'] = 'The contents of %s' % textfile
        msg['From'] = me
        msg['To'] = you
        msg['Cc'] = them
        msg['Bcc'] = they
        
        
        # Send the message via our own SMTP server.
        s = smtplib.SMTP('localhost')
        s.send_message(msg)
        s.quit()
        

        使用标题工作正常,因为send_message respects BCC as outlined in the documentation:

        send_message 不会传输任何可能出现在 msg 中的 Bcc 或 Resent-Bcc 标头


        对于sendmail,通常会将抄送标头添加到消息中,例如:

        msg['Bcc'] = blind.email@adrress.com
        

        或者

        msg = "From: from.email@address.com" +
              "To: to.email@adress.com" +
              "BCC: hidden.email@address.com" +
              "Subject: You've got mail!" +
              "This is the message body"
        

        问题在于,sendmail 函数对所有这些标头都一视同仁,这意味着它们将(明显地)发送给所有 To: 和 BCC: 用户,这违背了 BCC 的目的。正如这里的许多其他答案所示,解决方案是不在标题中包含密件抄送,而只在传递给sendmail 的电子邮件列表中包含。

        需要注意的是 send_message 需要一个 Message 对象,这意味着您需要从 email.message 导入一个类,而不是仅仅将字符串传递给 sendmail。

        【讨论】:

        • 刚刚验证 send_message(msg) 处理添加到 EmailMessage 中的 cc - msg['Cc'] 如果您使用的是 Python 3,那么这就是要走的路。
        • @bmiller 是的,非常方便。我写了这个答案,因为我正在研究它并在文档和其他参考文献中找到了更简单的方法,它对我来说效果很好,我认为它应该在这里占有一席之地,因为很多人会第一次看这里。
        • 我发现这个解决方案不仅更优雅,而且效果很好。它还解决了我在@ABentSpoon 的回答中遇到的一个问题,即对于 CC 中的 gmail 地址,电子邮件没有进入收件箱,而是进入了“所有邮件”。
        • 请注意,当使用 email.message.EmailMessage 时,smtplib.send_message() 将不会发送到未在邮件中列出的任何收件人地址(to、cc、bcc)调用 send_message() 时如果提供了 to_addr 函数的 to_addr 参数
        【解决方案8】:

        以上所有方法都不适合我,因为我在“收件人”和“抄送”中都有多个收件人。所以我尝试如下:

        recipients = ['abc@gmail.com', 'xyz@gmail.com']
        cc_recipients = ['lmn@gmail.com', 'pqr@gmail.com']
        MESSAGE['To'] = ", ".join(recipients)
        MESSAGE['Cc'] = ", ".join(cc_recipients)
        

        并使用“cc_recipients”扩展“收件人”并以简单的方式发送邮件

        recipients.extend(cc_recipients)
        server.sendmail(FROM,recipients,MESSAGE.as_string())
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-10-11
          • 2018-01-22
          • 1970-01-01
          • 1970-01-01
          • 2017-01-25
          • 2011-11-09
          相关资源
          最近更新 更多