今
日
鸡
汤
蝉鸣空桑林,八月萧关道。
上一篇关于邮件的自动发送教程中,我们讲解了如何使用yagmail进行简单的邮件发送:
现实生活中,如果只是发邮件给自己,像上一篇文章那样简陋的格式是可以接受的,但若要针对每个人进行邮件的定制化,群发给公司客户、内部员工、亲戚朋友,则需更加高级的邮件发送方式。
我们可以通过HTML制作一封精美的元旦祝福邮件,但是邮件的内容——比如姓名、祝福语等应该怎样动态渲染呢?答案是jinja2.
jinja2 是一个Python 的模板引擎,使用jinja2,我们能够在邮件HTML中设定占位符,在Python发送邮件的时候,将指定文本渲染到该占位符中,实现动态渲染的目的。
举一个jinja2的简单例子:
from jinja2 import Template
name = 'Peter'
age = 34
tm = Template("My name is {{ name }} and I am {{ age }}")
msg = tm.render(name=name, age=age)
print(msg)
使用 {{}} 圈起来的是占位符,称之为模板字符串。模板字符串呈现两个变量:名称和年龄,在这个例子中,硬编码了name和age的值传入模板,得到输出:
My name is Peter and I am 34
在本篇文章中,我将教大家如何通过Html及Python+jinja2给你的亲朋好友们定制元旦祝福邮件。
本文所有素材及源代码均可以在此下载:
https://pythondict.com/download/python-new-year-mail/
或Python实用宝典公众号回复:元旦邮件 直接拿到网盘下载链接。
1.准备
开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。
如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.
此外,推荐大家用VSCode编辑器,因为它有许多许多的优点:Python 编程的最好搭档—VSCode 详细指南。
准备输入命令安装依赖,如果你没有VSCode编辑器,Windows环境下打开 Cmd (开始-运行-CMD),苹果系统环境下请打开 Terminal (command+空格输入Terminal),如果你用的是VSCode编辑器或Pycharm,可以直接在下方的Terminal中输入命令:
pip install jinja2
pip install yagmail
2.编写HTML
将需要发送的邮件模板的HTML编写好。并将占位符变量提前写入HTML中。由于我的HTML文件过大,这里就不完全展示了,只展示几个关键变量。
为简化教程的复杂度,并尽可能覆盖到知识点,这里我们使用4个变量:
1.LOGO图片(让你更好地理解图片是如何渲染到HTMl里并发邮件)
2.背景图片
3.祝福对象
4.祝福语言
首先,是图片变量的配置:
<tr>
<td valign="left" width="50%" class="logo sub-gd" style="padding-left:0;">
<h1>
<img src="data:image/png;base64, {{pythondict_img}}">
</h1>
</td>
</tr>
由于我们需要发送html形的邮件,因此像代码这样将图片转码为base64再发送是最方便的。
其中,base64部分用jinja2语法 {{}} 包起来,中间就是变量名,一会render渲染的时候就会将base64渲染进来。
背景图片的配置比较特殊,使用 base64 渲染的话QQ邮箱会自动过滤为#号,因此必须使用url的形式:
<td valign="middle"style="background-image: url({{backgroud}});">
其次是祝福对象和祝福语言的配置:
<h2>
{{name}}
<br>
祝您2021年元旦快乐
</h2>
<p>
{{bless}}.
</p>
使用 {{}} 包裹变量,name是祝福的对象,bless是祝福语。这里简化了代码,还有许多样式要配置详细的大家可以看源代码中的 index_detail.html.
对了,我们源代码里包括两份html,一份是 index_detail.html 是未经过压缩的源代码,还有一份是 index.html,是被压缩过的源代码。
为什么要压缩HTML呢?因为邮箱客户端在解析HTML的时候,有可能会将换行符解析成<br>,因此压缩HTML不保留任何空格和换行符是最保险的做法。
详细的HTML代码,大家可以看源代码中的 index_detail.html.
3.Python代码
发送邮件的方法,我们在 人人都能懂的 Python 自动发送邮件教程 中已经详细地讲过了:
class Mail:
"""
邮件相关类
"""
def log(self, content):
now_time = time.strftime(
"%Y-%m-%d %H:%M:%S", time.localtime()
)
print(f'{now_time}: {content}')
def sendmail(self, html, title, receivers):
"""
发送邮件
Arguments:
html {str} -- 邮件正文(html)
title {str} -- 邮件标题
receivers {list} -- 邮件接收者,数组
"""
yag = yagmail.SMTP(
host='您的邮箱SMTPHOST', user='您的邮箱',
password='您的邮箱密码', smtp_ssl=True
)
yag.send(receivers, title, html)
self.log("邮件发送成功")
此外,为了渲染图片,需要将图片转化为base64,这个方法是这样的:
def get_image_base64(path):
"""
获得图片的base64编码
Args:
path (str): 图片路径
Returns:
str: base64编码
"""
import base64
f = open(path, "rb")
base64_data = base64.b64encode(f.read())
f.close()
return base64_data.decode("utf-8")
当然,最重要的地方是下面这段代码,需要针对每个人定制祝福语,我们可以采用字典的数据结构来保存数据:
bless_info = {
"admin@pythondict.com": {
"pythondict_img": get_image_base64("./images/pythondict.png"),
"name": "实用宝典",
"background": "https://背景图片.jpg",
"bless": "愿所有的幸运与您不期而遇..",
"title": "祝宝典哥明年粉丝破十万"
},
"test@qq.com": {
"pythondict_img": get_image_base64("./images/pythondict.png"),
"name": "老王",
"background": "https://背景图片.jpg",
"bless": "祝您女儿明年考研顺顺利利,全家幸福安康..",
"title": "老王,祝您元旦快乐!"
},
}
可以看到 bless_info 字典里的每个key是发送对象的邮箱,而这些 key 对应的value 中就有需要渲染到邮件的变量: pythondict_img, name, background 及 祝福语bless. 最后一个变量title,是用于指定邮件标题的。
这样,渲染+发送邮件做起来就方便多了:
tm = Template(open('./index.html', encoding="utf-8").read())
for mail in bless_info:
msg = tm.render(bless_info[mail])
Mail().sendmail(html=msg, title=bless_info[mail]["title"], receivers=[mail])
Mail().sendmail():是我们的发送邮件函数,应该不必多说。
bless_info[mail]:是需要渲染的变量,这里面的变量少了可不行,多了没关系。
bless_info[mail]["title"]:就是刚刚在字典里指定的最后一个变量 title,
由于 sendmail() 函数里的 receivers 是支持多人的,因此这里需要以数组的形式传入函数。
不过这里还有一个有趣的改进,如果你需要用同一个模板邮件发送给同一家人,你可以这么做:
bless_info = {
...,
"test1@qq.com,test2@qq.com,test3@qq.com": {
"pythondict_img": get_image_base64("./images/pythondict.png"),
"name": "老王一家",
"background": "https://背景图片.jpg",
"bless": "祝王小女明年考研顺顺利利,老王全家幸福安康,吉祥如意..",
"title": "老王一家,祝你们元旦快乐!"
},
}
tm = Template(open('./index.html', encoding="utf-8").read())
for mail in bless_info:
msg = tm.render(bless_info[mail])
Mail().sendmail(html=msg, title=bless_info[mail]["title"], receivers=mail.split(","))
没错,只需要在key里将这一家人的邮箱用逗号分隔开,然后receivers里改为mail.split(","),你就能实现同一份邮件发给一家人的功能,是不是非常方便?
大家可以自己找喜欢的背景图片,也可以用我在代码里已给大家提供的图片。想要去除LOGO的话,直接将pythondict_img设为空,或者设为你自己的卡片即可。
在源代码目录下运行代码:
python mail.py
即可成功发送邮件,快打开编辑器试一下吧(记得先测试)!
我们的文章到此就结束啦,如果你喜欢今天的Python 实战教程,请持续关注Python实用宝典。