简介

  发邮件前我们需要了解的是邮件是怎么一个形式去发送到对方手上的,通俗点来说就是你写好一封信,然后装进信封,写上地址,贴上邮票,然后就近找个邮局,把信仍进去,其他的就不关心了,只是关心时间,而电子邮件不像日常发送邮件的按天算,时间都是按

秒算的。

电子邮件的发送流程:

1、你使用某款电子邮件软件MUA:mail user agent --邮件用户代理,填写完成点击发送

2、在你点击发送的时候电子邮件软件发出去,到MTA:mail transfer agent--邮件传输代理,即email服务提供商,如网易等

3、MTA--邮箱传输代理会把邮箱投递到邮件的最终目的地MDA:mail delivery agent---邮箱投递服务

4、email到达MDA后就会放在某个服务器上,存在数据库里,收件人必须通过MUA从MDA中把邮箱放到自己电脑上

发件人 -> MUA -> MTA -> MTA -> 若干个MTA -> MDA<-MUA<-收件人

python发邮件需要掌握两个模块的用法,smtplib和email,这俩模块是python自带的,只需import即可使用。smtplib模块主要负责发送邮件,email模块主要负责构造邮件。

smtplib模块主要负责发送邮件:是一个发送邮件的动作,连接邮箱服务器,登录邮箱,发送邮件(有发件人,收信人,邮件内容)。

email模块主要负责构造邮件:指的是邮箱页面显示的一些构造,如发件人,收件人,主题,正文,附件等。

1.smtplib模块

smtplib使用较为简单。以下是最基本的语法。

导入及使用方法如下:

 import smtplib

 smtp = smtplib.SMTP()
smtp.connect('smtp.163.com,25')
smtp.login(username, password)
smtp.sendmail(sender, receiver, msg.as_string())
smtp.quit()

说明:

smtplib.SMTP():实例化SMTP()

connect(host,port):

host:指定连接的邮箱服务器。常用邮箱的smtp服务器地址如下:

新浪邮箱:smtp.sina.com,新浪VIP:smtp.vip.sina.com,搜狐邮箱:smtp.sohu.com,126邮箱:smtp.126.com,139邮箱:smtp.139.com,163网易邮箱:smtp.163.com。

port:指定连接服务器的端口号,默认为25.

login(user,password):

user:登录邮箱的用户名。

password:登录邮箱的密码,像笔者用的是网易邮箱,网易邮箱一般是网页版,需要用到客户端密码,需要在网页版的网易邮箱中设置授权码,该授权码即为客户端密码。

sendmail(from_addr,to_addrs,msg,...):

from_addr:邮件发送者地址

to_addrs:邮件接收者地址。发送邮件,多人时用list,字符串列表['接收地址1','接收地址2','接收地址3',...]或'接收地址'

msg:发送消息:邮件内容。邮件正文是一个str,一般是msg.as_string():as_string()是将msg(MIMEText对象或者MIMEMultipart对象)变为str。

quit(): 退出关闭邮箱,用于结束SMTP会话。

2.email模块

email模块下有mime包,mime英文全称为“Multipurpose Internet Mail Extensions”,即多用途互联网邮件扩展,是目前互联网电子邮件普遍遵循的邮件技术规范。

该mime包下常用的有三个模块:text,image,multpart

导入方法如下:

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage

构造一个邮件对象就是一个Message对象,如果构造一个MIMEText对象,就表示一个文本邮件对象,如果构造一个MIMEImage对象,就表示一个作为附件的图片,要把多个对象组合起来,就用MIMEMultipart对象,而MIMEBase可以表示任何对象。它们的继承关系如下:

Message
+- MIMEBase
+- MIMEMultipart
+- MIMENonMultipart
+- MIMEMessage
+- MIMEText
+- MIMEImage

2.1 text说明

邮件发送程序为了防止有些邮件阅读软件不能显示处理HTML格式的数据,通常都会用两类型分别为"text/plain"和"text/html"

构造MIMEText对象时,第一个参数是邮件正文,第二个参数是MIME的subtype,最后一定要用utf-8编码保证多语言兼容性。

2.1.1添加普通文本

