Skip to content

电子邮件

检查和答复电子邮件会占用大量的时间。当然,你不能只写一个程序来处理所有电子邮件,因为每个消息都需要有自己的回应。但是,一旦知道怎么编写收发电子邮件的程序,就可以自动化大量与电子邮件相关的任务。

例如,也许你有一个电子表格,包含许多客户记录,希望根据他们的年龄和位置信息,向每个客户发送不同格式的邮件。商业软件可能无法做这一点。好在,可以编写自己的程序来发送这些电子邮件,节省了大量复制和粘贴电子邮件的时间。

也可以编程发送电子邮件和短信,即使你远离计算机时,也能通知你。如果要自动化的任务需要执行几个小时,你不希望每过几分钟就回到计算机旁边,检查程序的状态。相反,程序可以在完成时向手机发短信,让你在离开计算机时,能专注于更重要的事情。

在学习课程之前可以理解一下下面三个概念:

  • POP3: Post Office Protocol 3的简称,即邮局协议的第3个版本,它规定怎样将个人计算机连接到 Internet 的邮件服务器和下载电子邮件的电子协议。
  • SMTP: Simple Mail Transfer Protocol,即简单邮件传输协议。
  • IMAP: Internet Mail Access Protocol,即交互式邮件存取协议,它是跟POP3类似邮件访问标准协议之一。

SMTP 发送电子邮件

正如 HTTP 是计算机用来通过因特网发送网页的协议,简单邮件传输协议(SMTP)是用于发送电子邮件的协议。SMTP 规定电子邮件应该如何格式化、加密、在邮件服务器之间传递,以及在你点击发送后,计算机要处理的所有其他细节。但是,你并不需要知道这些技术细节,因为 Python 的 yagmail 模块将它们简化成几个函数。

SMTP 只负责向别人发送电子邮件。另一个协议,名为IMAP,负责取回发送给你的电子邮件

连接到 SMTP 服务器

如果你曾设置了Thunderbird、Outlook 或其他程序,连接到你的电子邮件账户,你可能熟悉配置 SMTP 服务器和端口。这些设置因电子邮件提供商而不同,但在网上搜索“< 你的提供商> SMTP 设置”,应该能找到相应的服务器和端口。

SMTP 服务器的域名通常是电子邮件提供商的域名,前面加上SMTP。例如,Gmail 的 SMTP 服务器是smtp.gmail.com。下面列出了一些常见的电子邮件提供商及其 SMTP 服务器(端口是一个整数值,几乎总是587,该端口由命令加密标准 TLS 使用)。

提供商SMTP 服务器域名
QQ 邮箱smtp.qq.com
126邮箱smtp.126.com
163.comsmtp.163.com
sohu.comsmtp.sohu.com

得到电子邮件提供商的域名和端口信息后,调用 yagmail.SMTP 创建一个 SMTP 对象,传入域名作为一个字符串参数,传入端口作为整数参数。SMTP 对象表示与 SMTP 邮件服务器的连接,它有一些发送电子邮件的方法。例如,下面的调用创建了一个 SMTP 对象,连接到 QQ 邮箱:

python
# 导入库
import yagmail

# 设置服务器:这个是 `qq` 邮箱服务器,直接复制就可以
mail_host = "smtp.qq.com"
# 授权码(请使用自己的邮箱授权码)
mail_pass = "xxxxxx"
# 邮箱地址
sender = '2328074219@qq.com'
# 收件人的邮箱地址,可设置为你的 `QQ` 邮箱或者其他邮箱,可多个
receivers = ['209919481@qq.com']

"""登录 `SMTP` 服务器
user - 邮箱账号
password - 邮箱登录授权码
host - 邮箱 `SMTP` 服务器地址
"""
yag = yagmail.SMTP(user=sender, password=mail_pass, host=mail_host)

在正常情况下链接是没有问题的,如果出现了报错,大概率是账号与密码出问题了。可以核对一下账号与密码是否正确。

构建发送内容

得到 SMTP 对象后,就可以准备发送给服务器的内容了。在 yagmail 中,内容可以是一个列表,也能是一个字符串,为了方便操作,就选择使用列表构建发送内容。在 yagmail 中,发送的内容我们可以直接传递就可以了,不需要自己写格式内容:

python
# 编辑邮件内容
contents = [
    '你好, 这条信息是由 yagmail 发送的!',
    '这里在测试邮件发送!',
    '<a href="https://ke.qq.com/course/2526486">快来上课了</a>',  # 以 HTML 的 超链接 形式发送
    yagmail.inline('logo.png'),  # 邮件内容中内嵌图片
    'logo.png'  # 以附件方式发送,必须当前文件夹下有这个图片
]

发送电子邮件

登录到电子邮件提供商的 SMTP 服务器后,可以调用的sendmail()方法来发送电子邮件。sendmail()方法调用看起来像这样:

python
"""发送邮件
to - 收信邮箱
subject - 邮件主题
contents - 邮件内容
"""
try:
    yag.send(to=receivers, subject='来自yagmail', contents=contents)
    print('发送成功')
except Exception as e:
    print('发送失败', e)

