Python 第三方模块之 smtplib

1 python对SMTP的支持

SMTP(Simple Mail Transfer Protocol)是简单传输协议,它是一组用于用于由源地址到目的地址的邮件传输规则。

python中对SMTP进行了简单的封装,可以发送纯文本邮件、HTML邮件以及带附件的邮件。两个核心模块如下:

  • email模块:负责构建邮件
  • smtplib模块:负责发送邮件

1.1 smtp 模块

1、创建SMTP对象

import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
# smtpObj = smtplib.SMTP_SSL( [host [, port [, local_hostname]]] )参数说明:host: SMTP 服务器主机。 你可以指定主机的ip地址或者域名如: runoob.com,这个是可选参数。port: 如果你提供了 host 参数, 你需要指定 SMTP 服务使用的端口号,一般情况下 SMTP 端口号为25。local_hostname: 如果 SMTP 在你的本机上,你只需要指定服务器地址为 localhost 即可。 #################### 示例一
smtp = smtplib.SMTP()
smtp.connect([host[,port]])  # 连接远程smtp主机方法,host为远程主机地址,port为远程主机smtp端口,默认为25,也可以直接使用host:port形式来表示,例如:SMTP.connect("smtp.163.com","25")
smtp.starttls()                       # 开启安全传输模式
smtp.login("test@arcvideo.com","pwd") # 邮箱账号登录校验
smtp.sendmail(FROM, [TO], BODY)       # 邮件发送
smtp.quit()                           # 断开smtp连接#################### 示例二
smtp = smtplib.SMTP([host[,port]])
smtp.login("test@arcvideo.com","pwd") # 邮箱账号登录校验
smtp.set_debuglevel(1)                # 打印出和SMTP服务器交互的所有信息。
smtp.sendmail(FROM, [TO], BODY)       # 邮件发送
smtp.quit()                           # 断开smtp连接

2、SMTP对象使用sendmail方法发送邮件:

SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])  # from_addr: 邮件发送者地址。to_addrs: 字符串列表,邮件发送地址。msg: 发送消息 

这里要注意一下第三个参数,msg 是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,附件等构成,发送邮件的时候,要注意 msg 的格式。这个格式就是 smtp 协议中定义的格式。

SMTP类有几个常用的方法:

方法

描述

SMTP.set_debuglevel(level)设置输出debug调试信息,默认不输出
SMTP.docmd(cmd[, argstring])发送一个命令到SMTP服务器
SMTP.connect([host[, port]])连接到指定的SMTP服务器
SMTP.helo([hostname])使用helo指令向SMTP服务器确认你的身份
SMTP.ehlo(hostname)使用ehlo指令像ESMTP(SMTP扩展)确认你的身份
SMTP.ehlo_or_helo_if_needed()如果在以前的会话连接中没有提供ehlo或者helo指令,这个方法会调用ehlo()或helo()
SMTP.has_extn(name)判断指定名称是否在SMTP服务器上
SMTP.verify(address)判断邮件地址是否在SMTP服务器上
SMTP.starttls([keyfile[, certfile]])使SMTP连接运行在TLS模式,所有的SMTP指令都会被加密
SMTP.login(user, password)登录SMTP服务器
SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[])

发送邮件

from_addr:邮件发件人

to_addrs:邮件收件人

msg:发送消息

SMTP.quit()关闭SMTP会话
SMTP.close()关闭SMTP服务器连接

1.2 MIME

通过邮件传输简单的文本已经无法满足我们的需求,比如我们时常会定制业务质量报表,在邮件主体中会包含 HTML、图像、声音以及附件格式等,MIME(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展)作为一种新的扩展邮件格式很好地补充了这一点,更多MIME 知识见 email — An email and MIME handling package — Python 3.10.2 documentation。下面介绍几个 Python 中常用的 MIME 实现类:

MIMEBase

email.mime.base.MIMEBase(_maintype,_subtype,*,policy = compat32,** _ params ):

这是所有MIME特定类的基类

  • _maintpe是Content-Type主要类型(text or image)
  • _subtype是Content-Type次要类型(plain or gif)
  • _params是一个键值字典参数直接传递给Message.add_header
