Python发送邮件

smtplib 是 Python 用来发送邮件的模块,email 是用来处理邮件消息

这里,我们使用装饰器来制作发送邮件的功能

一、 文本信息

我们使用MIMEText来发送文本信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/env python
from smtplib import SMTP
from email.mime.text import MIMEText # 发送文本信息使用的库
from email.header import Header # 设置请求的头部信息
from email.utils import formataddr # 格式化
from functools import wraps

receivers = ['a.l.kun@qq.com',] # 接收者为可迭代对象,可以实现邮件的群发
subject = '测试邮件' # 设置邮件的标题


def decorate(fun_):

username = '2855595515@qq.com' # 发送邮件的qq号
password_pass = 'meryyupicqjjciei' # 授权密码,有的邮箱是使用登录密码
smtp = SMTP('smtp.qq.com') # 创建一个SMTP服务器,这里使用qq邮箱
smtp.login(username, password_pass) # 登录

@wraps(fun_)
def func_mail(*args, **kwargs):
fun_(smtp, username, *args, **kwargs) # 调用发邮件的函数
smtp.quit() # 关闭服务器
smtp.close()
return func_mail


@decorate
def mail(smtp, username):
for receiver_ in receivers:
msgRoot = MIMEText(f"这是一个测试邮件,不要回复哦~~~", "html", "utf-8") # 如果第二个参数为plain,则是发送纯文本信息,如果邮件有中文,就要使用utf-8
msgRoot["Subject"] = Header(subject, "utf-8") # 设置文本标题
msgRoot['From'] = formataddr(("A.L.Kun", username)) # 设置发件人信息
msgRoot['To'] = formataddr((receiver_.split("@")[0], receiver_)) # 设置收件人信息
smtp.sendmail(username, receiver_, msgRoot.as_string()) # 发送邮件
# smtp.set_debuglevel(1) # 输出调试信息
print(receiver_.split("@")[0], ':发送完成')


if __name__ == '__main__':
mail()

使用装饰器的好处,可以动态创建一个发送邮件的对象,同时可以不用关注邮件的配置,只要关注邮件的内容

二、 图片信息

我们可以使用MIMEImage来读取图片数据,然后进行发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/env python
from smtplib import SMTP
from email.mime.text import MIMEText # 发送文本信息使用的库
from email.mime.multipart import MIMEMultipart # 可以发送多种类型的邮件
from email.mime.image import MIMEImage # 读取图片信息
from email.header import Header
from email.utils import formataddr
from functools import wraps
import os

receivers = ['a.l.kun@qq.com',]
subject = '测试邮件'
pic_path = "./test.jpeg"


def decorate(fun_):
username = '2855595515@qq.com'
password_pass = 'mdsrecuicqjjciei'
smtp = SMTP('smtp.qq.com')
smtp.login(username, password_pass)

@wraps(fun_)
def func_mail(*args, **kwargs):
fun_(smtp, username, *args, **kwargs)
smtp.quit()
smtp.close()

return func_mail

@decorate
def mail(smtp, username):
for receiver_ in receivers:
msgRoot = MIMEMultipart("related") # 创建一个容器,可以为related模式,可以往里面添加文本、图片、附件
msgRoot["Subject"] = Header(subject, "utf-8")
msgRoot['From'] = formataddr(("A.L.Kun", username))
msgRoot['To'] = formataddr((receiver_.split("@")[0], receiver_))
pic_data = open(pic_path, "rb").read() # 读取图片数据
"""以附件的形式发送图片"""
send_img_f = MIMEImage(pic_data)
# 设置头部信息,第一个参数和第二个参数都表示以附件的形式发送,最后一个表示文件的文件名
# 只要设置了这个头部信息,就是为发送附件
send_img_f.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', os.path.basename(pic_path)))
msgRoot.attach(send_img_f) # 将图片附件添加到容器中
"""将图片添加到正文中"""
send_img_c = MIMEImage(pic_data)
# 设置图片的唯一标识,即图片的id为img1,通过`cid:img1`访问
send_img_c.add_header("Content-Id", "<img1>")
msgRoot.attach(send_img_c) # 要先将图片数据上传到容器中
img_text = f"""
<p>这是一张图片:</p>
<br><img src="cid:img1" width="300" alt={os.path.basename(pic_path)}></br>
""" # 使用导入的图片数据
msgRoot.attach(MIMEText(img_text, "html", "utf-8"))

smtp.sendmail(username, receiver_, msgRoot.as_string())
print(receiver_.split("@")[0], ':发送完成')

if __name__ == '__main__':
mail()

三、 附件

我们使用MIMEApplication来发送附件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/env python
from smtplib import SMTP
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.mime.application import MIMEApplication # 发送二进制附件
from email.utils import formataddr
from functools import wraps
import os

receivers = ['a.l.kun@qq.com',]
subject = '测试邮件'
file_lis = ["./test2.pptx", "./test.jpeg"]


def decorate(fun_):
username = '2855595515@qq.com'
password_pass = 'mwdftrtycqjjciei'
smtp = SMTP('smtp.qq.com')
smtp.login(username, password_pass)

@wraps(fun_)
def func_mail(*args, **kwargs):
fun_(smtp, username, *args, **kwargs)
smtp.quit()
smtp.close()

return func_mail


@decorate
def mail(smtp, username):
for receiver_ in receivers:
msgRoot = MIMEMultipart("related") # 创建一个容器,必须为related模式,可以往里面添加文本、图片、附件
msgRoot["Subject"] = Header(subject, "utf-8")
msgRoot['From'] = formataddr(("A.L.Kun", username))
msgRoot['To'] = formataddr((receiver_.split("@")[0], receiver_))

for file in file_lis:
# 创建二进制文件数据
msgFile = MIMEApplication(open(file, "rb").read())
# 设置标头
msgFile.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', os.path.basename(file)))
# 将数据添加到容器中
msgRoot.attach(msgFile)

smtp.sendmail(username, receiver_, msgRoot.as_string())
print(receiver_.split("@")[0], ':发送完成')


if __name__ == '__main__':
mail()