SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。
1.SMTP
Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。
以下是国内常见的邮件服务的端口号。
# 协议 服务器 SSL 非 SSL
# SMTP smtp.163.com 465 25
# IMAP imap.163.com 993 143
# POP3 pop.163.com 995 110
# -------------------------------
# SMTP smtp.qq.com 465/587
# IMAP imap.qq.com 993
# POP3 pop.qq.com 995
# -------------------------------
# SMTP smtp.gmail.com 465(SSL)/587(TLS/STARTTLS)
# IMAP imap.gmail.com 993
# POP3 pop.gmail.com 995
# -------------------------------
# 163/qq: password 为授权码
# gmail: password 为邮箱密码
2.实例
使用QQ邮箱发送邮件。首先必须开启qq邮箱的smtp服务。 如何打开POP3/SMTP/IMAP功能? 为了保障用户邮箱的安全,QQ邮箱设置了POP3/SMTP/IMAP的开关。系统缺省设置是“关闭”,在用户需要这些功能时请“开启”。 首先,登录邮箱,进入设置-帐户;

# -*- coding: utf-8 -*-
# @Time : 2022/5/9 18:56
# @File : smtpdemo.py
# @Software : PyCharm
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
my_sender='403357832@qq.com' # 发件人邮箱账号
my_pass = 'erfwftyewertbiab' # 发件人邮箱密码(当时申请smtp给的授权码)
my_user='tester@163.com' # 收件人邮箱账号,我这边发送给自己,可以自己发给自己
def mail():
ret=True
try:
msg=MIMEText('主人,有新域名,快来看看吧!','plain','utf-8')
msg['From']=formataddr(["simoniu",my_sender]) # 括号里的对应发件人邮箱昵称、发件人邮箱账号
msg['To']=formataddr(["bob",my_user]) # 括号里的对应收件人邮箱昵称、收件人邮箱账号
msg['Subject']="邮件主题-测试" # 邮件的主题,也可以说是标题
server=smtplib.SMTP_SSL("smtp.qq.com", 465) # 发件人邮箱中的SMTP服务器,端口是465
server.login(my_sender, my_pass) # 括号中对应的是发件人邮箱账号、邮箱密码
server.sendmail(my_sender,[my_user,],msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
server.quit()# 关闭连接
except Exception as e:# 如果 try 中的语句没有执行,则会执行下面的 ret=False
print(e)
ret=False
return ret
ret=mail()
if ret:
print("邮件发送成功")
else:
print("邮件发送失败")
运行结果:
邮件发送成功
发送附件 如果Email中要加上附件怎么办?带附件的邮件可以看做包含若干部分的邮件:文本和各个附件本身,所以,可以构造一个MIMEMultipart对象代表邮件本身,然后往里面加上一个MIMEText作为邮件正文,再继续往里面加上表示附件的MIMEBase对象即可。
import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr
my_sender='403357832@qq.com' # 发件人邮箱账号
my_pass = 'erfwftyewertbiab' # 发件人邮箱密码(当时申请smtp给的授权码)
my_user='tester@163.com' # 收件人邮箱账号,我这边发送给自己,可以自己发给自己
def mail():
ret = True
try:
# 发送附件必须构造一个MIMEMultipart对象
msg = MIMEMultipart()
msg['From'] = formataddr(["simoniu", my_sender]) # 括号里的对应发件人邮箱昵称、发件人邮箱账号
msg['To'] = formataddr(["bob", my_user]) # 括号里的对应收件人邮箱昵称、收件人邮箱账号
msg['Subject'] = "邮件主题-测试" # 邮件的主题,也可以说是标题
# 邮件正文是MIMEText:
msg.attach(MIMEText('send with file...', 'plain', 'utf-8'))
# 添加附件就是加上一个MIMEBase,从本地读取一个图片:
with open('D:/uploadFiles/test.jpg', 'rb') as f:
# 设置附件的MIME和文件名,这里是png类型:
mime = MIMEBase('image', 'jpg', filename='test.jpg')
# 加上必要的头信息:
mime.add_header('Content-Disposition', 'attachment', filename='test.jpg')
mime.add_header('Content-ID', '<0>')
mime.add_header('X-Attachment-Id', '0')
# 把附件的内容读进来:
mime.set_payload(f.read())
# 用Base64编码:
encoders.encode_base64(mime)
# 添加到MIMEMultipart:
msg.attach(mime)
server = smtplib.SMTP_SSL("smtp.qq.com", 465) # 发件人邮箱中的SMTP服务器,端口是465
server.login(my_sender, my_pass) # 括号中对应的是发件人邮箱账号、邮箱密码
server.sendmail(my_sender, [my_user, ], msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
server.quit() # 关闭连接
except Exception as e: # 如果 try 中的语句没有执行,则会执行下面的 ret=False
print(e)
ret = False
return ret
ret = mail()
if ret:
print("邮件发送成功")
else:
print("邮件发送失败")
发送图片
如果要把一个图片嵌入到邮件正文中怎么做?直接在HTML邮件中链接图片地址行不行?答案是,大部分邮件服务商都会自动屏蔽带有外链的图片,因为不知道这些链接是否指向恶意网站。
要把图片嵌入到邮件正文中,我们只需按照发送附件的方式,先把邮件作为附件添加进去,然后,在HTML中通过引用src="cid:0"就可以把附件作为图片嵌入了。如果有多个图片,给它们依次编号,然后引用不同的cid:x即可。
把上面代码加入MIMEMultipart的MIMEText从plain改为html,然后在适当的位置引用图片:
import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr
my_sender='403357832@qq.com' # 发件人邮箱账号
my_pass = 'erfwftyewertbiab' # 发件人邮箱密码(当时申请smtp给的授权码)
my_user='tester@163.com' # 收件人邮箱账号,我这边发送给自己,可以自己发给自己
def mail():
ret = True
try:
# 发送附件必须构造一个MIMEMultipart对象
msg = MIMEMultipart()
msg['From'] = formataddr(["simoniu", my_sender]) # 括号里的对应发件人邮箱昵称、发件人邮箱账号
msg['To'] = formataddr(["bob", my_user]) # 括号里的对应收件人邮箱昵称、收件人邮箱账号
msg['Subject'] = "邮件主题-测试" # 邮件的主题,也可以说是标题
# 添加附件就是加上一个MIMEBase,从本地读取一个图片:
with open('D:/uploadFiles/test.jpg', 'rb') as f:
# 设置附件的MIME和文件名,这里是png类型:
mime = MIMEBase('image', 'jpg', filename='test.jpg')
# 加上必要的头信息:
mime.add_header('Content-Disposition', 'attachment', filename='test.jpg')
mime.add_header('Content-ID', '<0>')
mime.add_header('X-Attachment-Id', '0')
# 把附件的内容读进来:
mime.set_payload(f.read())
# 用Base64编码:
encoders.encode_base64(mime)
# 添加到MIMEMultipart:
msg.attach(mime)
msg.attach(MIMEText('<html><body><h1>邮件中的图片</h1>' +
'<p><img src="cid:0"></p>' +
'</body></html>', 'html', 'utf-8'))
server = smtplib.SMTP_SSL("smtp.qq.com", 465) # 发件人邮箱中的SMTP服务器,端口是465
server.login(my_sender, my_pass) # 括号中对应的是发件人邮箱账号、邮箱密码
server.sendmail(my_sender, [my_user, ], msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
server.quit() # 关闭连接
except Exception as e: # 如果 try 中的语句没有执行,则会执行下面的 ret=False
print(e)
ret = False
return ret
ret = mail()
if ret:
print("邮件发送成功")
else:
print("邮件发送失败")
小结: 使用Python的smtplib发送邮件十分简单,只要掌握了各种邮件类型的构造方法,正确设置好邮件头,就可以顺利发出。