filename1 = '图片.pdf'
attachfile_base = MIMEBase('application', 'octet-stream')  # 创建基础对象指定类型
attachfile_base.set_payload(open(filename,'rb').read())    # 设置我有效负载# 设置文件名可用中文
attachfile_base.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', filename1))
attachfile_base.add_header('Content-Disposition', 'attachment', filename=filename1 .encode('UTF-8'))encoders.encode_base64(attachfile_base)
msg.attach(attachfile_base)

MIMEMultipart

email.mime.multipart.MIMEMultipart(_subtype='mixed',boundary= None,_subparts = None,*,policy = compat32,** _ params ):

作用是生成包含多个部分的邮件体的 MIME 对象

  • _subtype 指定要添加到"Content-type:multipart/subtype" 报头的可选的三种子类型,分别为 mixed、related、alternative,默认值为 mixed。定义 mixed实现构建一个带附件的邮件体;定义related 实现构建内嵌资源的邮件体;定义alternative 则实现构建纯文本与超文本共存的邮件体;
  • _subparts是有效负载的一系类初始部分,可以使用attach()方法将子部件附加到消息中。
from email.mime.multipart import MIMEMultipartmsg1 = MIMEMultipart('mixed')  # 创建带附件的实例
msg2 = MIMEMultipart('related')  # 创建内嵌资源的实例
msg3 = MIMEMultipart('alternative') # 创建纯文本与超文本实例

MIMEApplication

email.mime.application.MIMEApplication(_data, _subtype='octet-stream', _encoder=email.encoders.encode_base64, *, policy=compat32, **_params):

被用来表示主要类型的MIME消息对象应用

  • _data是一个包含原始字节数据的字符串
  • _subtype指定MIME子类型默认为八位字节流
  • _encoder是一个可调用函数,它执行传输数据的实际编码,使用set_payload()将有效载荷改为编码形式,默认编码位base64,可使用email.encoders模块查看内置编码表。
filename = 'abc.pdf'
with open(filename,'rb') as f:attachfile = MIMEApplication(f.read())
attachfile.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(attachfile)

MIMEAudio

email.mime.audio.MIMEAudio (_audiodata[, _subtype[, _encoder]]):

创建包含音频数据的邮件体

  • _audiodata 包含原始二进制音频数据的字节字符串;
  • _subtype音频类型,
  • _encoder编码。
from email.mime.audio import MIMEAudiomsgaudio = MIMEAudio(open('yishengsuoai.mp3','rb').read(),'plain')  # 文本音频对象msgaudio.add_header('Content-Disposition','attachment',filename='text.mp3')  # 扩展标题类型,文件名
msg.attach(msgaudio)  # 附加对象加入到msg

MIMEImage

email.mime.image.MIMEImage(_imagedata[, _subtype[, _encoder[, **_params]]]):

MIMENonMultipart中的一个子类,创建包含图片数据的邮件体,

  • _imagedata 是包含原始图片数据的字节字符串;
  • _sutype指定图像子类型;
  • _encoder指定一个函数内部编码默认为:email.encoders.encode_base64默认为base64编码
from email.mime.image import MIMEImage with open('test.png','rb') as fp:msgImage = MIMEImage(fp.read()) msgImage.add_header('Content-ID','imgid')  # 为图片对象拓展标题字段和值
msg.attach(msgImage)  # 将图像负载添加到msg负载

MIMEText

email.mime.text.MIMEText (_text[, _subtype[, _charset]]):

MIMENonMultipart中的一个子类,创建包含文本数据的邮件体

  • _text 是包含消息负载的字符串,
  • _subtype 指定文本类型,支持 plain(默认值)或 html类型的字符串。发送HTML格式的时候,修改为html,但同时要求msg的内容也是html的格式。
  • _charset设置字符集,参数接受一个charset实例。
