最新消息:20190717 VPS服务器:Vultr新加坡,WordPress主题:大前端D8,统一介绍入口:关于

【未解决】Python中smtp如何发送多个收件人地址且带名字的且可以被格式化

Python crifan 1012浏览 0评论

之前已经折腾了:

【已解决】Python中给某邮箱发送邮件

可以实现发送邮件。

现在继续去优化。

但是对于代码:

senderNameAddr = “%s <%s>” % (senderName, sender)

receiversAddr = RECEIVER_SEPERATOR.join(receiverList)

receiverNameAddrList = []

for curIdx, eachReceiver in enumerate(receiverList):

    eachReceiverName = receiverNameList[curIdx]

    eachNameAddr = “%s <%s>” % (eachReceiverName, eachReceiver)

    receiverNameAddrList.append(eachNameAddr)

receiversNameAddr = RECEIVER_SEPERATOR.join(receiverNameAddrList)

def _format_addr(nameAndAddress):

    “””

    format email address

    :param nameAndAddress: email name and address

    :return:

    “””

    name, addr = parseaddr(nameAndAddress)

    return formataddr(( \

        Header(name, ‘utf-8’).encode(), \

        addr.encode(‘utf-8’) if isinstance(addr, unicode) else addr))

msg = MIMEText(body, _subtype=type, _charset=”utf-8″)

msg[“From”] = _format_addr(senderNameAddr)

msg[“To”] = _format_addr(receiversNameAddr)

titleHeader = Header(title, “utf-8”)

encodedTitleHeader = titleHeader.encode()

msg[‘Subject’] = encodedTitleHeader

msgStr = msg.as_string()

执行出错:

已经获得的多个收件人带名字的,经过_format_addr后,只剩一个收件人了。

所以此处要去:

看看如何实现smtp,多个收件人,且带名字的,且支持被parseaddr和formataddr

python smtp multiple receiver

How to send email to multiple recipients using python smtplib? – Stack Overflow

Is there any way to add multiple receivers in Python SMTPlib? – Stack Overflow

Python Not Sending Email To Multiple Addresses – Stack Overflow

[Tutor] multiple “to” recipients using smtplib

都是简单的,多个收件地址列表,用逗号或分号分割了,但是没有format

还是参考之前的:

SMTP发送邮件 – 廖雪峰的官方网站

去找找官网的:

from email.header import Header

from email.mime.text import MIMEText

from email.utils import parseaddr, formataddr

看看是如何使用的。

python email utils

python – Parsing date with timezone from an email? – Stack Overflow

Python email.Utils.formataddr Examples

18.1.9. email.utils: Miscellaneous utilities — Python 2.7.14 documentation

email.utils.parseaddr(address)

Parse address – which should be the value of some address-containing field such as To or Cc – into its constituent realname andemail address parts. Returns a tuple of that information, unless the parse fails, in which case a 2-tuple of (”, ”) is returned.

email.utils.formataddr(pair)

The inverse of parseaddr(), this takes a 2-tuple of the form (realname, email_address) and returns the string value suitable for a Toor Cc header. If the first element of pair is false, then the second element is returned unmodified.

很明显:

  • email.utils.parseaddr:把 “name”, <address>转换为 tuple(“name”, “address”)

  • email.utils.formataddr:把tuple(“name”, “address”)格式化为:”name”  <address>

然后就再去研究:

python中smtp的”To”的Header,如果是多个收件人,应该是什么样子

结果直接去掉format,换成:

# msg[“From”] = _format_addr(senderNameAddr)

# msg[“To”] = _format_addr(receiversNameAddr)

msg[“From”] = senderNameAddr

msg[“To”] = receiversNameAddr

此处,当多个收件人分隔符用’;’而不是逗号时,貌似只有第一个收件人能收到邮件,但是收件地址栏中能显示出多个收件人:

对应log显示发送的内容为:

Content-Type: text/html; charset=”utf-8″

