Python发送邮件smtp协议编程及发送HTML、图文混合、具有附件的邮件

前言

这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题

于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。

微信小程序搜索:Python面试宝典

或可关注原创个人博客:https://lienze.tech

也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习

SMTP协议

SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,常用端口为25,属于TCP/IP协议簇;

可以通过SMTP协议在不同主机间进行邮件发送。更大多数TCP/IP应用层协议类似,SMTP协议也存在两个端;

发信人、收信人处于客户端,对应邮件系统运营商为服务端。

在接下来的代码中,我们将利用目前已有的一些主流SMTP服务器来进行邮件发送:比如QQ邮箱,这个大家应该都有。目前QQ邮箱采用端口为465,使用SSL安全协议更加安全的传输邮件

smtplib模块

在Python3版本中,可以通过SMTP协议发送邮件的模块常为smtplib,并且这个模块属于内置模块,不需要额外安装;以下为该模块常用函数介绍

参考地址:

https://docs.python.org/3.6/library/smtplib.html

https://docs.python.org/3.6/library/email.mime.html

smtplib.SMTP(host='', port=0, local_hostname=None, [timeout,])
# 实例化SMTP对象,并可以对远程SMTP服务器进行连接
# 返回stmp实例对象
'''
host:远程smtp主机地址
port:远程smtp主机端口
local_hostname:标示本地连接用户身份
timeout:连接超时选项
'''
smtplib.SMTP_SSL(host='',port=0,local_hostname=None,keyfile=None,certfile=None,[timeout, ]context=None,)
# 用于连接需要SSL安全加持才可以连接的SMTP服务器,是现在比较常用的SMTP实例化连接方式;
# ssl(Secure Sockets Layer)是一种为了网络通信提供安全及属性完整性的加持协议;
# ssl在TCP协议的传输层对数据进行加密,从而保证连接的安全性
'''
host:远程smtp主机地址
port:远程smtp主机端口
local_hostname:标示本地连接用户身份
keyfile、certfile:ssl连接时使用的验证证书及私人秘钥文件
timeout:连接超时选项
context:ssl连接时配置选项
'''

参考地址:https://docs.python.org/3.6/library/ssl.html#ssl.SSLContext

  • 实例方法
SMTP.set_debuglevel(level)
# 设置实例的调试级别
'''
level:调试级别
  0,不输出任何调试信息,同时0也是默认值。
  1:输出每次请求的单行信息。
  2:最高级别调试信息输出,记录每一行发送及接收时的命令
'''

SMTP.connect(host='localhost', port=0)
# 如果在实例化SMTP对时候,我们并没有指出连接的主机及端口地址,那么可以在后续的示例中使用该函数进行smtp服务器的连接
# 返回由服务器在响应连接之后的相应代码及消息的二元组
'''
host:smtp主机地址。
port:smtp主机端口,常用端口为25
如果采用加密方式连接时,常用端口为465或587,我们将在下面的示例代码中使用465加密验证端口进行邮件发送
'''

SMTP.helo([hostname])
# 使用helo指令向服务器确认身份,( helo来源于西班牙语的你好)
# 告知smtp服务器连接者身份

SMTP.verify(address)
# 判断address所指向的smtp服务器是否存在
# 不过出于安全考虑,一般smtp邮件服务器都会屏蔽这个指令

SMTP.login(user,passwd)
# 成功连接到smtp服务器之后,可以通过该函数登录对应邮箱账号
'''
user:对应smtp服务器邮件登录用户名。
passwd:对应smtp服务器邮件登录密码。
不过为了安全起见,默认的该密码与客户端登录密码不同,可能需要用户登录到邮件服务器客户端后台获取对应的三方授权密码才可以登录成功
'''

STMP.starttls(keyfiles=None,cerfile=None,context=None)
# 启用TLS安全传输命令,之后所有的SMTP指令在传输的时候,都会加密传输

SMTP.sendmail(from_addr,to_addrs,msg)
# 通过登录邮件服务器用户向目标用户发送邮件
'''
from_addr:发送邮件的用户邮箱
to_addrs:接收邮件的用户邮箱;这个值可以是一个有效邮箱用户列表,如:["xx1@xx.com", 'xx2@xx.com']
msg:需要发送的邮件内容。这里需要注意的是,邮件内容是有一定格式的字符串
'''
  • 邮件内容是一定格式的字符串
