- Python内置了对 SMTP 的支持,可以发送纯文本、富文本、HTML 等格式的邮件
- 邮箱需要开启 SMTP 服务
- 需要账号、授权码和服务器地址
- smtp 服务器端口,仅能使用25、465和587
- 25端口(明文传输)
- 465端口(SSL 加密)
- 587端口(STARTTLS 加密)
- 参考:https://www.yuque.com/fcant/python/tw3mdy#fySCx
一 smtplib
- SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。
- Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。
简单使用
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" #口令
sender = '1574188782@qq.com'
receivers = ['zhengxianyi@touch-spring.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
message['From'] = Header("菜鸟教程", 'utf-8')
message['To'] = Header("测试", 'utf-8')
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(sender, receivers, message.as_string())
print ("邮件发送成功")
except smtplib.SMTPException:
print ("Error: 无法发送邮件")
封装成工具类
utils/SendEmail.py
"""
邮件发送工具
Python对SMTP支持有smtplib和email两个模块:
1. email负责构造邮件
2. smtplib负责发送邮件。
"""
import smtplib
import ssl
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import attach as attach
from loguru import logger
from utils.ReadConfig import ReadConfig
class SendMail:
def __init__(self):
"""
初始化smtp服务器连接
smtp 服务器端口,仅能使用25、465和587
25端口(明文传输)465端口(SSL 加密) 587端口(STARTTLS 加密)
"""
self.cf = ReadConfig()
# qq邮箱服务器地址
self.mail_host = self.cf.get_email('mail_host')
# 端口
self.mail_port = self.cf.get_email('mail_port')
# 用户名
self.mail_user = self.cf.get_email('mail_user')
# 密码(部分邮箱为授权码)
self.mail_pass = self.cf.get_email('mail_pass')
self.mail_sender = self.cf.get_email('mail_sender')
# 根据不同的端口,用不同的方式连接
if self.mail_port == "587":
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
self.smtpObj = smtplib.SMTP(self.mail_host, self.mail_port)
self.smtpObj.ehlo()
self.smtpObj.starttls(context=ctx)
elif self.mail_port == "25":
self.smtpObj = smtplib.SMTP(self.mail_host, self.mail_port)
elif self.mail_port == "465":
self.smtpObj = smtplib.SMTP_SSL(self.mail_host, self.mail_port)
# 连接
self.smtpObj.connect(self.mail_host, self.mail_port)
# 登录
self.smtpObj.login(self.mail_user, self.mail_pass)
def send_text_mail(self, subject, content, receivers):
"""
发送文本邮件
:param subject: 邮件主题
:param message: 邮件内容
:param receivers: 邮件接受者
:return:
"""
# 邮件内容
message = MIMEText(content, 'plain', 'utf-8')
# 邮件主题
message['Subject'] = Header(subject, 'UTF-8')
# 发送方信息
message['From'] = Header(self.mail_sender, 'utf-8')
message['To'] = ','.join(receivers)
try:
# 发送
self.smtpObj.sendmail(self.mail_sender, receivers, message.as_string())
logger.info("mail has been send successfully. send to {} ".format(receivers))
except smtplib.SMTPException as e:
logger.error('error', e)
def send_html_mail(self,subject, content, receivers):
"""
发送HTML格式邮件
:param subject: 邮件主题
:param message: 邮件内容
:param receivers: 邮件接受者
:return:
"""
# 邮件内容
message = MIMEText(content, 'html', 'utf-8')
# 邮件主题
message['Subject'] = Header(subject, 'UTF-8')
# 发送方信息
message['From'] = Header(self.mail_sender, 'utf-8')
message['To'] = ','.join(receivers)
try:
# 发送
self.smtpObj.sendmail(self.mail_sender, receivers, message.as_string())
logger.info("mail has been send successfully. send to {} ".format(receivers))
except smtplib.SMTPException as e:
logger.error('error', e)
def send_appendix_mail(self,subject, content, receivers):
"""
发送带附件的邮件
"""
# 创建一个带附件的实例
message = MIMEMultipart()
message['From'] = Header(self.mail_sender, 'utf-8')
message['To'] = ','.join(receivers)
# 邮件主题
message['Subject'] = Header(subject, 'UTF-8')
# 邮件正文内容
message.attach(MIMEText(content, 'plain', 'utf-8'))
# 构造附件,传送当前目录下的 extract.py
att = MIMEText(open('extract.py','rb').read(),'base64', 'utf-8')
# 这里的filename可以任意写,写什么名字,邮件中显示什么名字
att["Content-Disposition"] = 'attachment; filename="extract.py"'
message.attach(att)
try:
# 发送
self.smtpObj.sendmail(self.mail_sender, receivers, message.as_string())
logger.info("mail has been send successfully. send to {} ".format(receivers))
except smtplib.SMTPException as e:
logger.error('error', e)
def exit(self):
# 关闭会话
self.smtpObj.quit()
以上封装了发送不同格式邮件方法,邮箱配置是从ReadConfig工具类中读取的
utils/ReadConfig.py
import configparser
import os
class ReadConfig:
"""读取配置文件类"""
def __init__(self,filepath=None):
if filepath:
configpath =filepath
else:
root_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
configpath = os.path.join(root_dir, 'config.ini')
self.cf = configparser.ConfigParser()
self.cf.read(configpath, encoding="utf-8")
def get_email(self, param):
return self.cf.get('Email', param)
config.ini
[Email]
mail_host = smtp.qq.com
mail_port = 465
mail_user = xx@qq.com
mail_sender = xx@qq.com
mail_pass = 授权码
调用上面邮件工具类
if __name__ == '__main__':
mail = SendMail()
subject = "邮件工具类测试"
message = "这是一个test"
receivers = ['zhengxianyi@touch-spring.com']
mail.send_appendix_mail(subject, message, receivers)
- 传递的收件人格式应该是list类型
二 yagmail
yagmail 只需要几行代码,就能实现发送邮件的功能,相比 smtplib,yagmail 实现发送邮件的方式更加简洁优雅
安装
pip3 install yagmail
下载过程中可能会出现错误,解决办法:https://blog.csdn.net/zhengshengnan123/article/details/89151094
简单使用
import yagmail
yag_server = yagmail.SMTP(user='1574188782@qq.com',password='授权码', host='smtp.qq.com')
# 发送对象列表
email_to = ['zhengxianyi@touch-spring.com', ]
email_title = '测试报告'
email_content = "这是测试报告的具体内容"
# 发送邮件
yag_server.send(email_to, email_title, email_content)
封装成工具类
import yagmail
from loguru import logger
from utils.ReadConfig import ReadConfig
class SendMail:
def __init__(self):
# 读取配置文件
self.cf = ReadConfig()
# 邮箱服务器地址
self.mail_host = self.cf.get_email('mail_host')
# 端口
self.mail_port = self.cf.get_email('mail_port')
# 用户名
self.mail_user = self.cf.get_email('mail_user')
# 密码(部分邮箱为授权码)
self.mail_pass = self.cf.get_email('mail_pass')
self.mail_sender = self.cf.get_email('mail_sender')
def send_mail(self, subject, content, receivers):
yag_server = yagmail.SMTP(user=self.mail_user, password=self.mail_pass, host=self.mail_host)
# 发送对象列表
email_to = ','.join(receivers)
# 发送邮件
try:
yag_server.send(email_to, subject, content)
logger.info("mail has been send successfully. send to {} ".format(receivers))
except Exception as e :
logger.error('error', e)
只有yagmail.SMTP
,没有yagmail.SMTP_SSL
,yagmail.SMTP
支持25、465、587端口
调用
if __name__ == '__main__':
mail = SendMail()
# 发送对象列表
receivers = ['zhengxianyi@touch-spring.com', ]
subject = '测试报告'
content = "这是测试报告的具体内容"
# 发送邮件
mail.send_mail(subject, content, receivers)