Python邮件接收

来自CloudWiki
跳转至: 导航搜索

邮件是互联网上应用非常广泛的服务,几乎所有的编程语言都支持发送和接收电子邮件,使用Python发送邮件和接收邮件也是非常简单易学的。现在几乎每个人的手机上都自带邮件客户端,多数邮箱都支持短信提醒.

因此,在运维场景中将程序报错的信息发送到相应人员的邮箱可以及时感知程序的报错,尽早处理从而避免更多的损失。当然,使用程序发送邮件还有许多应用场景,如网站的密码重置等,在此不再一一列举。

邮箱设置

win10系统下网易邮箱怎样设置SMTP服务:http://www.xitongcheng.com/jiaocheng/win10_article_30498.html

Python21051005.png

邮件发送和接受的原理

关于如何写代码发送邮件,我们应首先想到发送邮件使用什么协议。目前发送邮件的协议是SMTP(Simple Mail Transfer Protocol,简单邮件传输协议),是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。我们编写代码,实际上就是将待发送的消息使用SMTP协议的格式进行封装,再提交SMTP服务器进行发送的过程。

秒懂百科:https://baike.baidu.com/item/SMTP/175887?fr=aladdin

Auto1-1.png

SMTP

SMTP 的全称是“Simple Mail Transfer Protocol”,即简单邮件传输协议。它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。SMTP 服务器就是遵循 SMTP 协议的发送邮件服务器。

POP3

POP3是Post Office Protocol 3的简称,即邮局协议的第3个版本,它规定怎样将个人计算机连接到Internet的邮件服务器和下载电子邮件的电子协议。它是因特网电子邮件的第一个离线协议标准,POP3允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,用来接收电子邮件的。(与IMAP有什么区别?)

IMAP

IMAP全称是Internet Mail Access Protocol,即交互式邮件存取协议,它是跟POP3类似邮件访问标准协议之一。不同的是,开启了IMAP后,您在电子邮件客户端收取的邮件仍然保留在服务器上,同时在客户端上的操作都会反馈到服务器上,如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作。所以无论从浏览器登录邮箱或者客户端软件登录邮箱,看到的邮件以及状态都是一致的。


接收邮件

连接POP3服务器

# -*- encoding:utf-8 -*-
import poplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr

# 输入邮件地址, 口令和POP3服务器地址
email = "maxin5452@qq.com"
password = "aaaaaaaaaaa"
pop3_server = "pop.qq.com"


# 连接到POP3服务器,如果开启ssl请使用poplib.POP3_SSL
server = poplib.POP3_SSL(pop3_server)
# 可以打开或关闭调试信息
# server.set_debuglevel(1)
# 可选:打印POP3服务器的欢迎文字
print(server.getwelcome().decode("utf-8"))

# 身份认证:
server.user(email)
server.pass_(password)

输出邮箱总体信息

# stat()返回邮件数量和占用空间:
print("邮件数量: %s个. 大小: %.2fMB" % (server.stat()[0], server.stat()[1] / 1024 / 1024))


# list()返回所有邮件的编号:
resp, mails, octets = server.list()
# 可以查看返回的列表类似[b'1 82923', b'2 2184', ...]

获取特定邮件信息

# 获取最新一封邮件, 注意索引号从1开始,最新的邮件索引即为邮件的总个数
index = len(mails)
resp, lines, octets = server.retr(index)

# lines存储了邮件的原始文本的每一行可以获得整个邮件的原始文本
msg_content = b"\r\n".join(lines).decode("utf-8")

解析特定邮件信息

# 稍后解析出邮件
msg = Parser().parsestr(msg_content)


def decode_str(s):
    value, charset = decode_header(s)[0]
    if charset:
        value = value.decode(charset)
    return value


print("解析获取到的邮件内容如下:\n----------begin------------")
# 打印发件人信息
print(
    f"{ decode_str(parseaddr(msg.get('From',''))[0])}<{decode_str(parseaddr( msg.get('From',''))[1])}>"
)
# 打印收件人信息
print(
    f"{ decode_str(parseaddr(msg.get('To',''))[0])}<{decode_str(parseaddr( msg.get('To',''))[1])}>"
)
# 打印主题信息
print(decode_str(msg["Subject"]))
# 打印第一条正文信息
part0 = msg.get_payload()[0]
content = part0.get_payload(decode=True)
print(content.decode(part0.get_content_charset()))
print("----------end------------")

删除特定邮件

# 可以根据邮件索引号直接从服务器删除邮件
# server.dele(index)
# 关闭连接:
server.quit()

完整代码

