电子邮件,简称电邮,是指一种由寄件人将数字信息发送给一个人或者多个人的信息交换方式。
电邮包括三个部分:消息的“信封”、邮件标头、邮件内容。
电邮的格式:用户名@主机名(域名)。电邮地址是表示在某部主机上的一个用户账号。
电邮的报文格式包括两部分:邮件头部(主要包括收件人和发件人的地址、发送日期、邮件主题等)和邮件体(正文)。
报文头部主要关键字:To、Subject、CC(抄送,即此邮件应同时发给其他所列出的收件人)、From、Data

电子邮箱(E-mail地址)的获取需要在邮件服务器上进行申请。通常用户在邮件服务器上申请一个账号后,邮件服务器会为这个账号分配一定的空间。
用户想要发送一封电邮,需要遵循一定的通信规则,SMTP协议就是来定义这种通信规则的。通常把处理用户SMTP请求(邮件发送请求)的服务器称为SMTP服务器(邮件发送服务器)。
用户想要接受一封电邮,也要遵从一定的通信格式,POP3协议就是用来定义这种通信格式的。通常把处理用户POP3请求(邮件接收请求)的服务器称为POP3服务器(邮件接收服务器)。

发送电子邮件

SMTP发送电邮(smtplib模块)

SMTP(简单邮件传送协议),是一组由源地址到目的地址传送邮件的规则,用来控制邮件的中转方式。
smtplib模块,用于实现SMTP协议,发送邮件。
email模块帮助构造邮件格式。

创建SMTP对象smtpObj=smtplib.SMTP([host [,port [,local_hostname]]])
host:SMTP服务器主机,可选参数。可以指定主机的IP地址或者域名。
port:如果指定了host参数,就需要指定SMTP服务器使用的端口号。一般情况下SMTP服务器的端口号为25。
local_hostname:如果SMTP在本机上,只需要指定服务器地址为localhost即可。

SMTP对象使用sendmail方法发送邮件:SMTP.sendmail(from_addr,to_addrs,msg[,mail_options,rept_options])
from_addr:邮件发送者地址。
to_addrs:字符串列表,邮件发送地址。
msg:发送消息,一般使用字符串。

首先需要设置发送邮箱的SMTP授权。

import smtplib
from email.mime.text import MIMEText
from email.header import Headersender="1064800303@qq.com"#发送者邮箱用户名
password="XXXXXX"#(不是真的邮箱密码)SMTP授权码
receiver=["wangyifan9901@yeah.net",]#收件人地址,必须是列表类型
message=MIMEText("来自Python的邮件","plain","utf-8")#邮件正文
message["From"]=Header("WYF","utf-8")#发件人显示名字
message["To"]=Header("Wyf","utf-8")#收件人显示名字
message["Subject"]="SMTP发送邮件"#邮件标题try:smtp=smtplib.SMTP_SSL("smtp.qq.com",465)#使用QQ企业邮箱服务器发送smtp.login(sender,password)#登录smtp.sendmail(sender,receiver,message.as_string())print("邮件已发送")
except smtplib.SMTPException as e:print("ERROR!",e)

我是选择QQ发给网易。中间出了很多类似535、Connection unexpectedly closed之类的错误,感觉就是三个地方,可以自行尝试,从别人那里抄过来的解决方法不一定有效:
1.password密码要是SMTP授权码
2.这个函数SMTP_SSL也有可能是SMTP
3.服务器的选择,尽量选择发送方的服务器吧。端口号看起来465最保险。我的资料上显示发送方服务器是smtp.exmail.qq.com,但是在PyCharm会报错535。

邮箱 发件服务器 非SSL协议端口 SSL协议端口
163 smtp.163.com 25 465/587
qq smtp.qq.com 25 465/587

在浪费我1块钱发短信费用后,留下了感动的泪水。


PS:但是这个好像不能直接回复。

发送HTML格式的电子邮件

纯文本格式邮件只能是显示文字,要发送更丰富的内容可以发送HTML格式的邮件。即在使用MIMEText函数构造邮件消息体时将第二个参数指定格式为"html"。