send() 方法需要三个参数。

  • 你的电子邮件地址字符串(电子邮件的“from”地址)。
  • 收件人的电子邮件地址字符串,或多个收件人的字符串列表(作为“to”地址)。
  • 电子邮件正文字符串。

电子邮件正文字符串必须以'Subject: \n'开头,作为电子邮件的主题行。'\n'换行符将主题行与电子邮件的正文分开。

send()的返回值是一个字典。对于电子邮件传送失败的每个收件人,该字典中会有一个键值对。空的字典意味着对所有收件人已成功发送电子邮件。

IMAP 接受电子邮件

正如 SMTP 是用于发送电子邮件的协议,因特网消息访问协议(IMAP)规定了如何与电子邮件服务提供商的服务器通信,取回发送到你的电子邮件地址的电子邮件。

Python 有一个 imbox 模块,这个第三方模块非常简单易用。接来来我们介绍这个模块的使用,完整的文档在:https://github.com/martinrusev/imbox

imbox 模块从 IMAP 服务器下载电子邮件,格式非常简单。很多底层的内容全部给我们封装好了,我们只要直接使用即可。

从终端窗口安装imbox。

pip install imbox

登录与获取邮件列表

Python 中,查找和获取电子邮件是一个多步骤的过程,需要第三方模块 imbox 。作为概述,这里有一个完整的例子,包括登录到 IMAP 服务器,搜索电子邮件,获取它们,然后从中提取电子邮件的文本。

取得 Imbox 对象后,传入用户名(这通常是你的电子邮件地址)和密码字符串就可以实现登录。

python
from datetime import datetime
from imbox import Imbox

# 设置服务器:这个是 `qq` 邮箱服务器,直接复制就可以
mail_host = "smtp.qq.com"
# 刚才我们获取的授权码
mail_pass = "xxxxxxxx"
# 你的邮箱地址
sender = '2328074219@qq.com'

# Imbox(`IMAP` 服务器地址,邮箱地址,密码,是否开启 `SSL` 加密)
with Imbox(mail_host, username=sender, password=mail_pass, ssl=True) as imbox:
	all_inbox_messages = imbox.messages()

筛选邮件与邮件对象

就可以用 Imbox 对象的 messages() 方法筛选电子邮件。messages() 的参数有很多种,可以分别筛选邮箱中的邮件。

python
# 未读邮件: imbox.messages(unread=True)
# 红旗邮件: imbox.messages(flagged=True)
# 某发件人邮件: inbox_messages_from = imbox.messages(sent_from=邮件地口)
"""
按日期筛选邮件:
    date__lt    某天前
    date__gt    某天后
    date_on     指定某一天
    inbox_messages_received_before = imbox.messages(date__lt=datetime.date(2018, 7, 31))
    inbox_messages_received_after = imbox.messages(date__gt=datetime.date(2018, 7, 30))
    inbox_messages_received_on_date = imbox.messages(date__on=datetime.date(2018, 7, 30))
"""

with Imbox(mail_host, username=sender, password=mail_pass, ssl=True) as imbox:
    all_inbox_messages = imbox.messages()
print(all_inbox_messages)
for uid, message in all_inbox_messages:
    print(message.subject)
    print(message.body['plain'])

    """每个邮件可以读取的参数
    message.sent_from          发件人
    message.sent_to            收件人
    message.subject             主题
    message.date                时间
    message.body['plain']       文本格式内容 
    message.body['html']        `HTML` 格式内容
    message.attachments         附件
    """

获取邮件之后对象之后,邮件对象就有自己的一些参数,参数内容如下

参数含义
message.sent_from发件人
message.sent_to收件人
message.subject主题
message.date时间
message.body['plain']文本格式内容
message.body['html']HTML 格式内容
message.attachments附件

取邮件并标记为已读

得到 UID 的列表后,可以调用 Imbox 对象的 .mark_seen(uid) 方法标记为已读,.delete(uid) 删除邮件。

下载附件

1. 获取邮件的全部附件信息

附件的所有信息都存放在 message.attachments 属性里面。这个数量里面是一个列表对象,列表中存放了整个邮件里面的所有文件信息。

2. 下载附件内容

如果邮件中有附件,那就可以将附件下载到本地

python
with Imbox(mail_host, sender, mail_pass) as imbox:
    all_inbox_messages = imbox.messages(unread=False)
    for uid, message in all_inbox_messages:
        print(uid, message)
        # 如果邮件中有附件
        if message.attachments:
            # 遍历所有的附件
            for attachment in message.attachments:
                # 下载并保存附件内容
                with open(attachment['filename'], 'wb') as f:
                    f.write(attachment['content'].getvalue())

附录:发送 QQ 邮件

今天打算用 QQ 邮箱作为示例使用的邮箱,其他邮箱基本操作一样。

1、进入 QQ 邮箱首页,点击设置,如图

image-20210111202105673

2、然后点击账户

image-20210111202135937

3、拉到这个地方,开启POP3/SMTP 服务服务,按照指示操作获取你的邮箱授权码

image-20210111202214895

4、这个就是你的授权码,保存下来等会用