方法很简单,在构造MIMEText对象时,把TEXT字符串传进去,再把第二个参数plain和第三个参数编码传进去即可。plain表示纯文本 ,后面的则是编译,保证多语言兼容

text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttps://www.cnblogs.com/du-hong"
text_plain = MIMEText(text,'plain', 'utf-8')

查看MIMEText属性:可以观察到MIMEText,MIMEImage和MIMEMultipart的属性都一样。

print dir(text_plain)

['__contains__', '__delitem__', '__doc__', '__getitem__', '__init__', '__len__', '__module__', '__setitem__', '__str__', '_charset', '_default_type', '_get_params_preserve', '_headers', '_payload', '_unixfrom', 'add_header', 'as_string', 'attach', 'defects', 'del_param', 'epilogue', 'get', 'get_all', 'get_boundary', 'get_charset', 'get_charsets', 'get_content_charset', 'get_content_maintype', 'get_content_subtype', 'get_content_type', 'get_default_type', 'get_filename', 'get_param', 'get_params', 'get_payload', 'get_unixfrom', 'has_key', 'is_multipart', 'items', 'keys', 'preamble', 'replace_header', 'set_boundary', 'set_charset', 'set_default_type', 'set_param', 'set_payload', 'set_type', 'set_unixfrom', 'values', 'walk']

2.1.2添加超文本(HTML)

方法也很简单,在构造MIMEText对象时,把HTML字符串传进去,再把第二个参数由plain变为html就可以了

 html = """
<html>
<body>
<p>
Here is the <a href="https://www.cnblogs.com/du-hong">link</a> you wanted.
</p>
</body>
</html>
"""
text_html = MIMEText(html,'html', 'utf-8')

2.1.3添加附件

首先要创建MIMEMultipart()实例,然后构造附件,如果有多个附件,可依次构造,最后利用smtplib.smtp发送

sendfile=open(r'D:\pythontest\text.txt','rb').read()
text_att = MIMEText(sendfile, 'base64', 'utf-8')
text_att["Content-Type"] = 'application/octet-stream'
text_att["Content-Disposition"] = 'attachment; filename="显示的名字.txt"'

2.2 image说明

添加图片:

sendimagefile=open(r'D:\pythontest\testimage.png','rb').read()
image = MIMEImage(sendimagefile)
image.add_header('Content-ID','<image1>')

查看MIMEImage属性:

print dir(image)

['__contains__', '__delitem__', '__doc__', '__getitem__', '__init__', '__len__', '__module__', '__setitem__', '__str__', '_charset', '_default_type', '_get_params_preserve', '_headers', '_payload', '_unixfrom', 'add_header', 'as_string', 'attach', 'defects', 'del_param', 'epilogue', 'get', 'get_all', 'get_boundary', 'get_charset', 'get_charsets', 'get_content_charset', 'get_content_maintype', 'get_content_subtype', 'get_content_type', 'get_default_type', 'get_filename', 'get_param', 'get_params', 'get_payload', 'get_unixfrom', 'has_key', 'is_multipart', 'items', 'keys', 'preamble', 'replace_header', 'set_boundary', 'set_charset', 'set_default_type', 'set_param', 'set_payload', 'set_type', 'set_unixfrom', 'values', 'walk']

2.3 multpart说明

常见的multipart类型有三种:multipart/alternative, multipart/related和multipart/mixed。

邮件类型为"multipart/alternative"的邮件包括纯文本正文(text/plain)和超文本正文(text/html)。

邮件类型为"multipart/related"的邮件正文中包括图片,声音等内嵌资源。

邮件类型为"multipart/mixed"的邮件包含附件。向上兼容,如果一个邮件有纯文本正文,超文本正文,内嵌资源,附件,则选择mixed类型。

msg = MIMEMultipart('mixed')

我们必须把Subject,From,To,Date添加到MIMEText对象或者MIMEMultipart对象中,邮件中才会显示主题,发件人,收件人,时间(若无时间,就默认一般为当前时间,该值一般不设置)。

msg = MIMEMultipart('mixed')
msg['Subject'] = 'Python email test'
msg['From'] = 'XXX@163.com <XXX@163.com>'
msg['To'] = 'XXX@126.com'
msg['Date']='2019-5-10'

