SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。
Python对SMTP支持有smtplib
和email
两个模块,email
负责构造邮件,smtplib
负责发送邮件。
普通正文邮件:
#/usr/bin/env python #coding=utf-8 from email import encoders from email.header import Header from email.mime.text import MIMEText from email.utils import parseaddr, formataddr import smtplib def _format_addr(s): name, addr = parseaddr(s) return formataddr((Header(name, 'utf-8').encode(), addr)) from_addr = 'zy5724@163.com' password = 'xxxxx' to_addr = 'scottcho@qq.com' smtp_server = 'smtp.163.com' msg = MIMEText('hello, send by Python...', 'plain', 'utf-8') msg['From'] = _format_addr('Python爱好者 <%s>' % from_addr) msg['To'] = _format_addr('管理员 <%s>' % to_addr) msg['Subject'] = Header('来自SMTP的问候……', 'utf-8').encode() try: 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() print 'send OK' except Exception, e: print str(e)
注意到构造MIMEText
对象时,第一个参数就是邮件正文,第二个参数是MIME的subtype,传入'plain'
表示纯文本,最终的MIME就是'text/plain'
,最后一定要用utf-8
编码保证多语言兼容性。
我们用set_debuglevel(1)
就可以打印出和SMTP服务器交互的所有信息。SMTP协议就是简单的文本命令和响应。login()
方法用来登录SMTP服务器,sendmail()
方法就是发邮件,由于可以一次发给多个人,所以传入一个list
,邮件正文是一个str
,as_string()
把MIMEText
对象变成str
。
收到的邮件:
带有附件的邮件:
#/usr/bin/env python # coding: utf-8 from email import encoders from email.header import Header from email.mime.text import MIMEText from email.MIMEBase import MIMEBase from email.utils import parseaddr, formataddr from email.mime.multipart import MIMEMultipart import smtplib def _format_addr(s): name, addr = parseaddr(s) return formataddr(( Header(name, 'utf-8').encode(), addr.encode('utf-8') if isinstance(addr, unicode) else addr)) from_addr = 'zy5724@163.com' password = 'xxxx' to_addr = 'scottcho@qq.com' smtp_server = 'smtp.163.com' # 邮件对象: msg = MIMEMultipart() msg['From'] = _format_addr(u'张三 <%s>' % from_addr) msg['To'] = _format_addr(u'管理员 <%s>' % to_addr) msg['Subject'] = Header(u'来自SMTP的问候……', 'utf-8').encode() # 邮件正文是MIMEText: msg.attach(MIMEText('send with file...', 'plain', 'utf-8')) # 添加附件就是加上一个MIMEBase att1 = MIMEText(open('/python/new.txt', 'rb').read(), 'base64', 'utf-8') att1["Content-Type"] = 'application/octet-stream' att1["Content-Disposition"] = 'attachment; filename="new.txt"' msg.attach(att1) #再添加一个图片附件 with open('/python/Koala.jpg', 'rb') as f: att2 = MIMEBase('image', 'jpg', filename='Koala.jpg') att2.add_header('Content-Disposition', 'attachment', filename='Koala.jpg') att2.add_header('Content-ID', '<0>') att2.set_payload(f.read()) encoders.encode_base64(att2) msg.attach(att2) 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()
我们编写了一个函数_format_addr()
来格式化一个邮件地址。注意不能简单地传入name <addr@example.com>
,因为如果包含中文,需要通过Header
对象进行编码。
结果:
使用开源的yagmail发送邮件
yagmail底层依然使用smtplib和email模块,但是它提供了更加Pythonic的接口。
安装: pip install yagmail
查看邮件: