1. Python内置了对 SMTP 的支持,可以发送纯文本、富文本、HTML 等格式的邮件
  2. 邮箱需要开启 SMTP 服务
  3. 需要账号、授权码和服务器地址
  4. smtp 服务器端口,仅能使用25、465和587
    1. 25端口(明文传输)
    2. 465端口(SSL 加密)
    3. 587端口(STARTTLS 加密)
  5. 参考:https://www.yuque.com/fcant/python/tw3mdy#fySCx

一 smtplib

  1. SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件。
  2. Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。

简单使用

  1. import smtplib
  2. from email.mime.text import MIMEText
  3. from email.header import Header
  4. # 第三方 SMTP 服务
  5. mail_host="smtp.XXX.com" #设置服务器
  6. mail_user="XXXX" #用户名
  7. mail_pass="XXXXXX" #口令
  8. sender = '1574188782@qq.com'
  9. receivers = ['zhengxianyi@touch-spring.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
  10. message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
  11. message['From'] = Header("菜鸟教程", 'utf-8')
  12. message['To'] = Header("测试", 'utf-8')
  13. subject = 'Python SMTP 邮件测试'
  14. message['Subject'] = Header(subject, 'utf-8')
  15. try:
  16. smtpObj = smtplib.SMTP()
  17. smtpObj.connect(mail_host, 25) # 25 为 SMTP 端口号
  18. smtpObj.login(mail_user,mail_pass)
  19. smtpObj.sendmail(sender, receivers, message.as_string())
  20. print ("邮件发送成功")
  21. except smtplib.SMTPException:
  22. print ("Error: 无法发送邮件")

封装成工具类

utils/SendEmail.py

  1. """
  2. 邮件发送工具
  3. Python对SMTP支持有smtplib和email两个模块:
  4. 1. email负责构造邮件
  5. 2. smtplib负责发送邮件。
  6. """
  7. import smtplib
  8. import ssl
  9. from email.header import Header
  10. from email.mime.multipart import MIMEMultipart
  11. from email.mime.text import MIMEText
  12. import attach as attach
  13. from loguru import logger
  14. from utils.ReadConfig import ReadConfig
  15. class SendMail:
  16. def __init__(self):
  17. """
  18. 初始化smtp服务器连接
  19. smtp 服务器端口,仅能使用25、465和587
  20. 25端口(明文传输)465端口(SSL 加密) 587端口(STARTTLS 加密)
  21. """
  22. self.cf = ReadConfig()
  23. # qq邮箱服务器地址
  24. self.mail_host = self.cf.get_email('mail_host')
  25. # 端口
  26. self.mail_port = self.cf.get_email('mail_port')
  27. # 用户名
  28. self.mail_user = self.cf.get_email('mail_user')
  29. # 密码(部分邮箱为授权码)
  30. self.mail_pass = self.cf.get_email('mail_pass')
  31. self.mail_sender = self.cf.get_email('mail_sender')
  32. # 根据不同的端口,用不同的方式连接
  33. if self.mail_port == "587":
  34. ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
  35. self.smtpObj = smtplib.SMTP(self.mail_host, self.mail_port)
  36. self.smtpObj.ehlo()
  37. self.smtpObj.starttls(context=ctx)
  38. elif self.mail_port == "25":
  39. self.smtpObj = smtplib.SMTP(self.mail_host, self.mail_port)
  40. elif self.mail_port == "465":
  41. self.smtpObj = smtplib.SMTP_SSL(self.mail_host, self.mail_port)
  42. # 连接
  43. self.smtpObj.connect(self.mail_host, self.mail_port)
  44. # 登录
  45. self.smtpObj.login(self.mail_user, self.mail_pass)
  46. def send_text_mail(self, subject, content, receivers):
  47. """
  48. 发送文本邮件
  49. :param subject: 邮件主题
  50. :param message: 邮件内容
  51. :param receivers: 邮件接受者
  52. :return:
  53. """
  54. # 邮件内容
  55. message = MIMEText(content, 'plain', 'utf-8')
  56. # 邮件主题
  57. message['Subject'] = Header(subject, 'UTF-8')
  58. # 发送方信息
  59. message['From'] = Header(self.mail_sender, 'utf-8')
  60. message['To'] = ','.join(receivers)
  61. try:
  62. # 发送
  63. self.smtpObj.sendmail(self.mail_sender, receivers, message.as_string())
  64. logger.info("mail has been send successfully. send to {} ".format(receivers))
  65. except smtplib.SMTPException as e:
  66. logger.error('error', e)
  67. def send_html_mail(self,subject, content, receivers):
  68. """
  69. 发送HTML格式邮件
  70. :param subject: 邮件主题
  71. :param message: 邮件内容
  72. :param receivers: 邮件接受者
  73. :return:
  74. """
  75. # 邮件内容
  76. message = MIMEText(content, 'html', 'utf-8')
  77. # 邮件主题
  78. message['Subject'] = Header(subject, 'UTF-8')
  79. # 发送方信息
  80. message['From'] = Header(self.mail_sender, 'utf-8')
  81. message['To'] = ','.join(receivers)
  82. try:
  83. # 发送
  84. self.smtpObj.sendmail(self.mail_sender, receivers, message.as_string())
  85. logger.info("mail has been send successfully. send to {} ".format(receivers))
  86. except smtplib.SMTPException as e:
  87. logger.error('error', e)
  88. def send_appendix_mail(self,subject, content, receivers):
  89. """
  90. 发送带附件的邮件
  91. """
  92. # 创建一个带附件的实例
  93. message = MIMEMultipart()
  94. message['From'] = Header(self.mail_sender, 'utf-8')
  95. message['To'] = ','.join(receivers)
  96. # 邮件主题
  97. message['Subject'] = Header(subject, 'UTF-8')
  98. # 邮件正文内容
  99. message.attach(MIMEText(content, 'plain', 'utf-8'))
  100. # 构造附件,传送当前目录下的 extract.py
  101. att = MIMEText(open('extract.py','rb').read(),'base64', 'utf-8')
  102. # 这里的filename可以任意写,写什么名字,邮件中显示什么名字
  103. att["Content-Disposition"] = 'attachment; filename="extract.py"'
  104. message.attach(att)
  105. try:
  106. # 发送
  107. self.smtpObj.sendmail(self.mail_sender, receivers, message.as_string())
  108. logger.info("mail has been send successfully. send to {} ".format(receivers))
  109. except smtplib.SMTPException as e:
  110. logger.error('error', e)
  111. def exit(self):
  112. # 关闭会话
  113. self.smtpObj.quit()

以上封装了发送不同格式邮件方法,邮箱配置是从ReadConfig工具类中读取的
utils/ReadConfig.py

  1. import configparser
  2. import os
  3. class ReadConfig:
  4. """读取配置文件类"""
  5. def __init__(self,filepath=None):
  6. if filepath:
  7. configpath =filepath
  8. else:
  9. root_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
  10. configpath = os.path.join(root_dir, 'config.ini')
  11. self.cf = configparser.ConfigParser()
  12. self.cf.read(configpath, encoding="utf-8")
  13. def get_email(self, param):
  14. return self.cf.get('Email', param)

config.ini

  1. [Email]
  2. mail_host = smtp.qq.com
  3. mail_port = 465
  4. mail_user = xx@qq.com
  5. mail_sender = xx@qq.com
  6. mail_pass = 授权码

调用上面邮件工具类

  1. if __name__ == '__main__':
  2. mail = SendMail()
  3. subject = "邮件工具类测试"
  4. message = "这是一个test"
  5. receivers = ['zhengxianyi@touch-spring.com']
  6. mail.send_appendix_mail(subject, message, receivers)
  • 传递的收件人格式应该是list类型

image.png

二 yagmail

yagmail 只需要几行代码,就能实现发送邮件的功能,相比 smtplib,yagmail 实现发送邮件的方式更加简洁优雅

安装

  1. pip3 install yagmail

下载过程中可能会出现错误,解决办法:https://blog.csdn.net/zhengshengnan123/article/details/89151094

简单使用

  1. import yagmail
  2. yag_server = yagmail.SMTP(user='1574188782@qq.com',password='授权码', host='smtp.qq.com')
  3. # 发送对象列表
  4. email_to = ['zhengxianyi@touch-spring.com', ]
  5. email_title = '测试报告'
  6. email_content = "这是测试报告的具体内容"
  7. # 发送邮件
  8. yag_server.send(email_to, email_title, email_content)

封装成工具类

  1. import yagmail
  2. from loguru import logger
  3. from utils.ReadConfig import ReadConfig
  4. class SendMail:
  5. def __init__(self):
  6. # 读取配置文件
  7. self.cf = ReadConfig()
  8. # 邮箱服务器地址
  9. self.mail_host = self.cf.get_email('mail_host')
  10. # 端口
  11. self.mail_port = self.cf.get_email('mail_port')
  12. # 用户名
  13. self.mail_user = self.cf.get_email('mail_user')
  14. # 密码(部分邮箱为授权码)
  15. self.mail_pass = self.cf.get_email('mail_pass')
  16. self.mail_sender = self.cf.get_email('mail_sender')
  17. def send_mail(self, subject, content, receivers):
  18. yag_server = yagmail.SMTP(user=self.mail_user, password=self.mail_pass, host=self.mail_host)
  19. # 发送对象列表
  20. email_to = ','.join(receivers)
  21. # 发送邮件
  22. try:
  23. yag_server.send(email_to, subject, content)
  24. logger.info("mail has been send successfully. send to {} ".format(receivers))
  25. except Exception as e :
  26. logger.error('error', e)

只有yagmail.SMTP,没有yagmail.SMTP_SSLyagmail.SMTP支持25、465、587端口


调用

  1. if __name__ == '__main__':
  2. mail = SendMail()
  3. # 发送对象列表
  4. receivers = ['zhengxianyi@touch-spring.com', ]
  5. subject = '测试报告'
  6. content = "这是测试报告的具体内容"
  7. # 发送邮件
  8. mail.send_mail(subject, content, receivers)