MIME-Version: 1.0

Content-Transfer-Encoding: base64

From: Crifan2003 <crifan2003@163.com>

To: Crifan Li <admin@crifan.com>; green waste <green-waste@163.com>

Subject: =?utf-8?q?=5BHighPrice=5D_Dell_XPS_13_XPS9360-5797SLV-PUS_Laptop?=

CjxodG1sPgogICAgPGJvZHk+CiAgICAgICAgPGgxPltIaWdoUHJpY2VdIERlbGwgWFBTIDEzIFhQ

UzkzNjAtNTc5N1NMVi1QVVMgTGFwdG9wPC9oMT4KICAgICAgICA8cD5Ob3QgYnV5IDxhIGhyZWY9

Imh0dHBzOi8vd3d3Lm1pY3Jvc29mdC5jb20vZW4tdXMvc3RvcmUvZC9kZWxsLXhwcy0xMy14cHMt

OTM2MC1sYXB0b3AtcGMvOHExNzM4NGdyejM3L0dWNUQ/YWN0aXZldGFiPXBpdm90JTI1M2FvdmVy

dmlld3RhYiI+RGVsbCBYUFMgMTMgWFBTOTM2MC01Nzk3U0xWLVBVUyBMYXB0b3A8L2E+IGZvciBj

dXJyZW50IHByaWNlIDxiPiQ2OTkuMDA8L2I+ICZndDsgZXhwZWN0ZWQgcHJpY2UgPGI+JDU5OS4w

MDwvYj48L3A+CiAgICAgICAgPHA+U28gc2F2ZSBmb3IgbGF0ZXIgcHJvY2VzczwvcD4KICAgIDwv

Ym9keT4KPC9odG1sPgo=

再去分隔符改为逗号’,’试试

结果问题依旧:

第二个收件人收不到邮件。

好像是此处的收件人,应该是列表,而不是逗号分隔的多个地址

去改为:

结果就可以了:

第一个收件人:

第二个收件人:

所以,此处之所以多个收件人没有收到,其实是调用sendmail时多个收件人变量应该是list而不是str

【总结】

最后用代码:

def sendEmail(  sender, senderPassword, receiverList,

                senderName=””, receiverNameList= “”,

                smtpServer = “”, smtpPort = 25,

                type = “plain”, title = “”, body = “”):

    “””

    send email

    :param sender:

    :param senderPassword:

    :param receiverList:

    :param senderName:

    :param receiverNameList:

    :param smtpServer:

    :param smtpPort:

    :param type:

    :param title:

    :param body:

    :return:

    “””

    logging.debug(“sender=%s, receiverList=%s, senderName=%s, receiverNameList=%s, smtpServer=%s, smtpPort=%s, type=%s, title=%s, body=%s”,

                  sender, receiverList, senderName, receiverNameList, smtpServer, smtpPort, type, title, body)

    # init smtp server if necessary

    if not smtpServer:

        # extract domain from sender email

        # crifan2003@163.com -> 163.com

        atIdx = sender.index(‘@’)

        afterAtIdx = atIdx + 1

        lastDomain = sender[afterAtIdx:]

        smtpServer = ‘smtp.’ + lastDomain

        # smtpServer = “smtp.163.com”

        # smtpPort = 25

    # RECEIVER_SEPERATOR = ‘; ‘

    RECEIVER_SEPERATOR = ‘, ‘

    senderNameAddr = “%s <%s>” % (senderName, sender)

    receiversAddr = RECEIVER_SEPERATOR.join(receiverList)

    receiverNameAddrList = []

    for curIdx, eachReceiver in enumerate(receiverList):

        eachReceiverName = receiverNameList[curIdx]

        eachNameAddr = “%s <%s>” % (eachReceiverName, eachReceiver)

        receiverNameAddrList.append(eachNameAddr)

    receiversNameAddr = RECEIVER_SEPERATOR.join(receiverNameAddrList)

    # def _format_addr(nameAndAddress):

    #     “””

    #     format email address

    #     :param nameAndAddress: email name and address

    #     :return:

    #     “””

    #     name, addr = parseaddr(nameAndAddress)

    #     return formataddr(( \

    #         Header(name, ‘utf-8’).encode(), \

    #         addr.encode(‘utf-8’) if isinstance(addr, unicode) else addr))

    msg = MIMEText(body, _subtype=type, _charset=”utf-8″)

    # msg[“From”] = _format_addr(senderNameAddr)

    # msg[“To”] = _format_addr(receiversNameAddr)

    msg[“From”] = senderNameAddr

    msg[“To”] = receiversNameAddr

    titleHeader = Header(title, “utf-8”)

    encodedTitleHeader = titleHeader.encode()

    msg[‘Subject’] = encodedTitleHeader

    msgStr = msg.as_string()

    # try:

    # smtpObj = smtplib.SMTP(‘localhost’)

    smtpObj = smtplib.SMTP(smtpServer, smtpPort)

    smtpObj.set_debuglevel(1)

    smtpObj.login(sender, senderPassword)

    # smtpObj.sendmail(sender, receiversAddr, msgStr)

    smtpObj.sendmail(sender, receiverList, msgStr)

    logging.info(“Successfully sent email: message=%s”, msgStr)

    # except smtplib.SMTPException:

    #     logging.error(“Fail to sent email: message=%s”, message)

    return

