起源
就是通信的一个发展,懒得打字了省略了,以后再查吧
管理程序
一些让邮件普及的邮件公司
MUA(MailUserAgent)邮件用户代理
MTA(MailTransferAgent)邮件传输代理
MDA(MailDeliveryAgent)邮件投递代理
流程
MUT->MTA
qq MTA->...........................->sina MTA
sina MTA->.........................->sina MDA
sina MDA->MUA(FoxMail/outlook)邮件下载到本地电脑
编写程序
发送 MUA->MTA 协议
接收 MTA->MDA 协议
准备工作
注册邮箱
第三方邮箱进行设置
进入设置中心
取得授权码
案例07发送纯文本邮件‘
import smtplib
from email.mime.text import MIMEText
#MIMEText的主要参数有3个
#1。邮件内容
#2。MIME子类型,在这里用plain代表text格式的文件
#3.邮件的编码格式
msg = MIMEText('这是一封文本格式的邮件','plain','utf-8')
#发送email的地址,需要更改为对应的邮件地址
from_addr = '[email protected]'
#授权密码,大多数的邮箱在使用第三方软件时,都需要验证密钥,这里不是指邮箱的密码
from_pwd = 'XXXXXXXXXXX'
#收件人
to_addr = '[email protected]'
#输入smtplib服务器地址
#此处根据不同的邮件服务商有不同的值
#现在基本任何一家邮件服务商在开启第三方邮件的时候都需要开启服务
#TX QQ邮箱的smtplib地址时smtplib.qq.com
smtp_srv = 'smtplib.qq.com'
try:
srv = smtplib.SNTP_SSL(smtp_srv.encode(),465) #这里的465时QQ邮箱的端口
#登陆邮箱,任何的邮箱在使用之前都必须的登陆
srv.login(from_addr,from_pwd)
#发送邮件
#三参数,发送地址,接受的地址(必须时list格式),发送内容时字符串格式
srv.sendmail(from_addr,[to_addr],msg.as_String())
srv.quit()
except Exception as e:
print(e)
Python for mail
SMTP协议负责发送邮件
使用Email模块构建邮件-纯文本案例V07
HTML格式邮件发送
准备HTML代码作为内容
把邮件的subtype设为html
发送
案列V08
import smtplib
from email.mime.text import MIMEText
#MIMEText的主要的三个参数
#1。邮件内容
#2。MIME子类型的格式 这里时HTML所以是html
#3.邮件的编码格式
msg_content = """
Title
这是一封HTML格式的邮件
"""
#发送邮件的地址
from_addr = '[email protected]'
#发送邮件的密码
from_pwd = 'XXXXXXXXXXx'
#收件人
to_addr = '[email protected]'
#输入SMTP服务器地址
smtp_srv = 'smtp.qq.com'
try:
srv = smtplib.SMTP_SSL(smtp_srv.encode(),465)
#登陆邮箱
srv.login(from_addr,from_pwd)
#发送邮件
srv.sendemail = (from_addr,[to_addr],msg_content.as_toString())
srv.quit()
except Exception as e:
print(e)
发送带附件的邮件
可以看作有一个文本邮件和一个附件的合体
需要使用MIMEltaipart格式构建
添加一个MIMEBase或者MEME text作为附件
案列V09
import smtplib
from email.mime.text import MIMEText
from email.mime.text import MIMEBase,MIMMultipart #构建基础邮件时使用
mail_mul = MIMEMulipart()
#构建邮件正文
main_text = MIMEText("这是邮件的正文",'plain','utf-8')
#把构建的正文附加到邮件中
mail_mul.attach(mail_text)
#构建附件,需要从本地读入
#打开一个本地文件
with open('a.txt','rb') as f:
s = f.read()
#设置附件的MIME文件名
m = MIMEText(s,'base64','utf-8')
m['Content-Type'] = 'application.octet-stream'
#需要注意的
#1.attachment后的分号时英文状态
#2.filename 后面需要英文包裹,注意外面的引号错开
m['Content-Dispostion'] = 'attachment;filename="a.txt"'
#添加MIMEMultipation
mail_mul.attach(m)
#发送邮件
from_addr = '[email protected]'
from_pwd = 'XXXXXXXXx'
to_addr = 'XXXXXXX@qq,com'
smtp_srv = 'sntp.qq.com'
try:
srv = smtplib.SMTP_SSL(smtp_srv.encode(),465)
#登陆邮箱
srv.load(from_addr,from_pwd)
srv.sendmail(from_addr,[to_addr],mail_mul.as_string())
srv.quit()
except Exception as e:
print(e)
添加邮件头,抄送等信息
mail['From'] 表示发送者的信息,包括姓名和邮件
mail['To'] 表示接收者信息,包括姓名和邮件地址
mail['Subject']表示摘要或者主题信息
案例V10
同时支持html和text格式
构建一个MIMEMultipart格式的邮件
MIMEMultipart的subtype设置成alterbalive
添加html 文件和text文件
import smtplib
from email.mime.text import MIMEText
from email,mime.multipart import MIMEMUltipart
#构建一个MIMEMultipart邮件
msg = MIMEMultapart('alternative')
#构建一个HTML格式的邮件内容
html_content = """
Title
这是一封HTML格式的邮件
"""
msg_html = MIMEText(html_content,'html','utf-8')
msg.attach(msg_html)
#构建一个文本格式的邮件
msg_text = MIMEText("这是文本格式的邮件",'plain','utf-8')
msg.attach(msg_text)
from_addr = '[email protected]'
from_pwd = 'XXXXX'
to_addr = "[email protected]"
smtp_srv = 'smtp.qq.com'
try:
srv = smtplib.SMTP_SSL(smtp_srv.encode(),465)
srv.login(from_addr,from_pwd)
srv_sendmail(from_addr,[to_addr],msg.as_tostring())
srv.quit()
except Exception as e:
print(e)
使用smtplib模块发送邮件
POP3协议接受邮件
本质上讲是从MDA到MTA的一个过程
从MDA下载下来的是一个完整的邮件结构体,需要解析才能的带每个具有
步骤:
1.用poplib下载邮件结构体原始内容
1.准备相应的内容(邮件的内容,密码。pop3实例)
2.身份验证
3.一般会先得到邮箱内邮件的整体列表
4.根据相应的序号,得到某一封信的数据流
5.利用解析函数进行解析出相应的邮件结构体
2.emai解析邮件的具体内容
案例V12
#导入相关的包
#poplib负责相关的MDA到MUA的下载
import poplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
#得到邮件的原始内容
#这个过程主要看负责从MDA带MUA的下载并且使用Parse粗略的解析
def getMsg():
#准备相应的信息
email = '[email protected]'
#邮箱的授权码
pwd = 'pwd'
#pop3的服务器地址 默认端口995
pop3_srv = 'pop.qq.com'
#SSL代表安全通道
srv = poplib.POP3_SSL(pop3_srv)
#user代表Email地址
srv.user(email)
#pass_代表密码
srv.pass_(pwd)
#一下操作根据业务内容具体使用
#stat返回邮件的数量和占用的空间
#注意stat返回一个tuple格式
msgs,counts = srv.stat()
print("messages:{0},Size{1}".format(msgs,counts))
#list返回所有的邮件编号列表
#malis返回所有邮件编号列表
rsp,mails,octets = srv.list()
#可以查看返回mails列表类似
print(mails)
#获取最新一封邮件,注意,邮件的索引号从1开始,最新的邮件索引号最高
index = len(mails)
#retr 负责返回一个具体索引号的一封信的内容,此内容不具有可读性
#lines 存储邮件的最高原始文本的每一行
rsp,lines,octets = srv.retr(index)
#获取整个邮件的原始文本
msg_count = b'\r\n'.join(lines).decode('utf8')
#解析出邮件的整个结构体
#参数时解码后的邮件整体
msg = Parser().parsestr(msg_count)
#关闭链接
srv.quit()
return msg
#
#详细解释得到的邮件内容
#msg表示邮件的原始内容
#idnent代表的是邮件的嵌套层级
def parseMsg(msg,indent=0):
'''
1.邮件可能是完全嵌套
2.邮件只有一个From,To,Subject之类的信息
:param msg:
:param indent: 描述邮件里面的几个邮件的MIMEXXX类型的内容,展示的时候进行缩进
:return:
'''
#想办法提取头部信息
#只有在第一层的邮件中才会有相关信息内容
#此内容只有一个
if indent == 0:
for header in ['From','To','Subject']:
#使用get可以避免如果没有相关关键字报错的可能性
#如果没有关键字“From"在使用msg["From"]时会报错
value = msg.get(header,'')
if value:
#Subject中的内容直接解码就可以,他是字符串类型
if header == 'Subject':
value = decodeStr(value)
#如果是From和To字段,则内容的大概是‘我的邮箱’这种格式
else:
hdr,addr = parseaddr(value)
name = decodeStr(hdr)
#最终的返回类型如“我的邮箱是”
value = "{0}<{1}>.".format(name,addr)
print("{0},{1}:{2}".format(indent,header,value))
#接下来关注邮件内容本身
#邮件内容中,有可能是multipart类型,也有可能是普通邮件类型
#下面的解析使用递归的方法
if (msg.is_multipart()):
#如果是multipart类型则调用递归解释
#得到多部分邮件的一个基础邮件部分
parts = msg.get_payload()
#enumerate函数是内置函数
#作用是将一个列表,此处是parts,生成一个有索引和parts原内容生成的列表
#例如:enumerate(['a','b','c'])结果是:[(1,'a'),(2,'b'),(3,'c')]
for n,part in enumerate(parts):
#一个字符串乘以一个数字的意思就是对这个字符串进行n倍扩展
#例如("aa"*2) = 'aaaa'
print("{0}spart:{1}".format(' '*indent,n))
parseMsg(part,indent+1)
else:#基础类型
#get_content_type是系统函数,得到内容的类型
content_type = msg.get_content_type()
#text/plain,或者是text/html是固定值
if content_type == 'text/plain' or content_type == 'text/html':
content = msg.get_payload(decode=True)
charset = gussCharset(msg)
if charset:
content = content.decode(charset)
print("{0}text:{1}".format(indent,content))
else:#不是文本内容,因该是附件
print('{0}Attachment:{1}'.format(indent,content_type))
def decodeStr(s):
'''
s代表一封邮件中的from,to,Subject中的任意一项
对s进行解码,解码是通过编码的逆过程
:param s:
:return:
'''
value,charset = decode_header(s)[0]
#charset完全可能为空
if charset:
#如果指定编码,则用指定的编码格式进行解码
value = value.decode(charset)
return value
def gussCharset(msg):
'''
猜测邮件的编码格式
:param msg:
:return:
'''
#调用现成的函数
charset = msg.get_charset()
if charset is None:
#找到相应的内容类型转换成小写
content_type = msg.get("Content-Type","").lower()
pos = content_type.find('charset=')
if pos > 0:
#如果包含charset,则内容为charset=XXX
charset = content_type[pos+8:].strip()
return charset
if __name__ == '__main__':
#得到邮件的原始内容
msg = getMsg()
print(msg)
#精确解析邮件的内容
parseMsg(msg,0)