#Python基于smtp协议发送邮件
首先介绍下电子邮件的基本流程:
发件人 -> MUA -> MTA -> MTA -> 若干个MTA -> MDA <- MUA <- 收件人
MUA:Mail User Agent 邮件用户代理
MTA:Mail Transfer Agent 邮件传输代理
MDA:Mail Delivery Agent 邮件投递代理
发邮件时,MUA和MTA使用的协议就是SMTP:Simple Mail Transfer Protocol,后面的MTA到另一个MTA也是用SMTP协议
收邮件时,MUA和MDA使用的协议有两种:
POP:Post Office Protocol,目前版本是3,俗称POP3;
IMAP:Internet Message Access Protocol,目前版本是4,优点是不但能取邮件,还可以直接操作MDA上存储的邮件,比如从收件
箱移到垃圾箱,等等。
今天主要介绍的是基于SMTP的邮件发送:
SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。
Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。
简单的发一个邮件:
from email.mime.text import MIMEText
import smtplib
msg = MIMEText('you are buautiful','plain','utf-8')
#第一个参数是邮件正文,第二个传plain表示纯文本,第三个utf-8保证了多语言的兼容性
from_addr = input('From:') #输入发件人地址
password = input('password:') #输入客户端授权密码
to_addr = input('To:') #输入收件人地址
smtp_server = input('Smtp_server:')
#输入收件人邮箱的SMTP服务器 像网易163邮箱的就是smtp.163.com,可以查到的。注意不要写成stmp!!!!
msg['From'] = from_addr #显示邮件的发信人
msg['To'] = to_addr #显示邮件的收信人
msg['Subject'] = 'love and peace' #显示邮件的标题
server = smtplib.SMTP(smtp_server,25) #注意这里SMTP协议默认端口25
#SMTP的构造函数,功能:与smtp服务器建立连接,在连接成功后,就可以向服务器发送相关请求,如登陆,校验,发送,退出等
server.set_debuglevel(1) #打印出和SMTP服务器交互的所有信息,当然你可以选择去掉这句
server.login(from_addr,password) #登录SMTP服务器
server.sendmail(from_addr,[to_addr],msg.as_string())
#发邮件,第二个参数是list,因为可以同时发给几个人嘛,至于as_string()是把MIMEText对象变成str。
server.quit() #断开与SMTP服务器的连接
不出意外的话发送是能成功的,但邮件可能被邮箱放入垃圾箱了。。。。。。。。。。。
结果应该是这样:
但同时你也会发现,收件人和发件人显示的都是你邮箱默认的名字,但是你想自己起个名字怎么办呢
很简单你将上面那两句换成这两句就可以了
msg['From'] = 'sb <%s>' %from_addr
msg['To'] = 'gua pi <%s>' %to_addr
结果如下图:
但是你自己想起的名字是中文的,那么再简单的将上面两句换掉就不行了,
如果包含中文,需要通过Header
对象进行编码。
from email.utils import parseaddr,formataddr
from email.header import Header
def A(s): #创建一个函数A,用以得到Header处理后的地址
a,b = parseaddr(s) #parseaddr函数用于解析字符串中的email地址
return formataddr((Header(a,'utf-8').encode(),b))
msg['From'] = A('傻逼 <%s>' %from_addr)
msg['To'] = A('瓜皮 <%s>' %to_addr)
msg['Subject'] = Header('爱与和平','utf-8').encode()
注意:
parseaddr()不是内置函数,见于email.utils, 用来解析字符串中的email地址
例如:注意邮箱必须用<>括起来才能解析
>>> A = 'helloworld<[email protected]>'
>>> from email.utils import parseaddr,formataddr
>>> m,n = parseaddr(A)
>>> m
'helloworld'
>>> n
formataddr()则和parseaddr()相反:不过要注意的是传入的是一个tuple
>>> m
'helloworld'
>>> n
>>> formataddr((m,n))
'helloworld <[email protected]>'
而且你还想发送一张图片(作为附件)过去,怎么做呢??
带附件的邮件可以看做包含若干部分的邮件:文本和各个附件本身,所以,可以构造一个MIMEMultipart
对象代表邮件本身,然后往
里面加上一个MIMEText
作为邮件正文,再继续往里面加上表示附件的MIMEBase
对象即可:
from email.mime.text import MIMEText
import smtplib
from email.mime.base import MIMEBase
from email import encodersfrom email.mime.multipart import MIMEMultipart
from email.utils import parseaddr,formataddrfrom email.header import Header
msg = MIMEMultipart() #邮件对象
msg.attach(MIMEText('you are buautiful','plain','utf-8')) #邮件正文是MIMEText,添加进去
with open(r'C:\Users\14547\Desktop\picture\me.jpg','rb') as f:
#添加附件就是添加一个MIMEBase,从本地读取一个图片
mime = MIMEBase('image','png',filename = 'you.png')#设置附件的MIME和文件名,类型是png类型
mime.add_header('Content-Disposition','attachment',filename = 'you.png') #这里加上必要的头信息
mime.add_header('X-Attachment-Id','0')
mime.set_payload(f.read()) #把附件的内容读进来 encoders.encode_base64(mime) #用Base64编码
def A(s):
a,b = parseaddr(s)
return formataddr((Header(a,'utf-8').encode(),b))
from_addr = input('From:')
password = input('password:')to_addr = input('To:')
smtp_server = input('Smtp_server:')
msg['From'] = A('傻逼 <%s>' %from_addr)
msg['To'] = A('瓜皮 <%s>' %to_addr)
msg['Subject'] = Header('爱与和平','utf-8').encode()
server = smtplib.SMTP(smtp_server,25)
server.set_debuglevel(1)
server.login(from_addr,password)
server.sendmail(from_addr,[to_addr],msg.as_string())
server.quit()
然后输出如下:可以看到名字是中文的然后内容也成功包含了附件。
2017.10.27.23:23 写的有点累,一些没有说明白的明天再说。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。