调用举例:

“notification” : {

  “sender”: {

    “email”: “crifan2003@163.com”,

    “username” : “Crifan2003”,

    “password” : “xxxxxxxxx”

  },

  “receivers”: [

    {

      “email”: “green-waste@163.com”,

      “username” : “green waste”

    },

    {

      “email”: “admin@crifan.com”,

      “username” : “Crifan Li”

    }

  ]

}

# debug send email

productName = “First 163 then crifan. Dell XPS 13 XPS9360-5797SLV-PUS Laptop”

productUrl = “https://www.microsoft.com/en-us/store/d/dell-xps-13-xps-9360-laptop-pc/8q17384grz37/GV5D?activetab=pivot%253aoverviewtab”

notifType = “HighPrice”

title = “[%s] %s” % (notifType, productName)

notifContent = “””

<html>

    <body>

        <h1>%s</h1>

        <p>Not buy <a href=”%s”>%s</a> for current price <b>$699.00</b> &gt; expected price <b>$599.00</b></p>

        <p>So save for later process</p>

    </body>

</html>

“”” % (title, productUrl, productName)

receiversDictList = gCfg[“notification”][“receivers”]

receiverList = []

receiverNameList = []

for eachReceiverDict in receiversDictList:

    receiverList.append(eachReceiverDict[“email”])

    receiverNameList.append(eachReceiverDict[“username”])

sendEmail(  sender = gCfg[“notification”][“sender”][“email”],

            senderPassword = gCfg[“notification”][“sender”][“password”],

            receiverList = receiverList,

            senderName = gCfg[“notification”][“sender”][“username”],

            receiverNameList= receiverNameList,

            type = “html”,

            title = title,

            body = notifContent)

可以多个收件人都能收到邮件了。

期间的调试相关内容有:

Content-Type: text/plain; charset=”utf-8″

MIME-Version: 1.0

Content-Transfer-Encoding: base64

From: Crifan2003 <crifan2003@163.com>

To: green waste <green-waste@163.com>

Subject: =?utf-8?q?=5BhighPrice=5D_Dell_XPS_13_XPS9360-5797SLV-PUS_Laptop?=

Tm90IGJ1eSAnRGVsbCBYUFMgMTMgWFBTOTM2MC01Nzk3U0xWLVBVUyBMYXB0b3AnIGZvciBjdXJy

ZW50IHByaWNlICQ2OTkuMDAgPiBleHBlY3RlZCBwcmljZSAkNTk5LjAwLiBhbmQgc2F2ZSBmb3Ig

