参考:https://www.pynote.net/archives/630
parseaddr函数和formataddr函数,都来自email.utils模块,用来在发送Email的时候,“美化”地址中的姓名部分。本文介绍如何使用这两个函数。
引入parsesaddr和formataddr
use_parseaddr_formataddr.py
from email.header import Header from email.mime.text import MIMEText from email.utils import parseaddr,formataddr
由于下面代码需要使用到Header和MIMEText所以一并引入
带姓名的email地址
一般情况下,我们使用Email,地址都是直接写成这样(1):123456@qq.com,纯Email,不带姓名。写成这样没问题,在使用工具或代码(例如MIMEText对象)编写Email内容的时候,地址都可以直接写成这样。
但是,这个时候,地址还有另外一种写法(2):name<123456@qq.com>,将姓名放在Email地址前面。这种写法增加了姓名,并用尖括号将Email地址括起来,这种写法会让您发出的邮件,看起来更加专业。
按照第1种写法设置发件人,收到邮件时,地址显示是这样的:
而如果采用第2种写法,收到邮件时,地址会显示成这样
首先看发送邮件的写法
收件人
这就是带姓名的Email邮件地址格式
注意:
有的时候,我们使用第1种Email地址发邮件,对方在邮件工具中打开时,还是能看到地址前的姓名,比如QQ信箱。这是因为你的邮件地址在对方的邮件工具里有保存,显示邮件的时候,邮件工具默认将此地址保存的姓名显示了出来。如果对方邮件工具没有保存你的邮件,就不会出现这个现象。
如何 parsesaddr和formataddr
parseaddr 函数和 formataddr 函数就是用来合成这种符合Email标准的带姓名的地址格式的。我们继续上一篇的内容,用Python发送Email的技巧,这一篇就是介绍在发送Email的时候,如何使用带姓名的Email地址格式。
from email.header import Header from email.mime.text import MIMEText from email.utils import parseaddr,formataddr # 邮件发件人邮件格式其中pynote.net为发件人用户名可以自定义 # from@qq.com为发件人真实邮箱地址不能自定义 From = 'pynote.net<from@qq.com>' # 使用parseaddr()方法分隔用户名和邮箱地址 name,addr = parseaddr(From) print(name,addr) # pynote.net from@qq.com # 使用formataddr方法把邮箱用户名和邮箱地址转换成标准Email地址格式 # formataddr方法接收一个元组作为参数,元组的第一个元素是经过Header编码的用户名信息 # 元组的第二个元素是邮箱地址,返回一个str # 元组的两个元素都可以为空,如果第一个元素为空则返回邮箱地址,如果第二个元素为空则返回用户名经过Header函数编码信息 # 如果两个元素都为空则返回空 fromaddr = formataddr((Header(name,'utf-8').encode(), addr)) print(fromaddr) # =?utf-8?q?pynote=2Enet?= <from@qq.com> # 以下为收件者邮箱信息 To = 'mylove<babylove@qq.com>' name,addr = parseaddr(To) print(name,addr) # mylove babylove@qq.com toaddr = formataddr((Header(name,'utf-8').encode(), addr)) print(toaddr) # =?utf-8?q?mylove?= <babylove@qq.com>
注意:使用Header生成的字符串格式,如果name值有asscii字符则格式如下
# asscii字符 name = 'mylove' print(Header(name,'utf-8').encode()) # =?utf-8?q?mylove?= print(base64.b64encode(name.encode('utf-8'))) # b'bXlsb3Zl'
格式解析如下
=?utf-8?q?mylove?= =? #为固定格式开头 utf-8?#为utf-8编码 q? #只有ascii码不包含中文 mylove #为原文 ?= #为固定结尾
如果name包含中文则格式如下
# 包含中文 name = '中文' print(Header(name,'utf-8').encode()) # =?utf-8?b?5Lit5paH?= print(base64.b64encode(name.encode('utf-8'))) # b'5Lit5paH'
如果name包含中文则生成的字符串中包含使用base64解码的字符串,前面使用b?而不是q?
将带姓名的Email格式作为参数,给parseaddr函数,得到name和addr。name就是姓名,addr就是纯Email,请看parseaddr解析To后的打印显示。然后formataddr函数再将name和addr转换成标准Email地址格式。注意name还要经过Header函数的编码。fromaddr和toaddr,就是最后我们可以使用的地址字符串。我们来使用一下:
# 定义发送邮件的邮件内容信息 msg_str = 'this is a name-based email address test' # 注意到构造MIMEText对象时 # 第一个参数就是邮件正文 # 第二个参数是MIME的subtype,传入'plain'表示纯文本,最终的MIME就是'text/plain' # 最后一定要用utf-8编码保证多语言兼容性 msg = MIMEText(msg_str,'plain','utf-8') msg['From'] = fromaddr msg['To'] = toaddr # 把MIMEText对象转换成str print(msg.as_string())
msg['From']和msg['To']直接使用formataddr后的字符串,如果有多个这样的字符串地址,用逗号(,)分开。但是sendmail函数不使用编码后的带姓名的Email地址字符串,还是使用纯Email地址,这个细节要注意。带姓名的Email地址的编码,只是改变邮件内容的头部,而不改变投递细节。
小工具
这个函数小工具,合并了 parseaddr和formataddr功能,输入 以第2种方式编写的Email地址,得到直接可以在MIMEText中使用字符串,请收藏:
def _format_addr(s): name, addr = parseaddr(s) return formataddr((Header(name,'utf-8').encode(), addr))
这个函数即把以第2中方式写入的Email地址,返回为可以在MIMEText中使用字符串
这个函数还自带了一定能的容错性:
# 容错性 # 标准格式 print(_format_addr('godaddy<1123456@hotmail.com>')) # =?utf-8?q?godaddy?= <1123456@hotmail.com> # 没有用户名只有email地址地址没有使用<>括起来 print(_format_addr('1123456@hotmail.com')) # 1123456@hotmail.com # 没有用户名 print(_format_addr('<1123456@hotmail.com>')) # 1123456@hotmail.com print(_format_addr('pythonisgood<1123456@hotmail.com>')) # =?utf-8?q?pythonisgood?= <1123456@hotmail.com> print(_format_addr('pythonisgood')) # 用户名和地址都为空返回也为空字符串 print(_format_addr('')) #
parseaddr和formataddr函数的使用并不难,关键是要里面Email的地址格式,本文就介绍这么多啦。