'From: from@xx.com \r\n' + 
'To: to@xx.com \r\n' + 
'Subject:主题' \r\n + 
'\r\n'
'邮件内容'
其中第一行为发件人信息
第二行为接收邮件用户信息
第三行为邮件主题
第四行为与邮件内容分隔的一个'\r\n'
第五行为具体邮件内容

SMTP.quit()
# 断开与smtp主机的连接

发送普通邮件

通过QQ邮箱来向其他QQ邮箱地址发送邮件

  • 代码示例
import smtplib

mail_host = 'smtp.qq.com'
from_user = "from@qq.com"
from_passwd = "passwd"
to_user = ["to1@qq.com", 'to2@qq.com']
content = '这是一封测试邮件!'

msg = 'From: %s\r\n' % from_user + \
	'To: %s\r\n' % to_user + \
	'Subject: %s\r\n' % '测试邮件' + \
	'\r\n' + \
	'%s' % content
  
smtp = smtplib.SMTP_SSL(mail_host, 465)
smtp.set_debuglevel(2)
smtp.login(from_user, from_passwd)
smtp.sendmail(from_user, to_user, msg.encode('utf-8'))

MIME标准定制邮件

MIME(Multipurpose Internet Mail Extensions)名为多用途互联网邮件扩展类型

可以让我们在使用SMTP协议进行发送邮件时,让邮件内容更加丰富多彩。浏览器也会根据MIME格式对应支持的内容来打开一些特殊文件,比如图像,音频,HTML文件等等

MIME Type类型参考地址:https://en.wikipedia.org/wiki/MIME

  • MIME Type类型定义在邮件传输时的Content-type Herder中
Content-Type : type/subtype; charset='utf-8'
  • type类型
Text:# 用于标准文本信息,文本信息可以使多种字符集或多种格式的
Multipart:# 用于连接消息体的多个部分构成一个消息,这些部分可以是不同类型单独数据
Application:# 用于传输应用程序数据或者二进制数据
Message:# 用于包装一个简单消息
Image:# 用于传输静态图片资源
Audio:# 用于传输音频资源
Video:# 用于传输视频资源
  • subtype类型
text/plain:# 纯文本内容
text/html:# HTML内容
image/gif:# GIF图像
image/jpeg:# JPEG图像
image/png:# PNG图像
application/octet-stream:# 二进制数据
application/xhtml+xml:# XHTML文档
application/pdf:# PDF文档
application/msword:# Mirosoft Word文件
multipart/alternative:# HTML邮件的HTML形式和纯文本形式
application/x-www-form-urlencoded:# 使用HTTP的POST方法提交的表单

发送HTML邮件

发送HTML格式邮件时,我们需要额外导入email.mime.text模块下的MIMEText类,该类可以为我们初始化HTML邮件数据,之后可以很方便的通过smtp实例进行发送

email.mime.text.MIMEText(_text, _subtype='plain', _charset=None )
'''
_text	:发送邮件的HTML内容。
_subtype:文本类型。
	plain:纯文本格式。
	html:html格式
_charset:邮件HTML数据编码格式;为了支持中文,常为'utf-8'
'''
  • 代码示例
import smtplib
from email.mime.text import MIMEText

mail_host = 'smtp.qq.com'
from_user = "from@qq.com"
from_passwd = "passwd"
to_user_list = ["to1@qq.com", 'to2@qq.com']

smtp = smtplib.SMTP_SSL(mail_host, 465)
smtp.login(from_user, from_passwd)

content = '<a href="http://www.python.org">学习Python,我很快乐</a>'
msg = MIMEText(content, 'html', 'utf-8') #创建MIME格式HTML邮件
msg['From'] = from_user #邮件内容中的发件人信息
msg['Subject'] = 'HTML邮件测试' #邮件主题

for to_user in to_user_list:
	msg['To'] = to_user #邮件内容中的接收人信息
    smtp.sendmail(from_user, to_user, msg.as_string())

带有图片的混合邮件

当普通文本邮件无法满足我们的需求时,需要发送一些图片相关的静态资源,那么就需要我们继续使用新的MIMEImage格式构造类来进行图片资源的初始化