from email.mime.text import MIMEText# 创建文本内容的邮件体
msg = MIMEText("python test email",'plain','utf-8')# 创建HTML格式的邮件体
msg = MIMEText("<p>python test email</p><p><a href="http://www.demo.com">链接</a></p>",'html','utf-8')# 构造TEXT格式的消息
msg = MIMEText("hello.text","plain","utf-8")
msg["Subject"] = "xxxxx"  # 主题
msg["From"] = "xxxx"      # 发送者
msg["To"] = "xxxx"        # 接收者
msg["Cc"] = "xxxx"        # 抄送# 发送以上构造的邮件内容要使用as_string将构造的邮件内容转换为string形式。
msg.sendmail("xxx","xxx",msg.as_string)

MIME实例对象的方法:

  • as_string() :返回字符串信息,相当于__str__(),str(msg)
  • as_bytes() :返回字节信息,相当于__bytes__(),bytes(msg)
  • is_multipart() :判断是否为有效载荷的列表message对象,是返回True,否则返回False
  • set_unixfrom(unixfrom) :将消息的信封头设置为unixfrom为字符串
  • get_unixfrom() :返回消息的信封头。默认为None
  • attach(payload) :将给定的有效负载添加到当前有效负载
  • get_payload(i=None, decode=False) :返回当前的有效载荷,这将是一个列表 Message
  • set_payload(payload, charset=None) :将整个消息对象的有效载荷设置为有效载荷
  • set_charset(charset) ;将有效负载的字符集设置为charset
  • get_charset() :返回Charset与消息有效负载相关的实例
  • __len__() :返回标题的总数,包括重复项
  • __contains__(name) :如果消息对象具有名为name的字段,则返回true
  • __getitem__(name) :返回指定标题字段的值
  • __setitem__(name, val) :将字段添加到带有字段名称和值val的消息中
  • __delitem__(name) :从消息的标题中删除所有出现的具有名称name的字段
  • keys() :返回所有消息标题字段名称的列表
  • values() :返回所有消息字段值的列表
  • items() :返回包含所有消息的字段标题和值
  • add_header(_name, _value, **_params) :扩展标题设置,_name为要添加的标题字段,_value为标题的值。
msg.add_header('Content-ID','imgid')   #设置图片ID
msg.add_header('Content-Disposition','attachment',filename='test.xlsx') #为附件添加一个标题
msg.add_header('Content-Disposition','attachment',filename=('utf-8','','中文标题')) #添加非ASCII字符时需指定编码
  • replace_header(_name,_value) :替换标题

更多内容请阅读官方文档

email.header.Header(s=None,charset=None):创建一个可以包含不同字符集中的字符串,并符合MIME的标头。

可选参数:s是初始标题值默认为None,可以使用append()方法追加到标题,charset指定字符集

from email.header import Headermsg['From'] = Header("测试邮件来自",'utf-8')

附加工具:email.utils

  • email.utils.localtime(dt=None):返回当前时间,dt参数为datetime实例
  • email.utils.formataddr(pair,charset='utf-8'):pair是一个元祖或列表返回分割的标题和地址如邮箱收件人昵称和邮箱账号
from email.utils import formataddrmsg['From'] = formataddr(['Meslef','92066@163.com'])
msg['To'] = formataddr(['Anybody','92066@163.com'])

2 可以发送不同格式的邮件

2.1 发送文本邮件

# coding=utf-8
import smtplib
from email.mime.text import MIMETextsender = 'bmjoker@163.com'  # 发送邮箱地址
password = 'xxxxxxx'        # 邮箱授权码,非登陆密码
mailto_list = ['19xxxxxxx9@qq.com']  # 群发邮箱地址
smtp_server = 'smtp.163.com'  # smtp服务器# 发送纯文本格式的邮件
msg = MIMEText('hello,send by python_test...','plain','utf-8')
msg['From'] = sender                   # 发送邮箱地址
msg['To'] =';'.join(mailto_list)       # 发送多人邮件写法
msg['Subject'] = 'hello,i just want to test'  # 主题server = smtplib.SMTP(smtp_server,25)  # SMTP协议默认端口是25
server.login(sender,password)          # login()方法用来登录SMTP服务器
server.set_debuglevel(1)               # 打印出和SMTP服务器交互的所有信息。
server.sendmail(sender,mailto_list,msg.as_string()) # msg.as_string()把MIMEText对象变成str server.quit()
# 第一个参数为发送者,第二个参数为接收者,可以添加多个例如:['hello@163.com','xxx@qq.com',]# 第三个参数为发送的内容
server.quit()

查看和SMTP服务器交互的所有信息:

其中login()用来登陆SMTP服务器,sendmail()用来发送邮件,群发邮件的话,可以传入一个收件人邮箱列表,邮箱的正文是str,使用as_string()把MIMEText对象变成str,password指的不是smtp服务器的登陆密码,是smtp客户端的授权密码:

2.2 发送带HTML的邮件:

import smtplib
from email.mime.text import MIMEText
from email.header import Headersender = 'bmjoker@163.com'        # 发件邮箱
passwd = 'xxxxxxxx'               # 发送人邮箱授权码
receivers = '19xxxxxxx9@qq.com'   # 收件邮箱
subject = 'python发邮Html邮件测试' # 主题content = "<html><h1>人生苦短,何必执着</h1></html>"
msg = MIMEText(content,'html','utf-8')
msg['Subject'] = Header(subject,'utf-8')  # msg['Subject'] = subject
msg['From'] = Header('hello','utf-8')     # msg['From'] = sender
msg['To'] = Header('emmmm','utf-8')       # msg['To'] = receiverstry:s = smtplib.SMTP_SSL('smtp.163.com',25)s.login(sender,passwd)s.sendmail(sender,receivers,msg.as_string())print('Send Success')
except:print('Send Failure')

2.3 发送带图片附件的邮件:

import smtplib
from email.mime.image import MIMEImage
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipartsender = 'bmjoker@163.com'
passwd = 'xxxxxxxx'
receivers = '19xxxxxx9@qq.com'
subject = 'python发邮带img的邮件测试' # 创建一个带附件的实例
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = receivers# 创建正文
msg.attach(MIMEText('使用python smtplib模块和email模块自动发送邮件测试','plain','utf-8'))# 创建图片附件
import os
img_file = open(os.getcwd()+"/a4.jpg",'rb').read()
msg_img = MIMEImage(img_file)
msg_img.add_header('Content-Disposition','attachment', filename = "a4.jpg")
msg_img.add_header('Content-ID', '<0>')
msg.attach(msg_img)try:s = smtplib.SMTP('smtp.163.com',25)s.set_debuglevel(1) # 输出发送邮件详细过程s.login(sender,passwd)s.sendmail(sender,receivers,msg.as_string())print('Send Succese')except:print('Send Failure')

调整图片大小 

<!--有效-->
<img src="cid:ALogo"  width="500" height="200"><!--无效-->
<img src="cid:ALogo" style="width: 500px;height: 200px"><!--无效-->
<img src="cid:ALogo" width="500px" height="200px">

2.4 发送带附件的邮件:

# 首先是xlsx类型的附件
xlsxpart = MIMEApplication(open('test.xlsx', 'rb').read())
xlsxpart.add_header('Content-Disposition', 'attachment', filename='test.xlsx')
msg.attach(xlsxpart)# jpg类型的附件
jpgpart = MIMEApplication(open('beauty.jpg', 'rb').read())
jpgpart.add_header('Content-Disposition', 'attachment', filename='beauty.jpg')
msg.attach(jpgpart)# mp3类型的附件
mp3part = MIMEApplication(open('kenny.mp3', 'rb').read())
mp3part.add_header('Content-Disposition', 'attachment', filename='benny.mp3')
msg.attach(mp3part)##################### 以下待验证
# 读取xls文件作为附件,open()要带参数'rb',使文件变成二进制格式,从而使'base64'编码产生作用,否则附件打开乱码
# att = MIMEText(open('C:\\ceshi.xls', 'rb').read(), 'base64', 'GB2312')
# att['Content-Type'] = 'application/vnd.ms-excel'
# att['Content-Disposition'] = 'attachment; filename ="1.xls"'# 读取xlsx文件作为附件,open()要带参数'rb',使文件变成二进制格式,从而使'base64'编码产生作用,否则附件打开乱码
att = MIMEText(open(u'C:\\ceshi.xlsx', 'rb').read(), 'base64', 'utf-8')
att['Content-Type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
#下面的filename 等号(=)后面好像不能有空格
attname ='attachment; filename ="123.xlsx"'
att['Content-Disposition'] = attnamemsgroot.attach(att)

#encoding=utf8
import smtplib
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
# 第三方 SMTP 服务
mail_host = "*******"  # 设置服务器
mail_user = "*******"  # 用户名
mail_pass = "********"  # 口令sender = '*****'
receivers = ['*****']  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
content = MIMEText('test')
message = MIMEMultipart()
message.attach(content)
message['From'] = Header("Easy", 'utf-8')
message['To'] = Header("测试", 'utf-8')
subject = 'Python SMTP 邮件测试'
message['Subject'] = Header(subject, 'utf-8')
xlsx = MIMEApplication(open('test.xlsx', 'rb').read())
xlsx["Content-Type"] = 'application/octet-stream'
xlsx.add_header('Content-Disposition', 'attachment', filename='test.xlsx')
message.attach(xlsx)
try:smtpObj = smtplib.SMTP()smtpObj.connect(mail_host, 25)  # 25 为 SMTP 端口号smtpObj.login(mail_user, mail_pass)smtpObj.sendmail(sender, receivers, message.as_string())print("邮件发送成功")
except  Exception as e:print(e)

2.5 发送HTML中带图片的邮件

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImagesender = 'xxx@163.com'      # 这里就是你的163邮箱
receiver = 'xxx@qq.com'     # 发给单人时的邮件接收邮箱
smtpserver = "smtp.163.com" # 邮件服务器,如果是163邮箱那就是这个了,其他的可以自行查找
username = 'xxxx@163.com'   # 这里还是你的邮箱
password = 'xxxxx'          # 上面获取的SMTP授权码,相当于是一个密码验证
msgRoot = MIMEMultipart('related') # 邮件类型,如果要加图片等附件,就得是这个
msgRoot['Subject'] = '监控日报'     # 邮件标题,以下设置项都很明了
msgRoot['From'] = sender
msgRoot['To'] = receiver# 以下为邮件正文内容,含有一个居中的标题和一张图片
content = MIMEText('<html><head><style>#string{text-align:center;font-size:25px;}</style><div id="string">我是居中显示的标题<div></head><body><img src="cid:image1" alt="image1"></body></html>','html','utf-8')# 如果有编码格式问题导致乱码,可以进行格式转换:
# content = content.decode('utf-8').encode('gbk')
msgRoot.attach(content)# 上面添加的图片src必须是cid:xxx的形式,xxx就是下面添加图片时设置的图片id
fp = open('D:\\Desktop\\aaa.jpg', 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
msgImage.add_header('Content-ID', 'image')  # 这个id用于上面html获取图片
msgRoot.attach(msgImage)
# 再加一个
fp1 = open('D:\\Desktop\\bbb.jpg', 'rb')
msgImage1 = MIMEImage(fp1.read())
fp1.close()
msgImage1.add_header('Content-ID', 'image1') # 这个id用于上面html获取图片
msgRoot.attach(msgImage1)'''
# 另外也可以用base64的方法直接加,但是这种方式outlook不支持
import base64
img_file = open('C:\\Users\\cloudoxou\\Desktop\\img.png','rb')
base64_data = base64.b64encode(img_file.read())
html = "<img src="https://img-blog.csdnimg.cn/2022010708251630187.png" alt="image1">"%(base64_data) # 这里简化了html代码
'''
# 连接邮件服务器,因为使用SMTP授权码的方式登录,必须是994端口
smtp = smtplib.SMTP_SSL(smtpserver,994)
smtp.login(username, password)
smtp.sendmail(sender, receiver, msgRoot.as_string())

msg中输入的是邮件正文,因此需要根据具体内容格式选择合适的类型!

关于不同类型文件的对应类型,可参考此链接:HTTP Content-type 对照表。

2.6 汇总

import smtplib
from email.utils import make_msgid,formatdate
from email.mime.text import MIMEText            # html格式和文本格式邮件
from email.mime.multipart import MIMEMultipart  # 带多个部分的邮件
from email.mime.image import MIMEImage          # 带图片格式邮件
from email.mime.audio import MIMEAudio          # 音频文件对象
from email.utils import formataddr              # 分隔标题与地址
from email.header import Header                 # 设置标题字符集
from email import encoders                      # 编码器
from email.mime.application import MIMEApplication  # 主要类型的MIME消息对象应用
from email.mime.base import MIMEBaseusername = 'service@gemail.com' # 发件人地址,通过控制台创建的发件人地址
password = '*****'              # 发件人密码,通过控制台创建的发件人密码
replyto = 'aa@qq.com'           # 自定义的回复地址
rcptto = ['***', '***']         # 收件人地址或是地址列表,支持多个收件人,最多30个# 构建信件标头结构
msg = MIMEMultipart('alternative')  # 创建一个多部分的邮件对象
msg['Subject'] = Header('自定义信件主题', 'utf-8')
msg['From'] = formataddr([Header('自定义发信昵称','utf-8'),username])
msg['To'] = formataddr([Header('自定义收信昵称','utf-8'),rcptto])
msg['Reply-to'] = replyto
msg['Message-id'] = make_msgid() #Message-ID标头
msg['Date'] = formatdate()  #日期#构建文本邮件内容
msg_text = MIMEText('自定义TEXT纯文本部分','plain','utf-8')
msg.attach(msg_text)
#读取文件创建邮件内容
with open('textfile','rb') as fp:   #读取文件内容msg_text=MIMEText(fp.read(),'plain','utf-8')#构建HTML格式的邮件内容
msg_html = MIMEText("<h1>HTML格式邮件</h1>","html","utf-8")
msg.attach(msg_html)#构建HTML格式邮件带图片内容
html1 = "<div><img src='cid:imgid'></div>"
msg_html_img = MIMEText(html1,'html','utf-8')
msg.attach(msg_html_img)
with open("imgfile","rb") as f:msg_img = MIMEImage(f.read())
msg_img.add_header('Content-ID','imgid') #扩展图片标题
msg.attach(msg_img)#带附件的邮件MIMEApplication
filename = '简历.pdf'
with open(filename,'rb') as f:attachfile = MIMEApplication(f.read())
attachfile.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(attachfile)#带多个附件的邮件MIMEApplication
filenames = ['简历.pdf','副本.pdf']
for tmp in filename:with open(tmp,'rb') as f:attachfiles = MIMEApplication(f.read())attachfiles.add_header('Content-Disposition', 'attachment', filename=tmp)msg.attach(attachfiles)#带附件的邮件MIMEBase
filename1 = '图片.pdf'
attachfile_base = MIMEBase('application', 'octet-stream')  #创建基础对象指定类型
attachfile_base.set_payload(open(filename,'rb').read())  #设置我有效负载
attachfile_base.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', filename1) )
encoders.encode_base64(attachfile_base)
msg.attach(attachfile_base)#创建音频文件
AUDIO_HTML = '''<p>this's audio file</p><audio controls><source src="cid:audioid" type="audio/mpeg"></audio>
'''
msg_test1 = MIMEText(AUDIO_HTML,'html','utf-8')
msg_audio = MIMEAudio(open('iphone.mp3','rb').read(),'plain')
msg_audio.add_header('Content-ID','audioid')
msg.attach(msg_test1)
msg.attach(msg_audio)
#收到邮件不能播放,有待解决!# 发送邮件
try:client = smtplib.SMTP()#需要使用SSL,可以这样创建client#client = smtplib.SMTP_SSL()client.connect('smtp.163.com', 25)#开启DEBUG模式client.set_debuglevel(1)client.login(username, password)client.sendmail(username, rcptto, msg.as_string())client.quit()print('email send success!')
except smtplib.SMTPConnectError as e:print('邮件发送失败,连接失败:', e.smtp_code, e.smtp_error)
except smtplib.SMTPAuthenticationError as e:print('邮件发送失败,认证错误:', e.smtp_code, e.smtp_error)
except smtplib.SMTPSenderRefused as e:print('邮件发送失败,发件人被拒绝:', e.smtp_code, e.smtp_error)
except smtplib.SMTPRecipientsRefused as e:print('邮件发送失败,收件人被拒绝:', e.smtp_code, e.smtp_error)
except smtplib.SMTPDataError as e:print('邮件发送失败,数据接收拒绝:', e.smtp_code, e.smtp_error)
except smtplib.SMTPException as e:print('邮件发送失败, ', e.message)
except Exception as e:print('邮件发送异常, ', str(e))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454040.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node.js 使用jQuery取得Nodejs http服务端返回的JSON对象示例

server.js代码&#xff1a; // 内置http模块&#xff0c;提供了http服务器和客户端功能&#xff08;path模块也是内置模块&#xff0c;而mime是附加模块&#xff09; var httprequire("http");// 创建服务器,创建HTTP服务器要调用http.createServer()函数&#xff0c…

svg 动画_根据AI导出的SVG path制作SVG线条动画

点击右上方红色按钮关注“web秀”&#xff0c;让你真正秀起来前言首先祝大家2019新年快乐&#xff0c;万事大吉&#xff0c;猪事顺利&#xff0c;阖家欢乐。前面文章SVG 线条动画基础入门知识学习到了基础知识&#xff0c;现在来给大家讲讲如何制作SVG 制作复杂图形线条动画。假…

读书笔记2013第3本:《无价》

《无价》这本书是过年前买的&#xff0c;网络书店上写着“老罗推荐”&#xff0c;想着好像是在老罗哪一年的演讲里听过这本书&#xff0c;在豆瓣上评分7.9。读书是为了产生行动&#xff0c;读书时要提的4个问题&#xff0c;1&#xff09;这本书主要在谈些什么&#xff1f;2&…

Linux下的程序调试——GDB

无论是多么优秀的程序员&#xff0c;都难以保证自己在编写代码时不会出现任何错误&#xff0c;因此调试是软件开发过程中的一个必不可少的 组成部分。当程序完成编译之后&#xff0c;它很可能无法正常运行&#xff0c;或者会彻底崩溃&#xff0c;或者不能实现预期的功能。此时如…

圆锥曲线万能弦长公式_2020高考数学50条秒杀型公式与方法

考试马上就要到了&#xff0c;学姐整理了高考数学50条秒杀型公式和方法&#xff0c;希望能帮助考生们更好地攻克数学难关&#xff01;高考数学秒杀公式与方法一1&#xff0c;适用条件&#xff1a;[直线过焦点]&#xff0c;必有ecosA(x-1)/(x1)&#xff0c;其中A为直线与焦点所在…

Python 内置模块之 logging

日志的级别和适用情况 级别适用情况DEBUG详细信息&#xff0c;通常只在诊断问题时对其感兴趣INFO确认工作正常WARNING表示发生了意料之外的事或者在不远的将来会有问题&#xff08;比如磁盘空间低&#xff09;。软件依然正常工作ERROR由于一个更加严重的问题&#xff0c;软件不…

数据结构与算法 Python语言描述 笔记

数据结构 线性表包括顺序表和链表&#xff0c;python的list是顺序表&#xff0c;链表一般在动态语言中不会使用。不过链表还是会出现在各种算法题中。 链表 link list 单链表 逆转链表&#xff1a; leetcode 206双链表循环单链表字符串 string 有一个重要的点就是字符串的匹配问…

Flask 跨域问题

一、什么是跨域 跨域是指&#xff1a;浏览器A从服务器B获取的静态资源&#xff0c;包括Html、Css、Js&#xff0c;然后在Js中通过Ajax访问C服务器的静态资源或请求。即&#xff1a;浏览器A从B服务器拿的资源&#xff0c;资源中想访问服务器C的资源。 同源策略是指&#xff1a;…

1.3 使用电脑测试MC20的电话语音功能

需要准备的硬件 MC20开发板 1个https://item.taobao.com/item.htm?id562661881042GSM/GPRS天线 1根https://item.taobao.com/item.htm?id531979567261IPEX接口转SMA接口转接线 1根https://item.taobao.com/item.htm?id531979903836GPS有源天线 1根https://item.taobao.com/i…

前端之 AJAX

AJAX参数详细列表 参数名类型描述urlString(默认: 当前页地址) 发送请求的地址。typeString(默认: "GET") 请求方式 ("POST" 、 "GET")。注意&#xff1a;其它 HTTP 请求方法&#xff0c;如 PUT 和 DELETE &#xff0c;但仅部分浏览器支持。tim…

html5--1.18 div元素与布局

1.18 div元素与布局 1.元素的分类2.div元素与布局 1、元素的分类 块元素:主要特征是会产生换行效果&#xff0c;自动与其他元素分离成两行&#xff1b;通常可以作为容器在内部添加其他元素。已经学过的块元素有&#xff1a; h1~h6;hr;ul;ol;p;table......... 内联元素:不会产生…

五个优秀的视频格式转换工具

电脑、手机、DVD播放机、PSP……这么多的东西都可以播放视频&#xff0c;但是视频格式又千差万别的&#xff0c;我们该怎么办&#xff1f;这里&#xff0c;我们介绍五个功能强大且易于使用的媒体转换器&#xff0c;用于转换不同类型的视频文件。 一、Super (Windows) Super是一…

艾宾浩斯记忆表格excel_Excel全年学习复习计划表(艾宾浩斯遗忘曲线)

最近准备考在职博士&#xff0c;刷刷学历&#xff0c;不得不又拿起必考的英语来&#xff0c;发现由于这几年敲代码&#xff0c;日常生活词汇忘了很多&#xff0c;只好买本考博词汇背诵&#xff0c;不过三十而立的人背起来确实费劲了&#xff0c;所以开始寻找好的背诵方法。又想…

七个帮助你处理Web页面层布局的jQuery插件

1.UI.Layout jQuery UI布局插件官方网站&#xff1a;http://layout.jquery-dev.com/index.cfm使用大小可折叠的嵌套面板和大量选项创建高级UI布局。布局可以创建任何你想要的UI外观; 从简单的标题或侧边栏到具有工具栏&#xff0c;菜单&#xff0c;帮助面板&#xff0c;状态栏…

前端之 CSS

CSS介绍 CSS&#xff08;Cascading Style Sheet&#xff0c;层叠样式表)定义如何显示HTML元素。 当浏览器读到一个样式表&#xff0c;它就会按照这个样式表来对文档进行格式化&#xff08;渲染&#xff09;。 CSS语法 CSS实例 每个CSS样式由两个组成部分&#xff1a;选择器…

在Window下编译OpenH323

前言&#xff1a; 本文只提供VC6.0的编译说明&#xff0c;如果想知道VC.Net下的编译过程请参看原文。 原文 &#xff1a; http://www.voxgratia.org/docs/pwlib_windows.html#msvc_headers 作者 &#xff1a;Craig Southeren 翻译 &#xff1a; Richard 原文…

matlab立体坐标定位_无惧密集建筑,小天才立体定位技术带来最强定位体验

如今&#xff0c;在可穿戴设备市场中&#xff0c;智能手表占据相当大一部分。而作为核心功能之一的定位&#xff0c;在智能手表中发挥着不可替代的作用&#xff0c;尤其是对于儿童电话手表而言。并且&#xff0c;在技术飞速进步&#xff0c;产品迭代加快的当前&#xff0c;儿童…

svga文件如何查看_电脑隐藏文件?如何查看隐藏文件 方法简单易学

大家好&#xff0c;我是小白一键重装软件的客服。如何查看隐藏文件呢&#xff1f;有时候不小心把文件夹勾选隐藏后文件就消失了&#xff0c;到底是怎么回事呢&#xff1f;其实这个是电脑上面一些设置开启了文件隐藏的功能哦&#xff0c;那么下面小白系统带你了解下如何查看隐藏…

化工图纸中LISP_必备干货丨石油化工安装工程质量与成本控制研究

对于整个石油化工工程来说&#xff0c;石油化工的安装工程在其中是最重要并且最核心的一个环节&#xff0c;其对石油化工工程的质量有着决定性的作用。从客观的角度来说&#xff0c;如果石油化工安装工程在实际的施工过程中出现任何的问题&#xff0c;就会威胁到周边人群的生命…

[原创]windows server 2012 AD架构 试验 系列 – 15解决AD复制冲突

[原创]windows server 2012 AD架构 试验 系列 – 15解决AD复制冲突 这节我详细说下 ADDS使用stamp来作为解决冲突的依据 Stamp由三块组成 Version, time stamp , source DC GUID (发生对象修改行为的源DC的GUID) 一般来说冲突分为几下情况: 1-属性冲突 你可以用repadmin来查看版…