import smtplib
from email.mime.text import MIMEText
from email.header import Headersender="1064800303@qq.com"#发送者邮箱用户名
password="XXXXXX"#邮箱密码,SMTP授权码
receiver=["wangyifan9901@yeah.net",]#收件人地址,必须是列表类型mail_msg="""
<p>使用Python发送邮件</p>
<br>
<p><a href="http://www.baidu.com">这是一个超链接</p>
"""message=MIMEText(mail_msg,"html","utf-8")#邮件正文
message["From"]=Header("WYF","utf-8")#发件人显示名字
message["To"]=Header("Wyf","utf-8")#收件人显示名字
message["Subject"]="SMTP发送邮件"#邮件标题try:smtp=smtplib.SMTP_SSL("smtp.qq.com",465)#使用QQ企业邮箱服务器发送smtp.login(sender,password)#登录smtp.sendmail(sender,receiver,message.as_string())print("邮件已发送")
except smtplib.SMTPException as e:print("ERROR!",e)

就是不知道为什么这个超链接在收件箱能点开,发件箱点不开。

发送带附件的邮件

在构造邮件消息体的时候需要使用MIMEMultipart来构建复合类型的消息体,然后把文本和附件一个一个地加进去。

import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipartsender="1064800303@qq.com"#发送者邮箱用户名
password="XXXXXX"#邮箱密码,SMTP授权码
receiver=["wangyifan9901@yeah.net",]#收件人地址,必须是列表类型message=MIMEMultipart()
message["From"]=Header("WYF","utf-8")#发件人显示名字
message["To"]=Header("Wyf","utf-8")#收件人显示名字
message["Subject"]="SMTP发送邮件"#邮件标题mail_msg="""
<p>使用Python发送邮件</p>
<br>
<p><a href="http://www.baidu.com">这是一个超链接</p>
"""
message.attach(MIMEText(mail_msg,"html","utf-8"))
attached_file=MIMEText(open(__file__,encoding="utf-8").read(),"base64","utf-8")#添加附件
attached_file["Content-Disposition"]='attachment;filename="a.txt"'
message.attach(attached_file)try:smtp=smtplib.SMTP_SSL("smtp.qq.com",465)#使用QQ企业邮箱服务器发送smtp.login(sender,password)#登录smtp.sendmail(sender,receiver,message.as_string())print("邮件已发送")
except smtplib.SMTPException as e:print("ERROR!",e)

发送图片

把图片作为附件添加到邮件消息体中,然后在HTML格式的正文中使用src=cid:img1格式嵌入即可。

import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImagesender="1064800303@qq.com"#发送者邮箱用户名
password="XXXXXX"#邮箱密码,SMTP授权码
receiver=["wangyifan9901@yeah.net",]#收件人地址,必须是列表类型message=MIMEMultipart()
message["From"]=Header("WYF","utf-8")#发件人显示名字
message["To"]=Header("Wyf","utf-8")#收件人显示名字
message["Subject"]="SMTP发送邮件"#邮件标题msg_content=MIMEMultipart("alternative")
mail_msg="""
<p>使用Python发送带图片邮件</p>
<br>
<p>
图片
<img src="cid:img1'>
</p>
"""
msg_content.attach(MIMEText(mail_msg,"html","utf-8"))
message.attach(msg_content)with open("1.jpg","rb")as f:img1=MIMEImage(f.read())img1.add_header("Content-ID","img1")#定义资源的名字为img1
message.attach(img1)try:smtp=smtplib.SMTP_SSL("smtp.qq.com",465)#使用QQ企业邮箱服务器发送smtp.login(sender,password)#登录smtp.sendmail(sender,receiver,message.as_string())print("邮件已发送")
except smtplib.SMTPException as e:print("ERROR!",e)

接收电子邮件

接收邮件的两种常用协议:
POP3协议(邮局协议版本3),允许电邮客户端下载服务器上的邮件,但是在客户端的操作不会反馈到服务器上。
IMAP协议(Internet邮件访问协议),提供Webmail与电邮客户端之间的双向通信,任何在客户端做的改变都会同步到服务器上。

使用POP3协议下载邮件(poplib模块)

import poplib
from email.parser import Parserusername="1064800303@qq.com"#登录邮箱用户名
password="XXXXXX"#邮箱密码,SMTP授权码pop_server=poplib.POP3_SSL("pop.qq.com",995)#连接邮箱服务器
print(pop_server.getwelcome().decode("utf-8"))#打印出邮箱服务器的欢迎文字
pop_server.user(username)#登录邮箱服务器
pop_server.pass_(password)print("Server stat",pop_server.stat())#打印出当前账号状态,第一个返回值为邮件数,第二个为占用空间resp,mails,octets=pop_server.list()#获取所有邮件列表
print(mails)index=len(mails)#获取最新的一封邮件(序号最大),邮件索引从1开始计数
resp,lines,octets=pop_server.retr(index)msg_contnt=b'\r\n'.join(lines).decode("utf-8")
msg=Parser().parsestr(msg_contnt)#解析出邮件
pop_server.dele(index)#可以根据邮件索引号直接从服务器删除邮件
pop_server.quit()#关闭连接

如果正确连接上服务器并且列出邮件数量,说明已经正确使用了POP3协议并收到了邮件。
第一次运行:
又运行了一次:(邮件删除一封)

使用IMAP协议下载邮件(imaplib模块)

import imaplib
import emailusername="1064800303@qq.com"#登录邮箱用户名
password="XXXXXX"#邮箱密码,SMTP授权码imap_server=imaplib.IMAP4_SSL("imap.qq.com",993)#连接邮箱服务器imap_server.login(username,password)#登录邮箱服务器print("---------------LOG--------------")
imap_server.print_log()
print("--------------------------------")resp,data=imap_server.list()#获取邮箱目录
print(data)res,data=imap_server.select('INBOX')#选择默认收件箱并打印邮件数量
print(res,data)
print(data[0])typ,lines=imap_server.fetch(data[0],'(RFC822)')#获取最新的一封邮件
msg=email.message_from_string(lines[0][1].decode('utf-8'))imap_server.close()#关闭连接

解析邮件

解析邮件的过程正好和发送邮件构造邮件的过程相反,只要反向操作即可。

import poplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddrusername="1064800303@qq.com"#登录邮箱用户名
password="XXXXXXX"#邮箱密码,SMTP授权码pop_server=poplib.POP3_SSL("pop.qq.com",995)#连接邮箱服务器
print(pop_server.getwelcome().decode("utf-8"))#打印出邮箱服务器的欢迎文字
pop_server.user(username)#登录邮箱服务器
pop_server.pass_(password)print("Server stat",pop_server.stat())#打印出当前账号状态,第一个返回值为邮件数,第二个为占用空间resp,mails,octets=pop_server.list()#获取所有邮件列表
print(mails)index=len(mails)#获取最新的一封邮件(序号最大),邮件索引从1开始计数
resp,lines,octets=pop_server.retr(index)msg_contnt=b'\r\n'.join(lines).decode("utf-8")
msg=Parser().parsestr(msg_contnt)#解析出邮件
pop_server.dele(index)#可以根据邮件索引号直接从服务器删除邮件
pop_server.quit()#关闭连接def decode_email(s):if not s:return ""value,charset=decode_header(s)[0]if charset:value=value.decode(charset)return value#打印邮件的发件人、收件人、主题
mail_from=msg.get("From","")
hdr,mail_from_addr=parseaddr(mail_from)
mail_from_name=decode_email(hdr)
print("发件人",mail_from_name,mail_from_addr)mail_to=msg.get("To","")
hdr,mail_to_addr=parseaddr(mail_to)
mail_to_name=decode_email(hdr)
print("收件人",mail_to_name,mail_to_addr)subject=decode_email(msg.get("Subject",""))
print("主题",subject)def decode_mime(msg):#递归解析邮件if msg.is_multipart():parts=msg.get_payload()for part in parts:print(decode_mime(part))else:content_type=msg.get_content_type()if content_type in ("text/plain","text/html"):content=msg.get_payload(decode=True)print(content)else:print("Attachement",content_type)decode_mime(msg)

这封邮件运行后会在邮箱里被删除。

【Python学习笔记】(十)邮件处理:email模块;SMTP协议(smtplib模块);POP3协议(poplib模块);IMAP协议(imaplib模块)相关推荐

  1. python学习笔记[3]-邮件的发送

    本文摘抄自:http://www.cnblogs.com/xiaowuyi/archive/2012/03/17/2404015.html 一.相关模块介绍 发送邮件主要用到了smtplib和emai ...

  2. python学习笔记(十 三)、网络编程

    最近心情有点儿浮躁,难以静下心来 Python提供了强大的网络编程支持,很多库实现了常见的网络协议以及基于这些协议的抽象层,让你能够专注于程序的逻辑,而无需关心通过线路来传输比特的问题. 1 几个网络 ...

  3. Python学习笔记十 IO编程

    参考教程:廖雪峰官网https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000 IO编程 I ...

  4. python 学习笔记(十二) 文件和序列化

    python 文件读写和序列化学习. ## python文件读写 `1 打开并且读取文件` f = open('openfile.txt','r') print(f.read()) f.close() ...

  5. python学习笔记(十六)-Python多线程多进程

    一.线程&进程 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程, ...

  6. python 学习笔记十九 django深入学习四 cookie,session

    缓存 一个动态网站的基本权衡点就是,它是动态的. 每次用户请求一个页面,Web服务器将进行所有涵盖数据库查询到模版渲染到业务逻辑的请求,用来创建浏览者需要的页面.当程序访问量大时,耗时必然会更加明显, ...

  7. 【懒懒的Python学习笔记十】

    在程序运行期间遇到错误,Python会报错.Python使用被称为异常的特殊对象来管理程序运行期间发生的错误.每当发生一个错误,Python会创建一个异常对象,如果你编写了处理该异常的代码,程序将继续 ...

  8. python学习笔记十-文件操作

    对文件操作流程 1.打开文件,得到文件句柄并赋值给一个变量 2.通过句柄对文件进行操作 3.关闭文件 操作如下: 花间一壶酒,独酌无相亲. 举杯邀明月,对影成三人. 月既不解饮,影徒随我身. 暂伴月将 ...

  9. python学习笔记(十五) -- 枚举

    枚举 枚举的作用就是定义一组 数据形式为 dict 但却又不可变的常量 比如我们定义一个类,或者定义一个dict ,类中的成员变量可以被更改,而且类又可以被实例化,dict 里面的值也可以被更改. 如 ...

  10. python学习笔记十五:日期时间处理笔记

    #-*- coding: utf-8 -*- import datetime#给定日期向后N天的日期 def dateadd_day(days):d1 = datetime.datetime.now( ...

最新文章

  1. 《用Python进行自然语言处理》第2章 获得文本语料和词汇资源
  2. TensorFlow莫烦 placehoder (三)
  3. 提取过程_大米多肽提取过程中如何应用膜分离技术呢?
  4. 【LeetCode笔记】15.三数之和(JAVA、双指针)
  5. Linux中cp和scp命令的使用方法和区别
  6. JavaScript中的数组 1
  7. 天津工业大学19年计算机考研大纲,天津工业大学2019考研《计算机原理及接口技术》复试大纲...
  8. python爬取拉勾网_python爬虫—爬取拉钩网
  9. 灰色系统理论及其应用 (七) :道路交通事故灰色 Verhulst 预测模型
  10. matlab 画散点图后添加趋势线
  11. VMware 虚拟机Win10固定ip地址
  12. 虚拟机ip、主机ip、代理ip
  13. sys.path用法介绍
  14. pink老师京东关闭广告作业
  15. 【win 10】win 10:远程连接 Windows 服务器工具下载、安装和使用:PowerShell server Putty —— win 10 之间通过 ssh 登录
  16. Word文件打开的时候需要输入密码?
  17. 【硬件深似海】磁珠选型规范
  18. Linux 图片转换命令 convert
  19. 蓝海彤翔执行副总裁张加廷接受【联播苏州】独家专访
  20. IO流(输入流与输出流)

热门文章

  1. 计算机科学与技术国民经济,计算机科学与技术毕业论文
  2. 摄像头能用计算机里不显示,Windows7“计算机”不显示已连接的摄像头图标怎么办?...
  3. 生成二维码,用安卓手机扫直接下载apk,用苹果手机扫跳转至appstore
  4. 微信小程序云开发 之 登录注册界面 详细教程
  5. iOS9适配 之 关于info.plist 第三方登录 添加URL Schemes白名单
  6. Axure绘制密码输入框
  7. Random 随机数
  8. 太卷了,年薪40W的软件测试大D佬工作经验分享,原来我存在这么多问题......
  9. php 中的字符串转数组函数,php中字符串转数组的函数是什么
  10. [转载]J2me技术——跟我学制作Pak文件