如果是希望图文并茂的形式,那么还需要使用额外的MIMEMultipart来进行不同格式邮件体的组装

图片的发送一般为两种模式,第一种通过内嵌图片资源到HTML中,第二种办法可以把图像资源作为邮件附件发送

email.mime.image import MIMEImage(_imagedata,_subtype=None)
# 构建图片邮件格式信息,如果邮件内容可以被Python标准模块imghdr解码,那么子类型参数将会被自动设置。也可以通过手动指定该类型值
# 如果未设置_subtype子类型的值或Python标准库无法解释图像类型,则引发TypeError异常
'''
_imagedata:图像字符串内容
_subtype:图像类型
'''
email.mime.multipart import MIMEMultipart(_subtype='mixed')
# 该类用来组装多个邮件体的内容,我们会在接下来的示例代码使用这个类对象,来进行邮件HTML与图片内容的组合
'''
_subtype:组合方式类型
	multipart/alternative:邮件包含纯文本text/plain及超文本text/html
	multipart/related:邮件包含内嵌资源,如:图片,音频等
	multipart/mixed:邮件包含纯文本、超文本、内嵌资源等(向上兼容)
'''
  • 来个demo
msg = MIMEMultipart('related')
msg.attach(other_mime_type) # 添加不同的格式的邮件体,组合在一起
  • 代码示例
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

mail_host = 'smtp.qq.com'
from_user = "from@qq.com"
from_passwd = "passwd"
to_user_list = ["to1@qq.com", 'to2@qq.com']

smtp = smtplib.SMTP_SSL(mail_host, 465)
smtp.login(from_user, from_passwd)

content = ''' 
    <div>这是一张图片测试</div>
    <img src="cid:picid">
    ''' # cid:指明图片替换ID
mgs_ = MIMEText(content, 'html', 'utf-8') # 创建HTML邮件体

with open('image.jpg','rb') as fp: # 打开图片文件
    img_ = MIMEImage(fp.read()) # 创建图片邮件体
img_.add_header('Content-ID','picid') 
# 定义图片的ID值,连接到HTML代码邮件中的标签

msg = MIMEMultipart('related') # related为复合类型
# 使用MIMEMultipart类实例进行邮件的组合
msg['From'] = from_user  # 邮件内容中的发件人信息
msg['Subject'] = '图片邮件测试'  # 邮件主题

msg.attach(mgs_) # 添加普通HTML邮件体
msg.attach(img_) # 添加图片邮件体

for to_user in to_user_list:
    msg['To'] = to_user  # 邮件内容中的接收人信息
    smtp.sendmail(from_user, to_user, msg.as_string())

带有附件的邮件

在发送具有附件的邮件时,如果附件内容为图片,将指定邮件编码格式为base64;以及邮件的传输格式application/octet-stream代表二进制传输

  • 代码示例
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

mail_host = 'smtp.qq.com'
from_user = "from@qq.com"
from_passwd = "passwd"
to_user_list = ["to1@qq.com", 'to2@qq.com']

smtp = smtplib.SMTP_SSL(mail_host, 465)
smtp.login(from_user, from_passwd)

conetent = ''' <div>这是一个附件邮件测试</div>'''
mgs_ = MIMEText(conetent, 'html', 'utf-8') #创建HTML邮件体

with open('image.jpg','rb') as fp: #打开图片文件
  	img_ = fp.read() #图片内容

img_msg = MIMEText(img_,'base64','utf-8')
img_msg['Content-Type'] = 'application/octet-stream' #二进制数据
img_msg['Content-Disposition'] = 'attachment; filename="image.jpg"' #附件名
#Content-Disposition 为MIME协议的扩展,该属性作为下载文件的一个标识字段。

msg = MIMEMultipart()
#使用MIMEMultipart类实例进行邮件的组合

msg['From'] = from_user  # 邮件内容中的发件人信息
msg['Subject'] = '附件邮件测试'  # 邮件主题

msg.attach(mgs_) #添加普通HTML邮件体
msg.attach(img_msg) #添加图片邮件体

for to_user in to_user_list:
    msg['To'] = to_user  # 邮件内容中的接收人信息
    smtp.sendmail(from_user, to_user, msg.as_string())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李恩泽的技术博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值