Python使用POP3和SMTP协议收发邮件

时光总嘲笑我的痴心妄想 提交于 2021-01-05 16:47:47

先来了解一下收/发邮件有哪些协议:

*   **SMTP协议**
    SMTP(Simple Mail Transfer Protocol),即简单邮件传输协议。相当于中转站,将邮件发送到客户端。
*   **POP3协议**
    POP3(Post Office Protocol 3),即邮局协议的第3个版本,是电子邮件的第一个离线协议标准。该协议把邮件下载到本地计算机,不与服务器同步,缺点是更易丢失邮件或多次下载相同的邮件。
*   **IMAP协议**
    IMAP(Internet Mail Access Protocol),即交互式邮件存取协议。该协议连接远程邮箱直接操作,与服务器内容同步。
*   **Exchange服务**
    Exchange服务是一个设计完备的邮件服务器产品,提供了通常所需要的全部邮件服务功能。除了常规SMTP/POP协议服务之外,它还支持IMAP4 、LDAP和NNTP协议。

>本期推送整理了初学者可能会用到的Python资料,含有书籍/视频/在线文档和编辑器/源
代码,关于`Python`的安装qun:850973621


* * *

## SMTP发送邮件

Python对SMTP支持有 `smtplib` 和 `email` 两个模块,`email` 负责构造邮件,`smtplib` 负责发送邮件。

#### 构造邮件

构造最简单的纯文本邮件,如下:

```
from email.mime.text import MIMEText

msg = MIMEText('hello, send by Python...', 'plain', 'utf-8')
复制代码
```

注意到构造 `MIMEText` 对象时,第一个参数就是邮件正文,第二个参数是MIME的subtype,传入 `'plain'` 表示纯文本,最终的MIME就是 `'text/plain'`,最后一定要用 `utf-8` 编码保证多语言兼容性。

#### 发送邮件

```
import smtplib

# 输入Email地址和口令:
from_addr = 'test_from_addr@qq.com'
password = 'Password'
# 输入收件人地址:
to_addr = 'test_to_addr@qq.com'
# 输入SMTP服务器地址:
smtp_server = 'smtp.qq.com'

server = smtplib.SMTP(smtp_server, 25) # SMTP协议默认端口是25
# server.starttls() # 如果是SSL,则用 587 端口,再加上这句代码就行了
server.set_debuglevel(1)    # 打印出和SMTP服务器交互的所有信息
server.login(from_addr, password)   # 登录SMTP服务器
server.sendmail(from_addr, [to_addr], msg.as_string())    # 发邮件
server.quit()
复制代码
```

`sendmail()` 方法就是发邮件,由于可以一次发给多个人,所以传入一个 `list`,邮件正文是一个 `str`,`as_string()` 把MIMEText对象变成 `str`。

**注意:** QQ邮件等需要手动开通 `SMTP服务` , 邮箱设置 => 账号 => POP3/SMTP服务,如下图:

[图片上传失败...(image-7e7774-1609832793635)]

<figcaption></figcaption>

[图片上传失败...(image-c66a19-1609832793635)]

<figcaption></figcaption>

此时,我们就可以收到邮件了,如下:

[图片上传失败...(image-bd0168-1609832793635)]

<figcaption></figcaption>

#### 添加邮件标题、收/发件人

邮件主题、显示发件人、收件人等信息并不是通过SMTP协议发送的,而是包含在 `MIMEText` 对象中,如下:

```
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr

import smtplib

def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

from_addr = 'test_from_addr@qq.com'
password = 'Password'
to_addr = 'test_to_addr@qq.com'
smtp_server = smtp.qq.com

msg = MIMEText('hello, send by Python...', 'plain', 'utf-8')
msg['From'] = _format_addr('发件人昵称 <%s>' % from_addr)
msg['To'] = _format_addr('收件人昵称 <%s>' % to_addr)
msg['Subject'] = Header('这是个有主题的邮件', 'utf-8').encode()

server = smtplib.SMTP(smtp_server, 25)
server.set_debuglevel(1)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string())
server.quit()
复制代码
```

收到的邮件,如下:

[图片上传失败...(image-f7196d-1609832793635)]

<figcaption></figcaption>

收件人并不是我们设置的 “收件人昵称”,是因为很多邮件服务商在显示邮件时,会把收件人名字自动替换为用户注册的名字,这无伤大雅。

#### 添加抄送,暗送

```
# ccto_list 抄送
# bccto_list 暗送

msg['from'] = user
msg['to'] = ','.join(to_list)   #注意,不是分号
msg['cc'] = ','.join(ccto_list)
msg['subject'] = subject
server.sendmail(sender,to_list+ccto_list+bccto_list, str(msg))
复制代码
```

#### 发送HTML邮件

要发送HTML邮件很简单,在构造 `MIMEText` 对象时,把HTML字符串传进去,再把第二个参数由 `plain` 变为 `html` ,如下:

```
msg = MIMEText('<html><body><h1>Hello</h1>' +
    '<p>send by <a href="http://blog.pangao.vip">PanGao’s blog</a>...</p>' +
    '</body></html>

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!