SMTP(Simple Mail Transfer Protocol) 即简单邮件传输协议, 它是一组用于由源地址到目的地址传送邮件的规则, 由它来控制信件的中转方式.
python 的 smtplib 提供了一种很方便的途径发送电子邮件. 它对 smtp 协议进行了简单的封装.
创建 SMTP 对象
Python 创建 SMTP 对象语法如下:
- import smtplib
- smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
参数说明:
host: SMTP 服务器主机. 这个是可选参数, 一般情况下咱们查看邮箱的设置是可以看到的.
port: 如果你提供了 host 参数, 你需要指定 SMTP 服务使用的端口号, 一般情况下 SMTP 端口号为 25.
local_hostname: 如果 SMTP 在你的本机上, 你只需要指定服务器地址为 localhost 即可.
发送邮件
Python SMTP 对象使用 sendmail 方法发送邮件, 语法如下:
SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])
参数说明:
from_addr: 邮件发送者地址.
to_addrs: 字符串列表, 邮件发送地址.
msg: 发送消息
这里要注意一下第三个参数, msg 是字符串, 表示邮件. 我们知道邮件一般由标题, 发信人, 收件人, 邮件内容, 附件等构成, 发送邮件的时候, 要注意 msg 的格式. 这个格式就是 smtp 协议中定义的格式.
使用系统自带的 mail 发送, 只为测试
- #!/usr/bin/python
- # -*- coding: UTF-8 -*-
- import smtplib
- from email.mime.text import MIMEText
- from email.header import Header
- mail_user = 'local@admin.com'
- to_list = ['417685417@qq.com'] # 接收邮件, 可设置为你的 QQ 邮箱或者其他邮箱
- # 三个参数: 第一个为文本内容, 第二个 plain 设置文本格式, 第三个 utf-8 设置编码
- message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
- message['From'] = mail_user # 发送者
- message['To'] = ",".join(to_list) # 接收者
- subject = 'Python SMTP 邮件测试' #邮件主题
- message['Subject'] = Header(subject, 'utf-8')
- try:
- smtpObj = smtplib.SMTP('localhost')
- smtpObj.sendmail(mail_user, to_list, message.as_string())
- print "邮件发送成功"
- except smtplib.SMTPException:
- print "Error: 无法发送邮件"
我们使用三个引号来设置邮件信息, 标准邮件需要三个头部信息: From, To, 和 Subject , 每个信息直接使用空行分割.
我们通过实例化 smtplib 模块的 SMTP 对象 smtpObj 来连接到 SMTP 访问, 并使用 sendmail 方法来发送信息.
如果我们本机没有 sendmail 访问, 也可以使用其他邮件服务商的 SMTP 访问 (QQ, 网易, Google 等).
使用邮件服务商提供的 SMTP 服务
- #!/usr/bin/python
- # -*- coding: UTF-8 -*-
- import smtplib
- from email.mime.text import MIMEText
- from email.header import Header
- # 第三方 SMTP 服务
- mail_host="smtp.XXX.com" #设置服务器
- mail_user="XXXX" #用户名
- mail_pass="XXXXXX" #口令
- mail_user = 'wangshenghui@oldboyedu.com'
- to_list = ['417685417@qq.com'] # 接收邮件, 可设置为你的 QQ 邮箱或者其他邮箱
- # 三个参数: 第一个为文本内容, 第二个 plain 设置文本格式, 第三个 utf-8 设置编码
- message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
- message['From'] = mail_user # 发送者
- message['To'] = ",".join(to_list) # 接收者
- subject = 'Python SMTP 邮件测试' #邮件主题
- message['Subject'] = Header(subject, 'utf-8')
- try:
- smtpObj = smtplib.SMTP()
- smtpObj.connect(mail_host, 25) # 25 为 SMTP 端口号
- smtpObj.login(mail_user,mail_pass)
- smtpObj.sendmail(mail_user, to_list, message.as_string())
- print "邮件发送成功"
- except smtplib.SMTPException:
- print "Error: 无法发送邮件"
发送 html 邮件
Python 发送 HTML 格式的邮件与发送纯文本消息的邮件不同之处就是将 MIMEText 中_subtype 设置为 HTML. 具体代码如下:
- import smtplib
- from email.mime.text import MIMEText
- from email.header import Header
- mail_host="smtp.XXX.com" #设置服务器
- mail_user="XXXX" #用户名
- mail_pass="XXXXXX" #口令
- mail_user = 'wangshenghui@oldboyedu.com'
- to_list = ['417685417@qq.com'] # 接收邮件, 可设置为你的 QQ 邮箱或者其他邮箱
- # 三个参数: 第一个为文本内容, 第二个 plain 设置文本格式, 第三个 utf-8 设置编码
- mail_msg = """
- <p>Python 邮件发送测试...</p>
- <p><a href="http://www.baidu.com"> 这是一个链接 </a></p>
- """message = MIMEText('mail_msg','html','utf-8')
- message['From'] = mail_user # 发送者
- message['To'] = ",".join(to_list) # 接收者
- subject = 'Python SMTP 邮件测试' #邮件主题
- message['Subject'] = Header(subject, 'utf-8')
- try:
- smtpObj = smtplib.SMTP()
- smtpObj.connect(mail_host, 25) # 25 为 SMTP 端口号
- smtpObj.login(mail_user,mail_pass)
- smtpObj.sendmail(mail_user, to_list, message.as_string())
- print "邮件发送成功"
- except smtplib.SMTPException:
- print "Error: 无法发送邮件"
发送带附件的邮件
基本思路就是, 使用 MIMEMultipart 来标示这个邮件是多个部分组成的, 然后 attach 各个部分. 如果是附件, 则 add_header 加入附件的声明.
在 python 中, MIME 的这些对象的继承关系如下.
- MIMEBase
- |-- MIMENonMultipart
- |-- MIMEApplication
- |-- MIMEAudio
- |-- MIMEImage
- |-- MIMEMessage
- |-- MIMEText
- |-- MIMEMultipart
一般来说, 不会用到 MIMEBase, 而是直接使用它的继承类. MIMEMultipart 有 attach 方法, 而 MIMENonMultipart 没有, 只能被 attach.
MIME 有很多种类型, 这个略麻烦, 如果附件是图片格式, 我要用 MIMEImage, 如果是音频, 要用 MIMEAudio, 如果是 Word,Excel, 我都不知道该用哪种 MIME 类型了, 得上 google 去查.
最懒的方法就是, 不管什么类型的附件, 都用 MIMEApplication,MIMEApplication 默认子类型是 application/octet-stream.
application/octet-stream 表明 "这是个二进制的文件, 希望你们那边知道怎么处理", 然后客户端, 比如 qq 邮箱, 收到这个声明后, 会根据文件扩展名来猜测.
假设当前目录下有 derek.xlsx/derek.jpg/derek.PDF/derek.mp3 这 4 个文件.
- import smtplib
- from email.mime.multipart import MIMEMultipart
- from email.mime.text import MIMEText
- from email.mime.application import MIMEApplication
- mail_host="smtp.XXX.com" #设置服务器
- mail_user="XXXX" #用户名
- mail_pass="XXXXXX" #口令
- # 如名字所示 Multipart 就是分多个部分
- msg = MIMEMultipart()
- msg["Subject"] = "这是个带附件的邮件"
- msg['From'] = mail_user # 发送者
- msg['To'] = ",".join(to_list) # 接收者
- #--- 这是文字部分 ---
- part = MIMEText("停车坐爱枫林晚, 霜叶红于二月花!")
- msg.attach(part)
- #--- 这是附件部分 ---
- #xlsx 类型附件
- part = MIMEApplication(open('derek.xlsx','rb').read())
- part.add_header('Content-Disposition', 'attachment', filename="derek.xlsx")
- # 这里的 filename 可以任意写, 写什么名字, 邮件中显示什么名字
- msg.attach(part)
- # 文本类型
- att1 = MIMEApplication(open('manage.py', 'rb').read())
- att1.add_header('Content-Disposition','attachment', filename="manage.txt")
- msg.attach(att1)
- #jpg 类型附件
- part = MIMEApplication(open('derek.jpg','rb').read())
- part.add_header('Content-Disposition', 'attachment', filename="derek.jpg")
- msg.attach(part)
- #PDF 类型附件
- part = MIMEApplication(open('derek.pdf','rb').read())
- part.add_header('Content-Disposition', 'attachment', filename="derek.pdf")
- msg.attach(part)
- #mp3 类型附件
- part = MIMEApplication(open('derek.mp3','rb').read())
- part.add_header('Content-Disposition', 'attachment', filename="derek.mp3")
- msg.attach(part)
来源: http://blog.51cto.com/wangfeng7399/2346369