# -*- encoding:utf-8 -*-
import poplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr

# 输入邮件地址, 口令和POP3服务器地址
email = "maxin5452@163.com"
password = "******"
pop3_server = "pop.163.com"


# 连接到POP3服务器,如果开启ssl请使用poplib.POP3_SSL
server = poplib.POP3_SSL(pop3_server)
# 可以打开或关闭调试信息
# server.set_debuglevel(1)
# 可选:打印POP3服务器的欢迎文字
print(server.getwelcome().decode("utf-8"))

# 身份认证:
server.user(email)
server.pass_(password)

# stat()返回邮件数量和占用空间:
print("邮件数量: %s个. 大小: %.2fMB" % (server.stat()[0], server.stat()[1] / 1024 / 1024))


# list()返回所有邮件的编号:
resp, mails, octets = server.list()
# 可以查看返回的列表类似[b'1 82923', b'2 2184', ...]


# 获取最新一封邮件, 注意索引号从1开始,最新的邮件索引即为邮件的总个数
index = len(mails)
resp, lines, octets = server.retr(index)

# lines存储了邮件的原始文本的每一行可以获得整个邮件的原始文本
msg_content = b"\r\n".join(lines).decode("utf-8")
# 稍后解析出邮件
msg = Parser().parsestr(msg_content)


def decode_str(s):
    value, charset = decode_header(s)[0]
    if charset:
        value = value.decode(charset)
    return value


print("解析获取到的邮件内容如下:\n----------begin------------")
# 打印发件人信息
print(
    f"{ decode_str(parseaddr(msg.get('From',''))[0])}<{decode_str(parseaddr( msg.get('From',''))[1])}>"
)
# 打印收件人信息
print(
    f"{ decode_str(parseaddr(msg.get('To',''))[0])}<{decode_str(parseaddr( msg.get('To',''))[1])}>"
)
# 打印主题信息
print(decode_str(msg["Subject"]))
# 打印第一条正文信息
part0 = msg.get_payload()[0]
#content = part0.get_payload(decode=True)
#print(content.decode(part0.get_content_charset()))
print("----------end------------")

# 可以根据邮件索引号直接从服务器删除邮件
# server.dele(index)
# 关闭连接:
server.quit()


改进版:遍历所有邮件

# -*- encoding:utf-8 -*-
import poplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr

# 输入邮件地址, 口令和POP3服务器地址
email = "maxin5452@qq.com"
password = "************"
pop3_server = "pop.qq.com"

def decode_str(s):
    value, charset = decode_header(s)[0]
    if charset:
        value = value.decode(charset)
    return value


# 连接到POP3服务器,如果开启ssl请使用poplib.POP3_SSL
server = poplib.POP3_SSL(pop3_server)
# 可以打开或关闭调试信息
# server.set_debuglevel(1)
# 可选:打印POP3服务器的欢迎文字
print(server.getwelcome().decode("utf-8"))

# 身份认证:
server.user(email)
server.pass_(password)

# stat()返回邮件数量和占用空间:
print("邮件数量: %s个. 大小: %.2fMB" % (server.stat()[0], server.stat()[1] / 1024 / 1024))


# list()返回所有邮件的编号:
resp, mails, octets = server.list()
# 可以查看返回的列表类似[b'1 82923', b'2 2184', ...]


# 获取最新一封邮件, 注意索引号从1开始,最新的邮件索引即为邮件的总个数
i = len(mails)

for index in range(i,0,-1): 
    resp, lines, octets = server.retr(index)   #获取特定邮件

    # lines存储了邮件的原始文本的每一行可以获得整个邮件的原始文本
    msg_content = b"\r\n".join(lines).decode("utf-8")
    # 稍后解析出邮件
    msg = Parser().parsestr(msg_content)

    print("解析获取到的邮件内容如下:\n----------begin------------")
    # 打印发件人信息
    print(
        f"{ decode_str(parseaddr(msg.get('From',''))[0])}<{decode_str(parseaddr( msg.get('From',''))[1])}>"
    )
    # 打印收件人信息
    print(
        f"{ decode_str(parseaddr(msg.get('To',''))[0])}<{decode_str(parseaddr( msg.get('To',''))[1])}>"
    )
    # 打印主题信息
    print(decode_str(msg["Subject"]))
    # 打印第一条正文信息
    #part0 = msg.get_payload()[0]
    #content = part0.get_payload(decode=True)
    #print(content.decode(part0.get_content_charset()))
    print("----------end------------")

# 可以根据邮件索引号直接从服务器删除邮件
# server.dele(index)
# 关闭连接:
server.quit()