SMTP是发送邮件的协议,Python 2.3版本开始内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。本文以QQ邮件为例,用python发送各类邮件。
Python对SMTP支持主要使用smtplib和email两个模块,email模块负责构造邮件,smtplib模块负责发送邮件。
smtplib.SMTP([host[,port[,local_hostname[,timeout]]]])
作为SMTP的构造函数,功能是与smtp服务器建立连接,在连接成功后,就可以向服务器发送相关请求,比如登录、校验、发送、退出等。
由于安全问题,通常不直接使用smtplib.SMTP来实例化,第三方邮箱会认为它是不安全的而报错。使用加密过的SMTP_SSL来实例化,它负责让服务器做出具体操作,它有两个参数:
smtp_srv = "smtp.qq.com"
srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465)
host为远程主机地址,port为远程主机smtp端口,也可以直接使用host:port形式来表示
SMTP.connect("smtp.163.com","25")
参数为用户名与密码(或者授权码,视邮箱而定)
SMTP.login("python_2014@163.com","sdjkg358")
参数依次为是发件人、收件人(列表)、邮件内容
SMTP.sendmail("python_2014@163.com",["demo@domail.com","demo@domail02.com"],body)
所有SMTP指令都将加密传输,例如使用gmail的smtp服务时需要启动此项才能正常发送邮件,如SMTP.starttls()。
除简单文本外,很多时候邮件中还会包含HTML、图片、音频、附件等。MIME(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展)作为一种新的扩展邮件格式很好地补充了这一点。
可以将email.mime理解成smtplib模块邮件内容主体的扩展,从原先默认只支持纯文本格式扩展到HTML,同时支持附件、音频、图像等格式,smtplib只负责邮件的投递即可。
下面介绍几个常用的MIME实现类:
参数_subtype指定要添加到 "Content-type:multipart/subtype" 报头的三种可选子类型:
mixed(默认):构建一个带附件的邮件体
related:构建内嵌资源的邮件体
alternative:构建纯文本与超文本共存的邮件体
_audiodata包含原始二进制音频数据的字节字符串。
_imagedata是包含原始图片数据的字节字符串。
_text是包含消息负载的字符串,_subtype指定文本类型,支持plain(默认值)或html类型的字符串。
下面是一个小例子,只简单发送文本数据
进入QQ 邮箱的主界面→设置→账户,开启“POP3/SMTP服务”和“IMAP/SMTP 服务”。
开启后会弹出授权码,记录下来,例如
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#@Time : 2022/2/5 23:03
#@File : python_email.py
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
# 发件人
from_name = "Hehuyi_In"
# 发件邮箱
from_addr = "xxxxx@qq.com"
# 发件邮箱授权码,注意不是QQ邮箱密码
from_pwd = "jjjjjjjjjj"
# 收件邮箱
to_addr = "yyyyyy@qq.com"
# 邮件标题
my_title = "Hehuyi Test"
# 邮件正文
my_msg = "Hello World"
# MIMEText三个主要参数
# 1. 邮件内容
# 2. MIME子类型,plain表示text类型
# 3. 邮件编码格式,使用"utf-8"避免乱码
msg = MIMEText(my_msg, 'plain', 'utf-8')
msg['From'] = formataddr([from_name, from_addr])
# 邮件的标题
msg['Subject'] = my_title
# SMTP服务器地址,QQ邮箱的SMTP地址是"smtp.qq.com"
smtp_srv = "smtp.qq.com"
try:
# 不能直接使用smtplib.SMTP来实例化,第三方邮箱会认为它是不安全的而报错
# 使用加密过的SMTP_SSL来实例化,它负责让服务器做出具体操作,它有两个参数
# 第一个是服务器地址,但它是bytes格式,所以需要编码
# 第二个参数是服务器的接受访问端口,SMTP_SSL协议默认端口是465
srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465)
# 使用授权码登录QQ邮箱
srv.login(from_addr, from_pwd)
# 使用sendmail方法来发送邮件,它有三个参数
# 第一个是发送地址
# 第二个是接受地址,是list格式,可以同时发送给多个邮箱
# 第三个是发送内容,作为字符串发送
srv.sendmail(from_addr, [to_addr], msg.as_string())
print('发送成功')
except Exception as e:
print('发送失败')
finally:
#无论发送成功还是失败都要退出你的QQ邮箱
srv.quit()
执行代码
注意Python文件名不能和import的包名相同,否则会遇到以下报错
E:\Python36\python.exe E:/pytest/email.py
Traceback (most recent call last):
File "E:/pytest/email.py", line 7, in
import smtplib
File "E:\Python36\lib\smtplib.py", line 47, in
import email.utils
File "E:\pytest\email.py", line 8, in
from email.mime.text import MIMEText
ModuleNotFoundError: No module named 'email.mime'; 'email' is not a package
Process finished with exit code 1
查看QQ邮箱,发现果然收到了新邮件,并且标题、发件人、正文都跟我们设置的一样
本示例通过引入email.mime的MIMEText类来实现支持HTML格式的邮件,支持所有HTML元素,包含表格、图片、动画、CSS样式、表单等。使用HTML的表格定制美观的业务报表:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2022/2/5 23:03
# @Author: Hehuyi_In
# @File : html_email.py
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
# 发件人
from_name = "Hehuyi_In"
# 发件邮箱
from_addr = "xxxxxxx@qq.com"
# 发件邮箱授权码,注意不是QQ邮箱密码
from_pwd = "jjjjjjj"
# 收件邮箱
to_addr = "xxxxxxx@qq.com"
# 邮件标题
my_title = "HTML Test"
# 邮件正文,html格式
my_msg = '''
*官网数据 更多>>
1)日访问量:152433 访问次数:23651 页面浏览量:45123 点击数:545122 数据流量:504Mb
2)状态码信息
500:105 404:3264 503:214
3)访客浏览器信息
IE:50% firefox:10% chrome:30% other:10%
4)页面信息
/index.php 42153
/view.php 21451
/login.php 5112
'''
# 参数2改为html
msg = MIMEText(my_msg, 'html', 'utf-8')
msg['From'] = formataddr([from_name, from_addr])
# 邮件的标题
msg['Subject'] = my_title
# SMTP服务器地址
smtp_srv = "smtp.qq.com"
try:
srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465)
# 使用授权码登录QQ邮箱
srv.login(from_addr, from_pwd)
# 使用sendmail方法来发送邮件
srv.sendmail(from_addr, [to_addr], msg.as_string())
print('发送成功')
except Exception as e:
print('发送失败')
finally:
# 无论发送成功还是失败都要退出你的QQ邮箱
srv.quit()
运行结果
当要求包含图片数据的邮件内容时,需要引用MIMEImage类,若邮件主体由多个MIME对象组成,则同时需引用MIMEMultipart类来进行组装。
本示例通过MIMEText与MIMEImage类的组合来实现图文格式邮件的定制:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2022-02-07 22:00
# @Author: Hehuyi_In
# @File : image_email.py
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.utils import formataddr
# 发件人
from_name = "Hehuyi_In"
# 发件邮箱
from_addr = "xxxx@qq.com"
# 发件邮箱授权码,注意不是QQ邮箱密码
from_pwd = "xxxxx"
# 收件邮箱
to_addr = "xxxx@qq.com"
# 邮件标题
my_title = "HTML+Image Test"
# 添加图片函数,参数1:图片路径,参数2:图片id
def addimg(src,imgid):
fp = open(src,'rb') # 打开文件
msg_image = MIMEImage(fp.read()) # 创建MIMEImage对象,读取图片内容并作为参数
fp.close() # 关闭文件
msg_image.add_header('Content-ID',imgid) # 指定图片文件的Content-ID,
标签src用到
return msg_image
# 创建MIMEMultipart对象,采用related定义内嵌资源的邮件体
msg_multipart = MIMEMultipart('related')
# 创建MIMEText对象,HTML元素包括表格及图片
msg_text = MIMEText("""
*SqlServer001 更多>>
![](cid:001)
![](cid:002)
![](cid:003)
![](cid:004)
""","html","utf-8") #
标签的src属性是通过Content-ID来引用的
# MIMEMultipart对象附加MIMEText及MIMEImage的内容
msg_multipart.attach(msg_text)
msg_multipart.attach(addimg("img/001.png","001")) # 图片路径与标签,001对应上方html中的
msg_multipart.attach(addimg("img/002.png","002"))
msg_multipart.attach(addimg("img/003.png","003"))
msg_multipart.attach(addimg("img/004.png","004"))
# 发件人
msg_multipart['From'] = formataddr([from_name, from_addr])
# 邮件标题
msg_multipart['Subject'] = my_title
# SMTP服务器地址
smtp_srv = "smtp.qq.com"
try:
srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465)
# 使用授权码登录QQ邮箱
srv.login(from_addr, from_pwd)
# 使用sendmail方法来发送邮件
srv.sendmail(from_addr, [to_addr], msg_multipart.as_string())
print('发送成功')
except Exception as e:
print('发送失败')
finally:
# 无论发送成功还是失败都要退出你的QQ邮箱
srv.quit()
运行结果如图
本示例通过MIMEText与MIMEImage类的组合,实现图文邮件格式,另通过MIMEText类再定义Content-Disposition属性来实现带附件的邮件。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time : 2022-02-07 22:33
# @Author: Hehuyi_In
# @File : attach_email.py
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.utils import formataddr
# 发件人
from_name = "Hehuyi_In"
# 发件邮箱
from_addr = "xxxx@qq.com"
# 发件邮箱授权码,注意不是QQ邮箱密码
from_pwd = "xxxxx"
# 收件邮箱
to_addr = "xxxx@qq.com"
# 邮件标题
my_title = "Text+Image+Attachment Test"
# 添加图片函数,参数1:图片路径,参数2:图片id
def addimg(src,imgid):
fp = open(src,'rb') # 打开文件
msg_image = MIMEImage(fp.read()) # 创建MIMEImage对象,读取图片内容并作为参数
fp.close() # 关闭文件
msg_image.add_header('Content-ID',imgid) # 指定图片文件的Content-ID,
标签src用到
return msg_image
# 创建MIMEMultipart对象,采用related定义内嵌资源的邮件体
msg_multipart = MIMEMultipart('related')
#创建一个MIMEText对象,HTML元素包括文字与图片
msg_text = MIMEText("sqlserver介绍
![](\"cid:001\")
详情参考附件","html","utf-8")
# 创建一个MIMEText对象,附加sqlserver.txt文档
msg_attach = MIMEText(open("doc/sqlserver.txt", "rb").read(),"base64","utf-8")
# 指定文件格式类型
msg_attach["Content-Type"] = "application/octet-stream"
# 指定Content-Disposition值为attachment则出现下载保存对话框,保存的默认文件名使用filename指定
msg_attach["Content-Disposition"] = "attachment; filename=\"sqlserver.txt\""
# MIMEMultipart对象附加text,img,attach内容
msg_multipart.attach(msg_text)
msg_multipart.attach(addimg("img/001.png","001")) # 图片路径与标签,001对应上方html中的
msg_multipart.attach(msg_attach)
# 发件人
msg_multipart['From'] = formataddr([from_name, from_addr])
# 邮件标题
msg_multipart['Subject'] = my_title
# SMTP服务器地址
smtp_srv = "smtp.qq.com"
try:
srv = smtplib.SMTP_SSL(smtp_srv.encode(), 465)
# 使用授权码登录QQ邮箱
srv.login(from_addr, from_pwd)
# 使用sendmail方法来发送邮件
srv.sendmail(from_addr, [to_addr], msg_multipart.as_string())
print('发送成功')
except Exception as e:
print('发送失败')
# 打印具体报错
print(e)
finally:
# 无论发送成功还是失败都要退出你的QQ邮箱
srv.quit()
运行结果如图
参考
《python自动化运维技术与最佳实践》
https://docs.python.org/2.7/library/smtplib.html
https://docs.python.org/2.7/library/email.mime.html
用python发送qq邮件_fgdwa的博客-CSDN博客_python发送qq邮件
python发送QQ邮件_齐天大圣的博客-CSDN博客_python 发送qq邮件