查看MIMEMultipart属性:

msg = MIMEMultipart('mixed')
print dir(msg)

结果:

['__contains__', '__delitem__', '__doc__', '__getitem__', '__init__', '__len__', '__module__', '__setitem__', '__str__', '_charset', '_default_type', '_get_params_preserve', '_headers', '_payload', '_unixfrom', 'add_header', 'as_string', 'attach', 'defects', 'del_param', 'epilogue', 'get', 'get_all', 'get_boundary', 'get_charset', 'get_charsets', 'get_content_charset', 'get_content_maintype', 'get_content_subtype', 'get_content_type', 'get_default_type', 'get_filename', 'get_param', 'get_params', 'get_payload', 'get_unixfrom', 'has_key', 'is_multipart', 'items', 'keys', 'preamble', 'replace_header', 'set_boundary', 'set_charset', 'set_default_type', 'set_param', 'set_payload', 'set_type', 'set_unixfrom', 'values', 'walk']

说明:

msg.add_header(_name,_value,**_params):添加邮件头字段。

msg.as_string():是将msg(MIMEText对象或者MIMEMultipart对象)变为str,如果只有一个html超文本正文或者plain普通文本正文的话,一般msg的类型可以是MIMEText;如果是多个的话,就都添加到MIMEMultipart,msg类型就变为MIMEMultipart。

msg.attach(MIMEText对象或MIMEImage对象):将MIMEText对象或MIMEImage对象添加到MIMEMultipart对象中。MIMEMultipart对象代表邮件本身,MIMEText对象或MIMEImage对象代表邮件正文。

以上的构造的文本,超文本,附件,图片都何以添加到MIMEMultipart('mixed')中:

msg.attach(text_plain)
msg.attach(text_html)
msg.attach(text_att)
msg.attach(image)

3.文字,html,图片,附件实现实例

3.1实例

3.2运行结果

3.3参考代码

 # coding=utf-
#.先设置编码,utf-8可支持中英文,如上,一般放在第一行 #.注释:包括记录创建时间,创建人,项目名称。
'''
Created on --
@author: 北京-宏哥
Project:学习和使用邮箱发文字,html,图片,附件实现实例邮件
'''
#.导入模块
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.header import Header # 设置smtplib所需的参数
# 下面的发件人,收件人是用于邮件传输的。
smtpserver = 'smtp.mxhichina.com'
username = 'noreply@xxx.cn'
password = 'xxxx@@xx3'
sender = 'noreply@xxx.cn'
# 收件人为一个收件人
# receiver='XXX@126.com'
# 收件人为多个收件人
receiver = ["1918991791@qq.com","2014816656@qq.com","hongge@xxx.cn"] subject = 'Python email test'
# 通过Header对象编码的文本,包含utf-8编码信息和Base64编码信息。以下中文名测试ok
# subject = '中文标题'
# subject=Header(subject, 'utf-8').encode() # 构造邮件对象MIMEMultipart对象
# 下面的主题,发件人,收件人,日期是显示在邮件页面上的。
msg = MIMEMultipart('mixed')
msg['Subject'] = subject
msg['From'] = '北京-宏哥<noreply@xxx.cn>'
# msg['To'] = "1918991791@qq.com","2014816656@qq.com","hongge@xxx.cn"
# 收件人为多个收件人,通过join将列表转换为以;为间隔的字符串
msg['To'] = ";".join(receiver)
# msg['Date']='2019-5-10' # 构造文字内容
text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttps://www.cnblogs.com/du-hong"
text_plain = MIMEText(text, 'plain', 'utf-8')
msg.attach(text_plain) # 构造图片链接
sendimagefile = open(r'E:\pythontest\testimage.png', 'rb').read()
image = MIMEImage(sendimagefile)
image.add_header('Content-ID', '<image1>')
image["Content-Disposition"] = 'attachment; filename="honggeimage.png"'
msg.attach(image) # 构造html
# 发送正文中的图片:由于包含未被许可的信息,网易邮箱定义为垃圾邮件,报554 DT:SPM :<p><img src="cid:image1"></p>
html = """
<html>
<head></head>
<body>
<p>Hi!<br>
How are you?<br>
Here is the <a href="https://www.cnblogs.com/du-hong/">link 北京-宏哥</a> you wanted.<br>
</p>
</body>
</html>
"""
text_html = MIMEText(html, 'html', 'utf-8')
text_html["Content-Disposition"] = 'attachment; filename="texthtml.html"'
msg.attach(text_html) # 构造附件
sendfile = open(r'E:\pythontest\text.txt', 'rb').read()
text_att = MIMEText(sendfile, 'base64', 'utf-8')
text_att["Content-Type"] = 'application/octet-stream'
# 以下附件可以重命名成aaa.txt
# text_att["Content-Disposition"] = 'attachment; filename="aaa.txt"'
# 另一种实现方式
text_att.add_header('Content-Disposition', 'attachment', filename='hongge.txt')
# 以下中文测试不ok
# text_att["Content-Disposition"] = u'attachment; filename="中文附件.txt"'.decode('utf-8')
msg.attach(text_att) # 发送邮件
smtp = smtplib.SMTP()
smtp.connect('smtp.mxhichina.com')
# 我们用set_debuglevel()就可以打印出和SMTP服务器交互的所有信息。
# smtp.set_debuglevel()
smtp.login(username, password)
smtp.sendmail(sender, receiver, msg.as_string())
smtp.quit()

