使用PYTHON发送电子邮件

时间:2021-12-26 22:49:11

1. 需求

使用flask写博客(GWMMS)的时候,遇到用户注册的问题,需要服务器发送一封电子邮件到指定用户邮箱下,用户点击URL后激活对应的账号。

python内置两个模块用以发送邮件: smtplibemail 。email模块主要用以构造邮件;smtplib则用以发送。(本文只讨论发送邮件,接收邮件不做讨论)

2. 构造一封简单纯文本的邮件

2.1 代码实现:

from email.mime.text import MIMEText
msg = MIMEText(‘hello, send by Python…’, ‘plain’, ‘utf-8’)

2.2 解释:
先将MIMEText类从email.mime.text导入创建msg实例对象的时候注意,第一个参数是邮件的内容,第二个参数 plain 表示纯文本,第三个参数为编码方式, utf-8 保证多语言兼容性。

3. 通过SMTP发送邮件

3.1 代码实现:

# Email地址和密码:
from_addr = ‘i@lvhuiyang.cn’
password = ‘example_password’
# 要发送的地址
to_addr = input(‘to_addr@example.com’)
# 输入SMTP服务器地址,比如腾讯邮箱服务器“smtp.qq.com”
smtp_server = input(‘SMTP server: ‘)

import smtplib
server = smtplib.SMTP(smtp_server, 25) # SMTP协议默认端口是25,要看具体服务商(腾讯smtp服务器默认端口587)
server.set_debuglevel(1)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string())
server.quit()

3.2 解释:
set_debuglevel(1) 可以打印出和SMTP服务器交互的所有信息。 login() 方法用来登录SMTP服务器, sendmail() 方法就是发邮件,由于可以一次发给多个人,所以传入一个list,邮件正文是一个str, as_string() 把MIMEText对象变成str。

4. 问题?

发现如下问题:

  • 邮件没有主题;
  • 收件人的名字没有显示为友好的名字,比如Mr Green green@example.com
  • 收到了邮件,却提示不在收件人中。

5. 原因?解决方案

5.1 原因:
邮件主题、如何显示发件人、收件人等信息并不是通过SMTP协议发给MTA,而是包含在发给MTA的文本中的。[注:MTA,报文传送代理]

5.2 解决:
把发送人,收件人,主题等信息包含在MIMEText 发送。

完整的代码:

# -*- coding: utf-8 -*-
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr
from email.utils import formataddr
import smtplib
import os


# Python对SMTP支持有smtplib和email两个模块,email负责构造邮件,smtplib负责发送邮件。
# _format_addr() 函数用来格式化邮件地址
def _format_addr(s):
name, addr = parseaddr(s)
return formataddr((
Header(name, 'utf-8').encode(),
addr.encode('utf-8') if isinstance(addr, unicode) else addr))


# 邮件发送的函数,接收参数分别为 主题, 发件人, 收件人, 内容
# 发件人的密码口令从环境变量中获取
def send_mail(subject, from_addr, to_addr, content):
from_addr = os.getenv('MAIL_USERNAME')
to_addr = os.getenv("MAIL_USERNAME")
password = os.getenv('MAIL_PASSWORD')
msg = MIMEText(content, 'plain', 'utf-8')
msg['Subject'] = Header(u'%s', 'utf-8').encode() % subject
msg['From'] = _format_addr(u'lvhuiyang <%s>' % from_addr)
msg['To'] = _format_addr(u'service of python_smtp <%s>' % to_addr)
smtp_server = 'smtp.qq.com'
smtp_port = 587
server = smtplib.SMTP(smtp_server, smtp_port)
server.starttls()
server.set_debuglevel(1)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string())
server.quit()

6. 发送html邮件

如果我们要发送HTML邮件,而不是普通的纯文本文件怎么办?方法很简单,在构造MIMEText对象时,把HTML字符串传进去,再把第二个参数由plain变为html就可以了:

msg = MIMEText(‘<html><body><h1>Hello</h1>’ +
<p>send by <a href=”http://www.python.org”>Python</a></p>’ +
</body></html>’, ‘html’, ‘utf-8’)

就这么多,其他的比如发送附件暂时没什么需求~

7. 参考

廖雪峰的博客关于email的讲解