bGF0ZXIgcHJvY2Vzcw==

Content-Type: text/html; charset=”utf-8″

MIME-Version: 1.0

Content-Transfer-Encoding: base64

From: Crifan2003 <crifan2003@163.com>

To: Crifan Li <admin@crifan.com>; green waste <green-waste@163.com>

Subject: =?utf-8?q?=5BHighPrice=5D_Dell_XPS_13_XPS9360-5797SLV-PUS_Laptop?=

CjxodG1sPgogICAgPGJvZHk+CiAgICAgICAgPGgxPltIaWdoUHJpY2VdIERlbGwgWFBTIDEzIFhQ

UzkzNjAtNTc5N1NMVi1QVVMgTGFwdG9wPC9oMT4KICAgICAgICA8cD5Ob3QgYnV5IDxhIGhyZWY9

Imh0dHBzOi8vd3d3Lm1pY3Jvc29mdC5jb20vZW4tdXMvc3RvcmUvZC9kZWxsLXhwcy0xMy14cHMt

OTM2MC1sYXB0b3AtcGMvOHExNzM4NGdyejM3L0dWNUQ/YWN0aXZldGFiPXBpdm90JTI1M2FvdmVy

dmlld3RhYiI+RGVsbCBYUFMgMTMgWFBTOTM2MC01Nzk3U0xWLVBVUyBMYXB0b3A8L2E+IGZvciBj

dXJyZW50IHByaWNlIDxiPiQ2OTkuMDA8L2I+ICZndDsgZXhwZWN0ZWQgcHJpY2UgPGI+JDU5OS4w

MDwvYj48L3A+CiAgICAgICAgPHA+U28gc2F2ZSBmb3IgbGF0ZXIgcHJvY2VzczwvcD4KICAgIDwv

Ym9keT4KPC9odG1sPgo=

【后记】

此处对于From和To,都没有format编码,所以再去研究:

【已解决】Python中如何把smtp的From和To进行Header编码

但是会出错:

    smtpObj.sendmail(sender, receiverList, msgStr)

  File “/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/smtplib.py”, line 751, in sendmail

    raise SMTPDataError(code, resp)