说明:

对有些 header 要特别留意,服务器会针对这些 header 做检查

User-Agent : 有些服务器或 Proxy 会通过该值来判断是否是浏览器发出的请求

Content-Type : 在使用 REST 接口时,服务器会检查该值,用来确定 HTTP Body 中的内容该怎样解析。常见的取值有:

application/xml : 在 XML RPC,如 RESTful/SOAP 调用时使用

application/json : 在 JSON RPC 调用时使用

application/x-www-form-urlencoded : 浏览器提交 Web 表单时使用

在使用服务器提供的 RESTful 或 SOAP 服务时, Content-Type 设置错误会导致服务器拒绝服务

小结

  好了,哈哈,到这里把python发邮件的十八辈祖宗都被我们挖出来了,自己都感觉到有点缺德,但是我们学习就是需要这种精神,但是也不要过于钻牛角筋,要适可而止。想必小伙伴们对python发邮件有了更深刻的认识了,以后遇到类似的问题,

往上套就可以了,但是要注意方式和方法,不要生搬硬套,生搬硬套又会出现问题,要灵活有技巧的套。

python接口自动化(三十三)-python自动发邮件总结及实例说明番外篇——下(详解)的更多相关文章

  1. 《手把手教你》系列技巧篇(三十一)-java+ selenium自动化测试- Actions的相关操作-番外篇(详解教程)

    1.简介 上一篇中,宏哥说的宏哥在最后提到网站的反爬虫机制,那么宏哥在自己本地做一个网页,没有那个反爬虫的机制,谷歌浏览器是不是就可以验证成功了,宏哥就想验证一下自己想法,于是写了这一篇文章,另外也是 ...

  2. 《手把手教你》系列技巧篇(三十六)-java+ selenium自动化测试-单选和多选按钮操作-番外篇(详解教程)

    1.简介 前边几篇文章是宏哥自己在本地弄了一个单选和多选的demo,然后又找了网上相关联的例子给小伙伴或童鞋们演示了一下如何自动化测试,这一篇宏哥在网上找了一个问卷调查,给小伙伴或童鞋们来演示一下.上 ...

  3. 《手把手教你》系列技巧篇(三十三)-java+ selenium自动化测试-单选和多选按钮操作-上篇(详解教程)

    1.简介 在实际自动化测试过程中,我们同样也避免不了会遇到单选和多选的测试,特别是调查问卷或者是答题系统中会经常碰到.因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助 ...

  4. python自动发邮件总结及实例说明

    python发邮件需要掌握两个模块的用法,smtplib和email,这俩模块是python自带的,只需import即可使用.smtplib模块主要负责发送邮件,email模块主要负责构造邮件. sm ...

  5. python接口自动化(四十一)- 发xml格式参数的post请求(超详解)

    简介 最近在工作中,遇到一种奇葩的接口,它的参数数据是通过xml,进行传递的,不要大惊小怪的,林子大了什么鸟都有,每个人的思路想法不一样,开发的接口也是各式各样的,如果想要统一的话,必须是提前团队已经 ...

  6. python接口自动化三(登录绕开验证码及发帖)

    前言 有些登录的接口会有验证码:短信验证码,图形验证码等,这种登录的话验证码参数可以从后台获取的(或者查数据库最直接). 获取不到也没关系,可以通过添加cookie的方式绕过验证码. 但是这里需要明确 ...

  7. python接口自动化测试三十三:获取时间戳(10位和13位)

    很多时候,在调用接口时,需要对请求进行签名.需要用到unix时间戳. 在python里,在网上介绍的很多方法,得到的时间戳是10位.而java里默认是13位(milliseconds,毫秒级的). 下 ...

  8. python接口自动化(十三)--cookie绕过验证码登录(详解)

    简介 有些登录的接口会有验证码:短信验证码,图形验证码等,这种登录的话验证码参数可以从后台获取的(或者查数据库最直接).获取不到也没关系,可以通过添加cookie的方式绕过验证码.(注意:并不是所有的 ...

  9. [Python接口自动化]从零开始学习python自动化(1):环境搭建

    第一步:安装python编译环境 安装python编译环境之前,必须保证已安装jdk哈,如果为安装,请参考https://jingyan.baidu.com/article/6dad5075d1dc4 ...

随机推荐

  1. rdlc水晶报表在wpf里的使用

    1引用程序集 Microsoft.ReportViewer.WinForms 2 xaml 命名空间 xmlns:rv="clr-namespace:Microsoft.Reporting. ...

  2. 通过Chrome扩展来批量复制知乎好友

        1.初始化文件 Chrome 官方扩展教程地址 新建一个文件夹 zhi-follow 下图中 1 部分为 默认的图标3种尺寸 会显示在 Chrome 中   2. 定义按钮样式   页面上会有 ...

  3. SQLServer 使用sp_repldone标识所有未分发的事务为已分发

    原文:SQLServer 使用sp_repldone标识所有未分发的事务为已分发 对于发布数据库的数据大量操作时,会使日志扫描并读取太多,会导致分发堵塞很久.也有一些解决方法,参考 <SqlSe ...

  4. 随机森林分类器(Random Forest)

    阅读目录 1 什么是随机森林? 2 随机森林的特点 3 随机森林的相关基础知识 4 随机森林的生成 5 袋外错误率(oob error) 6 随机森林工作原理解释的一个简单例子 7 随机森林的Pyth ...

  5. Have You Tried Delphi on Amazon Linux? (就是AWS用的Linux)

    The new Delphi Linux compiler enables customers to take new or existing Windows server applications ...

  6. 子函数内malloc分配内存,论如何改变指针参数所指内存,二级指针、三级指针的应用

    工作中优化一段代码,代码中有一大段分配堆内存的内容,我觉得这段代码太长了,更适合放在子函数里面. 我把指针作为参数,然后在子函数中malloc分配内存,结果出现了问题,函数结束后,以参数传进来的指针并 ...

  7. QTableWidget简单应用之文件浏览器

     实现下面这个简单的文件浏览功能,常用的QTableWidget设置都用到了.  基本设置 ui->tableWidget->setColumnCount(5); //设置表格列数 ui- ...

  8. Redis EXISTS命令耗时过长case排查

    一.背景 redis慢日志分析平台上线后,随便看了一下,发现onestore使用的缓存集群,存在大量的EXISTS命令慢查询的情况: 平均每个EXISTS命令需要13ms,最大耗时近20ms.这个结果 ...

  9. Java的String类字符串的拆分

    在java编程中,有时候我们需要把一个字符串按照某个特定字符.字母等作为截点分割这个字符串, 这样我们就可以使用这个字符串的一部分或者把所有截取的内容保存到数组里等操作. public class S ...

  10. SpringBoot整合Redis注意的一些问题

    1:ERR value is not an integer or out of range 1-1:背景 使用redisTemplate.opsForValue().increment(key, de ...