使用 Python 发送电子邮件

使用 Python 的 smtplib 模块,就可以实现发送邮件。

1 电子邮件服务器

如果是网易 163 邮箱,我们可以在浏览器中登陆 https://mail.163.com/ 邮箱后,依次点击 设置 → POP3/SMTP/IMAP ,进入服务器设置页:

进入服务器设置页后,确保开启 SMTP 与 IMAP 服务。设置页的最下面就是网易邮箱的服务器地址:

(1)SMTP

发送电子邮件使用的协议是简单邮件传输协议( SMTP ,Simple Mail Transfer Protocol)。它是一种提供可靠且有效的电子邮件传输的协议。 SMTP 是建立在 FTP 文件传输服务上的一种邮件服务,主要用于系统之间的邮件信息传递,并提供有关来信的通知。 SMTP 独立于特定的传输子系统,且只需要可靠有序的数据流信道支持, SMTP 的重要特性之一是其能跨越网络传输邮件,即“ SMTP 邮件中继 ”。 使用 SMTP ,可实现相同网络处理进程之间的邮件传输,也可通过中继器或网关实现某处理进程与其他网络之间的邮件传输。

(2)IMAP

IMAP(Internet Mail Access Protocol)以前称作交互邮件访问协议(Interactive Mail Access Protocol),是一个应用层协议。IMAP是斯坦福大学在1986年开发的一种邮件获取协议。它的主要作用是邮件客户端可以通过这种协议从邮件服务器上获取邮件的信息,下载邮件等。当前的权威定义是RFC3501。IMAP协议运行在TCP/IP协议之上,使用的端口是143。

(3)POP3

POP3,全名为“Post Office Protocol – Version 3”,即“邮局协议版本3”。是TCP/IP协议族中的一员,由RFC1939 定义。本协议主要用于支持使用客户端远程管理在服务器上的电子邮件。提供了SSL加密的POP3协议被称为POP3S。

POP 协议支持 “ 离线 ” 邮件处理。其具体过程是:邮件发送到服务器上,电子邮件客户端调用邮件客户机程序以连接服务器,并下载所有未阅读的电子邮件。这种离线访问模式是一种存储转发服务,将邮件从邮件服务器端送到个人终端机器上,一般是 PC 机或 MAC 。 一旦邮件发送到 PC 机或 MAC 上,邮件服务器上的邮件将会被删除。但 POP 3邮件服务器大都可以 “ 只下载邮件,服务器端并不删除 ” ,也就是改进的 POP 3协议。


IMAP 与 POP3 协议的主要区别是用户可以不用把所有的邮件全部下载,可以通过客户端直接对服务器上的邮件进行操作。所以相对来说,IMAP 协议更先进。

2 发送电子邮件

(1)创建 SMTP 对象

首先创建一个 SMTP 对象,入参为 163 邮箱地址与端口号

smtp_obj = smtplib.SMTP('smtp.163.com', 25);

(2)建立连接

response = smtp_obj.ehlo()
logging.info('ehlo() -> %s', response)

运行结果:

INFO - ehlo() -> (250, b'mail\nPIPELINING\nAUTH LOGIN PLAIN\nAUTH=LOGIN PLAIN\ncoremail xxx\nSTARTTLS\n8BITMIME')

得到 SMTP 对象后,调用 ehlo() 方法,连接 SMTP 电子邮件服务器,。

250 就表示连接成功。

SMTP 协议有以下这些响应码,每个响应码的具体说明如下:

响应码 说明
501 参数格式错误
502 命令不可实现
503 错误的命令序列
504 命令参数不可实现
211 系统状态或系统帮助响应
214 帮助信息
220 <domain>服务就绪
221 <domain>服务关闭
421 <domain>服务未就绪,关闭传输信道
250 操作完成
251 用户非本地,将转发到<forward-path>
450 要求的操作未完成,收信端无此账户
550 要求的操作未完成,邮箱不可用
451 放弃要求的操作;处理过程中出错
551 用户非本地,请尝试<forward-path>
452 系统存储不足,要求的操作未执行
552 过量的存储分配,要求的操作未执行
553 邮箱名不可用,要求的操作未执行
554 操作失败

(3)TLS 加密

网易邮箱的 POP3/SMTP/IMAP 服务全部支持 SSL 连接。

安全传输层协议(TLS)用于在两个通信应用程序之间提供保密性和数据完整性。

