本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1 SMTP协议介绍
简单邮件传输协议 / 发送邮件服务器(SMTP:Simple Mail Transfer Protocol)是用于电子邮件传输的通信协议。 Is 是一个 Internet 标准,该标准于 1982 年由 RFC 821 首次定义,并于 2008 年由 RFC 5321 更新为扩展 SMTP 添加。 邮件服务器和其他邮件传输代理使用 SMTP 发送和接收邮件。
2 python smtplib模块使用
smtplib是一个 Python 库,用于使用简单邮件传输协议(SMTP)发送电子邮件。 smtplib是内置模块; 我们不需要安装它。 它抽象了 SMTP 的所有复杂性。
2.1 发送邮件到本地邮件服务器
1、要实际发送电子邮件,我们需要有权访问邮件服务器。 Python 带有一个简单的开发邮件服务器。 Mailslurper 是易于使用的本地开发服务器。 共享的虚拟主机提供商使我们可以访问邮件服务器。 我们可以在帐户中找到详细信息。
注意:避免使用 Gmail,因为它是高度安全的服务器,并且使其工作非常复杂。 实际上,Internet 上的大多数(如果不是全部)示例演示了如何通过 Gmail 服务器发送电子邮件,这些示例都无法正常工作。 而是使用开发服务器或共享的虚拟主机服务器。
最后,我们可以使用 Web 服务。 有开发 Web 服务(例如 MailTrap 或 MailSlurp)或生产服务(例如 Mailgun 或 Mandrill)。
2、使用 Python 内置邮件服务器
python -m smtpd -c DebuggingServer -n localhost:1025
运行上面的命令,就可以在端口1025上启动 Python 内置邮件服务器。
3、向服务器上发送邮件信息
我们向上面python本地的邮件服务器,发送邮件,发送脚本如下:
import smtplib
from email.mime.text import MIMEText
# 向本地开发邮件服务器发送一条简单的文本信息
# 发送者的邮箱 example.com是专门用于文档中的说明性示例的域名
sender = 'admin@example.com'
# 接收者的邮箱
receivers = ['info@example.com']
# 服务器的端口
port = 1025
# 发送到服务器的文本信息
msg = MIMEText('This is test mail')
# print(msg, type(msg)) # This is test mail <class 'email.mime.text.MIMEText'>
msg['Subject'] = 'Test mail'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'
# MimeText用于发送文本电子邮件。我们提供主题,从选项到选项
# SMTP类管理 与 SMTP服务器的连接
with smtplib.SMTP('localhost', port) as server:
# 由于我们使用本地开发服务器,因此不用登录
# server.login('username', 'password')
# 电子邮件带有sendmail()发送
server.sendmail(sender, receivers, msg.as_string())
print("Successfully sent email")
发送电子邮件后,我们会在开启的本地邮件服务器的一端,接收到发送的消息
(base) PS C:\Users\shl> python -m smtpd -c DebuggingServer -n localhost:1025
---------- MESSAGE FOLLOWS ----------
b'Content-Type: text/plain; charset="us-ascii"'
b'MIME-Version: 1.0'
b'Content-Transfer-Encoding: 7bit'
b'Subject: Test mail'
b'From: admin@example.com'
b'To: info@example.com'
b'X-Peer: ::1'
b''
b'This is test mail'
------------ END MESSAGE ------------
2.2 发送邮件到Mailtrap服务器
Mailtrap提供了一项免费计划,使我们每个月可以发送 500 封邮件。 设置 Mailtrap 非常容易。 如果我们拥有 Github 或 Google 帐户,则只需几秒钟。
设置页面中提供了必要的凭据。 另外,还有一些简短的代码示例显示了如何使用服务,包括smtplib,Django或Flask。
mailtrap_simple.py
import smtplib
from email.mime.text import MIMEText
# 向本地开发邮件服务器发送一条简单的文本信息
# 发送者的邮箱 example.com是专门用于文档中的说明性示例的域名
sender = 'admin@example.com'
# 接收者的邮箱
receivers = ['info@example.com']
# 服务器的端口
port = 1025
# 发送到服务器的文本信息
msg = MIMEText('This is test mail')
# print(msg, type(msg)) # This is test mail <class 'email.mime.text.MIMEText'>
msg['Subject'] = 'Test mail'
msg['From'] = 'admin@example.com'
msg['To'] = 'info@example.com'
user = 'xxxx@gmail.com'
password = 'xxx@bxx'
# MineText用于发送文本电子邮件。我们提供主题,从选项到选项
# SMTP类管理 与 SMTP服务器的连接
with smtplib.SMTP('smtp.mailtrap.io', 2525) as server:
server.login(user, password)
# 电子邮件带有sendmail()发送
server.sendmail(sender, receivers, msg.as_string())
print("Successfully sent email")
报错:smtplib.SMTPServerDisconnected: Connection unexpectedly closed
说解决方案是在:server.login()前加上如下两行代码,但是我尝试并不可行(参考)
server.ehlo()
server.starttls()
2.3 发送邮件到qq服务器
这里用到了Python的两个包来发送邮件: smtplib 和 email 。
Python 的 email 模块里包含了许多实用的邮件格式设置函数,可以用来创建邮件“包裹”。使用的 MIMEText 对象,为底层的 MIME(Multipurpose Internet MailExtensions,多用途互联网邮件扩展类型)协议传输创建了一封空邮件,最后通过高层的SMTP 协议发送出去。 MIMEText 对象 msg 包括收发邮箱地址、邮件正文和主题,Python 通过它就可以创建一封格式正确的邮件。smtplib 模块用来设置服务器连接的相关信息。
要想通过QQ邮箱来发送邮件,需要开启QQ邮箱的设置-账户里SMTP服务,接下来会通过发送短信验证来获得授权码,有了授权码后就可以在代码里添加了。(参考)
使用qq邮箱给其他的邮箱发送简单的文本信息
1、首先获取发送者邮箱的授权码,这里我发送者用的是QQ邮箱,下面说下QQ邮箱如何获取授权码
1)首先登录qq账号邮箱,然后在设置-账户下找到SMTP服务
2)点击生成授权码,之后会让你发送短信,用户获取授权码
3)发送短信成功之后,会看到16位长度的授权码,如下图(后面使用授权码的时候,不要加空格)
2、下面是获取发送者邮箱服务器的域名和端口,这里我们的发送者使用的是QQ邮箱,其邮件服务器和端口为:
- QQ发送邮件服务器:
smtp.qq.com - 使用
SSL,端口号为465或587
def send_text_info():
import smtplib
from email.mime.text import MIMEText
# 向本地开发邮件服务器发送一条简单的文本信息
# 发送者的邮箱 example.com是专门用于文档中的说明性示例的域名
sender = '931762054@qq.com'
password = 'xnsgcuuavelrbbdj' # 发送者邮箱的授权码
# 接收者的邮箱,接收者可以是多个,因此是一个列表
receivers = ['shliang0603@gmail.com']
# 发送到服务器的文本信息
subject = '这个是邮件主题'
content = '这是使用python smtplib及email模块发送的邮件'
msg = MIMEText(content)
# print(msg, type(msg)) # This is test mail <class 'email.mime.text.MIMEText'>
# msg['Subject']是发送邮件的主题
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = receivers[0]
# 发送邮件时qq邮箱,对应qq邮箱服务器域名时smtp.qq.com 对应端口时465
with smtplib.SMTP_SSL(host='smtp.qq.com', port=465) as server:
# 登录发送者的邮箱
server.login(sender, password)
# 开始发送邮件
server.sendmail(sender, receivers, msg.as_string())
print("Successfully sent email")
'''
上面发送邮件部分也可以写成:
server = smtplib.SMTP_SSL(host='smtp.qq.com', port=465)
server.login(sender, password)
server.sendmail(sender, receivers, msg.as_string())
server.quit()
'''
if __name__ == '__main__':
send_text_info()
2.4 发送邮件添加附件
# 发送文本和附件
# reference: https://blog.csdn.net/weixin_46211269/article/details/121243675
def send_text_and_file():
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
def send_email(msg_from, passwd, msg_to, text_content, file_path=None):
# 发送的消息内容分多个部分,MIMEMultipart类可以放任何内容
msg = MIMEMultipart()
subject = 'python 实现发送文本和附件邮件' # 主题
text = MIMEText(text_content)
# 把要发送的消息添加到msg中
msg.attach(text)
if os.path.exists(file_path):
docFile = file_path
# 读取文本和图片文件都可以正常发送
docApart = MIMEApplication(open(docFile, 'rb').read())
# filename 附件的名字,这个可以重新命名,不重新指定发送附件的名可能就是文件的路径名了
filename = os.path.split(file_path)[-1]
docApart.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(docApart)
print('发送附件!')
msg['subject'] = subject
msg['From'] = msg_from
msg['To'] = msg_to
try:
server = smtplib.SMTP_SSL(host='smtp.qq.com', port=465)
server.login(msg_from, passwd)
server.sendmail(msg_from, msg_to, msg.as_string())
print('发送成功')
except smtplib.SMTPException as e:
print('发送失败')
finally:
server.quit()
msg_from = '931762054@qq.com' # 发送者邮箱
passwd = 'xnsgcuuavelrbbdj' # 发送者邮箱的授权码
msg_to = 'shliang0603@gmail.com' # 接收者邮箱
msg_to = '931762054@qq.com'
text_content = 'This is a test demo!'
# 发送文件和图片附件都是可以的!
# file_path = 'read.md'
file_path = 'imgs/email1.png'
send_email(msg_from, passwd, msg_to, text_content, file_path)
if __name__ == '__main__':
send_text_and_file()
2.5 发送HTML格式的邮件
# 发送html本文,同时发送两个附件
# reference:https://blog.csdn.net/MATLAB_matlab/article/details/106240424
def send_html_file():
import os
import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
def send_email(msg_from, passwd, msg_to, text_content, *args):
# 发送的消息内容分多个部分,MIMEMultipart类可以放任何内容
msg = MIMEMultipart()
subject = 'python 实现发送文本和附件邮件' # 主题
text = MIMEText(text_content)
# 把要发送的消息添加到msg中
msg.attach(text)
# 添加附件
def add_file(file_path):
if os.path.exists(file_path):
docFile = file_path
docApart = MIMEApplication(open(docFile, 'rb').read())
# filename 附件的名字,这个可以重新命名,不重新指定发送附件的名可能就是文件的路径名了
filename = os.path.split(file_path)[-1]
docApart.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(docApart)
print('发送附件!')
# 添加多个附件
for file in args:
add_file(file)
now_time = datetime.datetime.now()
year = now_time.year
month = now_time.month
day = now_time.day
mytime = str(year) + " 年 " + str(month) + " 月 " + str(day) + " 日 "
fayanren="爱因斯坦"
zhuchiren="牛顿"
#构造HTML
content = '''
<html>
<body>
<h1 align="center">这个是标题,xxxx通知</h1>
<p><strong>您好:</strong></p>
<blockquote><p><strong>以下内容是本次会议的纪要,请查收!</strong></p></blockquote>
<blockquote><p><strong>发言人:{fayanren}</strong></p></blockquote>
<blockquote><p><strong>主持人:{zhuchiren}</strong></p></blockquote>
<p align="right">{mytime}</p>
<body>
<html>
'''.format(fayanren=fayanren, zhuchiren=zhuchiren, mytime=mytime)
msg.attach(MIMEText(_text=content, _subtype='html', _charset='utf-8'))
msg['subject'] = subject
msg['From'] = msg_from
msg['To'] = msg_to
try:
server = smtplib.SMTP_SSL(host='smtp.qq.com', port=465)
server.login(msg_from, passwd)
server.sendmail(msg_from, msg_to, msg.as_string())
print('发送成功')
except smtplib.SMTPException as e:
print('发送失败')
finally:
server.quit()
msg_from = '931762054@qq.com' # 发送者邮箱
passwd = 'xnsgcuuavelrbbdj' # 发送者邮箱的授权码
msg_to = 'shliang0603@gmail.com' # 接收者邮箱
msg_to = '931762054@qq.com'
text_content = 'This is a test demo!'
# 发送文件和图片附件都是可以的!
file_path1 = 'read.md'
file_path2 = 'imgs/email1.png'
send_email(msg_from, passwd, msg_to, text_content, file_path1, file_path2)
if __name__ == '__main__':
send_html_file()
参考:geek-docs.com/python/pyth… 参考:cloud.tencent.com/developer/a… 参考:www.cnblogs.com/lovealways/… 参考:blog.csdn.net/MATLAB_matl… 参考:blog.csdn.net/weixin_4621…