smtplib.SMTPDataError: (554, ‘DT:SPM 163 smtp10,DsCowAB3OHAY6S9aTlBTDQ–.22748S2 1513089324,please see http://mail.163.com/help/help_spam_16.htm?ip=222.93.8.156&hostid=smtp10&time=1513089324‘)

log:

send: ‘ehlo licrifandeMacBook-Pro.local\r\n’

reply: ‘250-mail\r\n’

reply: ‘250-PIPELINING\r\n’

reply: ‘250-AUTH LOGIN PLAIN\r\n’

reply: ‘250-AUTH=LOGIN PLAIN\r\n’

reply: ‘250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UFrfKocUCa0xDrUUUUj\r\n’

reply: ‘250-STARTTLS\r\n’

reply: ‘250 8BITMIME\r\n’

reply: retcode (250); Msg: mail

PIPELINING

AUTH LOGIN PLAIN

AUTH=LOGIN PLAIN

coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UFrfKocUCa0xDrUUUUj

STARTTLS

8BITMIME

send: ‘AUTH PLAIN AGNyaWZhbjIwMDNAMTYzLmNvbQAqMWxpbWFvbGluMSo=\r\n’

reply: ‘235 Authentication successful\r\n’

reply: retcode (235); Msg: Authentication successful

send: u’mail FROM:<crifan2003@163.com>\r\n’

reply: ‘250 Mail OK\r\n’

reply: retcode (250); Msg: Mail OK

send: u’rcpt TO:<84483423@qq.com>\r\n’

reply: ‘250 Mail OK\r\n’

reply: retcode (250); Msg: Mail OK

send: ‘data\r\n’

reply: ‘354 End data with <CR><LF>.<CR><LF>\r\n’

reply: retcode (354); Msg: End data with <CR><LF>.<CR><LF>

data: (354, ‘End data with <CR><LF>.<CR><LF>’)

send: ‘Content-Type: text/plain; charset=”utf-8″\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: base64\r\nFrom: =?utf-8?b?56eR55Ge5YiGMjAwMyA8Y3JpZmFuMjAwM0AxNjMuY29tPg==?=\r\nTo: =?utf-8?b?56S86LKMUVEgPDg0NDgzNDIzQHFxLmNvbT4=?=\r\nSubject: =?utf-8?b?W+mrmOS7t+agvF0gdGl0bGXkuK3mlocgTWFkZGVuIE5GTCAxNiBmb3IgWGJv?=\r\n =?utf-8?q?x_One?=\r\n\r\nW+mrmOS7t+agvF0gdGl0bGXkuK3mlocgTWFkZGVuIE5GTCAxNiBmb3IgWGJveCBPbmUKICAgICAg\r\nICBOb3QgYnV5IGh0dHBzOi8vd3d3Lm1pY3Jvc29mdC5jb20vZW4tdXMvc3RvcmUvZC9tYWRkZW4t\r\nbmZsLTE2LWZvci14Ym94LW9uZS85M3M1dzZiZGcyNTAvbGdrcyB0aXRsZeS4reaWhyBNYWRkZW4g\r\nTkZMIDE2IGZvciBYYm94IE9uZSBmb3IgY3VycmVudCBwcmljZSAkMjk5LjAwIGV4cGVjdGVkIHBy\r\naWNlICQxOTkuMDAK\r\n.\r\n’

reply: ‘554 DT:SPM 163 smtp10,DsCowAB3OHAY6S9aTlBTDQ–.22748S2 1513089324,please see http://mail.163.com/help/help_spam_16.htm?ip=222.93.8.156&hostid=smtp10&time=1513089324\r\n’

reply: retcode (554); Msg: DT:SPM 163 smtp10,DsCowAB3OHAY6S9aTlBTDQ–.22748S2 1513089324,please see http://mail.163.com/help/help_spam_16.htm?ip=222.93.8.156&hostid=smtp10&time=1513089324

data: (554, ‘DT:SPM 163 smtp10,DsCowAB3OHAY6S9aTlBTDQ–.22748S2 1513089324,please see http://mail.163.com/help/help_spam_16.htm?ip=222.93.8.156&hostid=smtp10&time=1513089324‘)

send: ‘rset\r\n’

reply: ‘250 OK\r\n’

reply: retcode (250); Msg: OK

算了,去换用qq的邮箱作为发件人试试。

【已解决】QQ邮箱中开启SMTP服务

然后又遇到:

【已解决】python中smtp用qq发送邮件出错:smtplib.SMTPAuthenticationError 530 Error A secure connection is required

然后又是:

【已解决】python中smtp发送qq邮件出错:smtplib.SMTPAuthenticationError 530 Must issue a STARTTLS command first

但是:

【基本解决】python中用smtp发送QQ邮件提示成功但是收件人收不到邮件

结果发件箱还是空的:

结果看到草稿箱中有:

但是收件人邮箱列表有问题:

复制后得到收件人是:

“<crifan2003@163.com>, Crifan2003克瑞芬”<admin@crifan.com>;

所以还是收不到。

-》难道又是 name和email写反了?

好像没有反啊。

‘=?utf-8?q?Crifan2003?= <crifan2003@163.comadmin@crifan.com

>, =?utf-8?b?5YWL55Ge6Iqs?= <>’

然后去Header中编码:

为:

=?utf-8?b?PT91dGYtOD9xP0NyaWZhbjIwMDM/PSA8Y3JpZmFuMjAwM0AxNjMuY29tPiwg?=

=?utf-8?b?PT91dGYtOD9iPzVZV0w1NUdlNklxcz89IDxhZG1pbkBjcmlmYW4uY29tPg==?=

-》所以还是有问题。

带中文的 姓名 邮箱,经过一次utf-8编码了,再去utf-8编码,所以就不正常了。

所以还是要去搞清楚,如何对于:

u’克瑞芬 <admin@crifan.com>’

u’Crifan2003 <crifan2003@163.com>’

如何放在msg的To中,如何用Header去编码

想到了,对于每个”姓名 <邮件>”用逗号加起来,然后再去用Header编码,应该就可以了。

然后再去合并:

formatedReceiversNameAddr = RECEIVER_SEPERATOR.join(receiverNameAddrList) # u’Crifan2003 <crifan2003@163.com>, 克瑞芬 <admin@crifan.com>’

然后再去用Header去格式化,得到:

mergedReceiversNameAddr = RECEIVER_SEPERATOR.join(receiverNameAddrList) # u’Crifan2003 <crifan2003@163.com>, 克瑞芬 <admin@crifan.com>’

formatedReceiversNameAddr = formatEmailHeader(mergedReceiversNameAddr) #=?utf-8?b?Q3JpZmFuMjAwMyA8Y3JpZmFuMjAwM0AxNjMuY29tPiwg5YWL55Ge6IqsIDxh?=

# =?utf-8?q?dmin=40crifan=2Ecom=3E?=

然后再去调用看看结果:

结果QQ邮箱中的收件人,也还是不太正常:

“Crifan2003 <crifan2003@163.com>, 克瑞芬”<admin@crifan.com>;

不是希望的:

“Crifan2003” <crifan2003@163.com>, “克瑞芬” <admin@crifan.com>;

那还是把分隔符换成分号试试

不过归根结底,还是不知道To,设置为多个收件人时,应该如何写,写成什么格式,再去用Header编码

python smtp header multiple to

email – python: how to send mail with TO, CC and BCC? – Stack Overflow

How to send email to multiple recipients using python smtplib? – Stack Overflow

Multiple recipients with python’s smtplib sendmail method · Musings from the bitbucket

Python 102: How to Send an Email Using smtplib + email | The Mouse Vs. The Python

18.1.11. email: Examples — Python 2.7.14 documentation

官网示例中,To的多个收件人,也还是不带名字,只是地址用逗号分隔的。

[Tutor] multiple “to” recipients using smtplib

Sending to multiple email addresses from a python script – Raspberry Pi Forums

Sending Advanced Emails Made Simple in Python

Send email to multiple recipients from SMTP API – Email – HubSpot Developer Forums

Sending Unicode emails in Python – Random notes from mg

python smtp multiple recipients with name

python smtp multiple email with name

python smtp multiple to email with name

Send Email to multiple recipients from .txt file with Python smtplib – Stack Overflow

Python Mail with Mandrill To Multiple email id – Stack Overflow

Messages API | Mandrill

带名字的多个收件人,好像也不支持,只支持单个的带名字的收件人。

How to send email to multiple recipients using python smtplib? – Stack Overflow

所以截至目前,多个收件人的话,如果带名字的,则是不支持的。

难道此处的From和To,都不需要手动去编码,而只需要

msg.as_string()

时,自动进行了UTF-8的编码?

去看看

结果:

此处的from和to,都是被编码了的:

而另外的,Subject则是通过Header去(额外)编码了的

另外,再去试试Subject主题没有Header编码的话

则是就是原始未编码的字符串

结果问题依旧:

收件人带名字的话,还是无法识别。

至此,都还是无法实现:

带名字的多个收件人:

u’Crifan2003 <crifan2003@163.com>, 克瑞芬 <admin@crifan.com>’

只能支持不带名字的,多个收件人:

【未解决】python中smtp发送QQ邮件出错:smtplib.SMTPDataError 550 Error content rejected mail.qq.com rejectedmail.html

转载请注明:在路上 » 【未解决】Python中smtp如何发送多个收件人地址且带名字的且可以被格式化

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
64 queries in 0.093 seconds, using 18.89MB memory