传输层安全性协议( Transport Layer Security ,缩写作 TLS ),及其前身安全套接层( Secure Sockets Layer ,缩写作 SSL )是一种安全协议,目的是为互联网通信提供安全及数据完整性保障。网景公司( Netscape )在 1994 年推出首版网页浏览器,网景导航者时,推出 HTTPS 协议,以 SSL 进行加密,这是 SSL 的起源 。IETF 将 SSL 进行标准化, 1999 年公布第一版 TLS 标准文件。随后又公布 RFC5246 ( 2008 年8月)与 RFC6176 ( 2011 年3月)。在浏览器 、 邮箱 、 即时通信 、 VoIP 、 网络传真等应用程序中,广泛支持这个协议。主要的网站,如Google 、 Facebook等也以这个协议来创建安全连线,发送数据。目前已成为互联网上保密通信的工业标准。

response = smtp_obj.starttls()
logging.info('starttls() -> %s\n', response)

运行结果:

INFO - starttls() -> (220, b'Ready to start TLS')

响应码 220 表示服务器已开启 TLS 加密模式。

(4)登陆 SMTP 服务器

建立 TLS 加密连接后,就可以调用 login() 方法,用邮箱账户名与密码进行登录操作。建议使用 input() ,在程序运行时输入密码。这样做的好处是,避免因为源代码泄露,导致密码外泄。

email_address = xxx@xxx.com'
pwd = input('please input your password:')

response = smtp_obj.login(email_address, pwd)
logging.info('\nlogin() -> %s', response)

运行结果:

please input your password:> xxx
INFO - 
login() -> (235, b'Authentication successful')

login 方法接收账号与密码作为入参。这里返回 235 表示认证成功。如果密码不正确, Python 会抛出 smtplib.SMTPAuthenticationError 异常。

(5)定义发送内容

msg = MIMEMultipart()
msg["From"] = email_address
to_mail_address = yyy@yyy.com'
msg['To'] = to_mail_address
msg['Subject'] = '确认《Spring Cloud微服务架构》'
content = MIMEText('收到这本书后,<b>请回复下</b>', 'html', 'utf-8')
msg.attach(content)

先创建 MIMEMultipart 对象,然后定义以下内容:

说明
From 发送端邮箱地址。
To 接收端邮箱地址。
Subject 邮箱标题。
content 邮箱内容,HTML 格式。

(6)发送邮件

response = smtp_obj.sendmail(email_address, to_mail_address, msg.as_string())
logging.info('sendmail() -> %s', response)

运行结果:

INFO - sendmail() -> {}

然后调用 sendmail()方法来发送电子邮件。 sendmail() 的返回值是一个字典类型。如果发送失败,那么该字典就会返回包含失败收件人的键值对信息;如果发送成功,那么该字典为空。

(7)断开连接

response = smtp_obj.quit()
logging.info('quit() -> %s', response)

运行结果:

INFO - quit() -> (221, b'Bye')

发送电子邮件后,调用 quit()方法,断开与 SMTP 服务器的连接。 响应码 221 表示会话结束。


完整示例如下:

import logging
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

logging.basicConfig(level=logging.DEBUG, format='%(levelname)s - %(message)s')

'''
send email
@author Deniro Lee
'''
print('$$$')
smtp_obj = smtplib.SMTP('smtp.163.com', 25);
response = smtp_obj.ehlo()
logging.info('ehlo() -> %s', response)
response = smtp_obj.starttls()
logging.info('starttls() -> %s\n', response)

email_address = xxx@xxx.com'
pwd = input('please input your password:')

response = smtp_obj.login(email_address, pwd)
logging.info('\nlogin() -> %s', response)

msg = MIMEMultipart()
msg["From"] = email_address
to_mail_address = yyy@yyy.com'
msg['To'] = to_mail_address
msg['Subject'] = '确认《Spring Cloud微服务架构》'
content = MIMEText('收到这本书后,<b>请回复下</b>', 'html', 'utf-8')
msg.attach(content)

response = smtp_obj.sendmail(email_address, to_mail_address, msg.as_string())
logging.info('sendmail() -> %s', response)

response = smtp_obj.quit()
logging.info('quit() -> %s', response)

运行结果:

INFO - ehlo() -> (250, b'mail\nPIPELINING\nAUTH LOGIN PLAIN\nAUTH=LOGIN PLAIN\ncoremail xxx\nSTARTTLS\n8BITMIME')
INFO - starttls() -> (220, b'Ready to start TLS')
please input your password:> xxx
INFO - 
login() -> (235, b'Authentication successful')
INFO - sendmail() -> {}
INFO - quit() -> (221, b'Bye')

打开发送目标邮箱后,就会看到刚刚发出的这封邮件:

发表评论