Python邮件自动化实战之发送附件和智能处理收件箱

 更新时间:2026年03月12日 08:50:07   作者:MarkHD  
这篇文章主要介绍了Python中邮件自动化的核心技能,涵盖发送和接收邮件两大模块,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

引言

在自动化运维和日常办公中,电子邮件依然是最正式、最广泛使用的通知和交互手段。无论是定时发送报表、监控报警,还是自动处理用户请求,邮件自动化都是程序员工具箱中的必备技能。

在Python领域,大多数开发者对smtplib发送邮件较为熟悉,但在邮件接收与处理(尤其是IMAP协议)方面却往往力不从心,通常需要编写大量底层代码来处理邮件解析、附件下载和搜索条件。本篇文章将深入浅出,不仅讲解如何使用smtplib发送带附件的复杂邮件,更将重点引入强大的第三方库——imap_tools,手把手教你如何优雅地读取和处理收件箱邮件,实现真正意义上的邮件自动化闭环。

夯实基础 —— 使用smtplib发送带附件的邮件

SMTP(Simple Mail Transfer Protocol)是推送邮件的协议。Python的smtplib模块封装了其底层细节,而email库则负责构建符合MIME标准的邮件内容。

核心概念:MIMEMultipart

要发送带附件的邮件,我们不能使用简单的MIMEText对象。因为邮件包含独立的两部分:正文和附件。这时需要用到MIMEMultipart,它是一个容器,可以将不同的MIME部分组合在一起。

一个标准的带附件邮件结构如下:

MIMEMultipart(混合类型)

  • MIMEText(纯文本或HTML正文)
  • MIMEBase / MIMEApplication(附件)

实战:发送带Excel附件的HTML邮件

下面的示例演示了如何连接QQ邮箱的SMTP服务器,发送一封包含HTML样式的正文,并附带一个Excel文件的邮件。

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from email.utils import formataddr

# 邮件配置
SMTP_SERVER = 'smtp.qq.com'
SMTP_PORT = 587  # TLS端口
SENDER_EMAIL = 'your_qq@qq.com'
SENDER_PWD = '你的授权码'  # QQ邮箱需使用授权码,非登录密码

def send_email_with_attachment(receiver, subject, html_content, attachment_path):
    """
    发送带附件的HTML邮件
    """
    # 创建一个混合类型的邮件对象
    msg = MIMEMultipart()
    msg['From'] = formataddr(('自动化发送者', SENDER_EMAIL))
    msg['To'] = receiver
    msg['Subject'] = subject

    # 1. 添加HTML正文
    msg.attach(MIMEText(html_content, 'html', 'utf-8'))

    # 2. 处理附件
    try:
        with open(attachment_path, 'rb') as f:
            # 创建附件对象 (MIMEBase)
            part = MIMEBase('application', 'octet-stream')
            part.set_payload(f.read())
            # 编码为Base64
            encoders.encode_base64(part)
            # 添加头部信息,声明此为附件
            filename = attachment_path.split('/')[-1]  # 获取文件名
            part.add_header(
                'Content-Disposition',
                f'attachment; filename="{filename}"'
            )
            msg.attach(part)
    except FileNotFoundError:
        print(f"附件 {attachment_path} 未找到,邮件将无附件发送。")

    # 3. 发送邮件
    try:
        server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
        server.starttls()  # 启用TLS加密
        server.login(SENDER_EMAIL, SENDER_PWD)
        server.sendmail(SENDER_EMAIL, receiver, msg.as_string())
        server.quit()
        print(f"邮件发送成功至 {receiver}")
    except Exception as e:
        print(f"发送失败: {e}")

# 使用示例
if __name__ == '__main__':
    html_body = """
    <h2>月度数据报告</h2>
    <p>您好,</p>
    <p>本月销售数据请见附件。</p>
    <p><strong>请注意:</strong> 此邮件由系统自动发送,请勿回复。</p>
    """
    send_email_with_attachment(
        receiver='target@example.com',
        subject='【自动化】2024年5月销售报表',
        html_content=html_body,
        attachment_path='./report.xlsx'  # 假设当前目录有该文件
    )

注意事项

  • 使用.starttls()时端口通常为587;若使用SSL,则端口为465并改用smtplib.SMTP_SSL
  • 对于Gmail、QQ等邮箱,务必使用授权码而非邮箱密码,以确保安全性。

进阶突破 —— 使用imap_tools智能处理收件箱

发送邮件只是自动化的一半。如何自动读取邮件、下载附件或根据规则自动回复,才是真正的难点。标准库imaplib虽然功能强大,但使用起来较为繁琐。这里推荐使用基于imaplib封装的高阶库——imap_tools,它提供了简洁的查询语法和对象化的邮件属性。

安装与基础连接

首先,安装这个轻量级且无外部依赖的库:

pip install imap-tools

基础连接使用上下文管理器(with语句),确保连接自动关闭:

from imap_tools import MailBox

# 连接IMAP服务器(QQ邮箱IMAP地址:imap.qq.com)
with MailBox('imap.qq.com').login('your_qq@qq.com', '你的授权码', initial_folder='INBOX') as mailbox:
    print("登录成功,当前文件夹:收件箱")
    # 后续操作...

强大的查询语法(AND/OR/NOT)

imap_tools的核心优势在于其查询构造器。它模仿了SQLAlchemy的语法,告别了复杂的IMAP搜索字符串。

基本查询示例

from imap_tools import MailBox, AND, OR, NOT

with MailBox('imap.qq.com').login('your_qq@qq.com', '授权码', 'INBOX') as mailbox:
    
    # 1. 查询未读邮件
    unread_emails = mailbox.fetch(AND(seen=False))
    
    # 2. 查询特定发件人且包含附件的邮件
    specific_emails = mailbox.fetch(AND(from_='boss@company.com', subject='报告'))
    
    # 3. 复杂查询:来自某个域,或者是紧急邮件
    complex_query = OR(
        from_='@important.com',
        subject='URGENT'
    )
    for msg in mailbox.fetch(complex_query):
        print(msg.subject)
    
    # 4. 日期范围查询:近3天的邮件
    from datetime import date, timedelta
    three_days_ago = date.today() - timedelta(days=3)
    recent_mails = mailbox.fetch(AND(date_gte=three_days_ago))

解析邮件并下载附件

MailMessage对象提供了直观的属性来访问邮件内容。以下是一个自动下载所有未读邮件附件的脚本:

import os
from imap_tools import MailBox, AND

DOWNLOAD_DIR = './attachments'

def download_attachments_from_inbox():
    # 确保下载目录存在
    os.makedirs(DOWNLOAD_DIR, exist_ok=True)
    
    with MailBox('imap.qq.com').login('your_qq@qq.com', '授权码', 'INBOX') as mailbox:
        # 获取所有未读邮件
        # fetch 返回一个生成器,支持分页和排序,这里设置 reverse=True 让最新的邮件先出现
        for msg in mailbox.fetch(AND(seen=False), reverse=True, limit=50):  # 限制处理50封,防止过载
            print(f"处理邮件: {msg.subject} 来自: {msg.from_}")
            
            # 检查是否有附件
            if msg.attachments:
                for att in msg.attachments:
                    # att 是 MailAttachment 对象
                    filename = att.filename
                    # 可以按文件类型过滤
                    if filename.endswith(('.xlsx', '.pdf', '.docx')):
                        file_path = os.path.join(DOWNLOAD_DIR, filename)
                        # att.payload 是附件的二进制数据 (bytes)
                        with open(file_path, 'wb') as f:
                            f.write(att.payload)
                        print(f"  已下载附件: {filename}")
                
                # 处理完后,可以将邮件标记为已读(默认fetch时mark_seen=True),或移动到其他文件夹
                # 将邮件移动到 "Processed" 文件夹
                mailbox.move([msg.uid], 'PROCESSED')
            else:
                # 无附件邮件,直接标记为已读,也可以不做任何操作
                # 如果不希望在fetch时自动标记已读,可以在fetch参数中设置 mark_seen=False
                pass

if __name__ == '__main__':
    download_attachments_from_inbox()

代码解析

  • msg.attachments 返回一个由 MailAttachment 对象组成的列表,每个对象包含 filenamepayload(二进制)、content_type 等属性。
  • mailbox.move([msg.uid], 'PROCESSED') 演示了如何将处理完的邮件移动到指定文件夹,实现收件箱归零。
  • fetch 方法的 limit 参数可以有效防止一次性处理大量邮件导致的性能问题。

邮件自动回复机器人雏形

结合发送和接收,我们可以构建一个简单的自动应答机器人:当收到特定主题的邮件时,自动回复预设内容。

import smtplib
from email.mime.text import MIMEText
from imap_tools import MailBox, AND

# 发送函数 (简化版)
def send_reply(to_addr, original_subject):
    smtp_server = smtplib.SMTP('smtp.qq.com', 587)
    smtp_server.starttls()
    smtp_server.login('your_qq@qq.com', '授权码')
    
    msg = MIMEText('感谢您的来信,我们已经收到您的请求,会尽快处理。', 'plain', 'utf-8')
    msg['From'] = 'your_qq@qq.com'
    msg['To'] = to_addr
    msg['Subject'] = f'RE: {original_subject} [自动回复]'
    
    smtp_server.send_message(msg)
    smtp_server.quit()

# 主监控逻辑
def auto_responder():
    with MailBox('imap.qq.com').login('your_qq@qq.com', '授权码', 'INBOX') as inbox:
        # 查找未读的、主题包含"咨询"的邮件
        for msg in inbox.fetch(AND(seen=False, subject='咨询')):
            # 发送自动回复
            send_reply(msg.from_, msg.subject)
            print(f"已回复: {msg.from_}")
            
            # 标记为已读并添加自定义标志
            inbox.flag([msg.uid], ['ANSWERED'], True)

综合实战:监控邮箱并自动备份附件

假设你有一个需求:每天定时检查收件箱,将当天收到的所有邮件的Excel附件下载下来,并将下载记录发送给管理员。

完整流程

  • 使用imap_tools连接IMAP,查询当天日期范围内的邮件。
  • 遍历邮件,下载.xlsx附件。
  • 所有附件下载完成后,调用smtplib发送一封汇总邮件给管理员。

这部分代码融合了上述所有知识点,是邮件自动化的典型应用场景。通过结合操作系统的定时任务(如Linux Crontab或Windows任务计划程序),即可实现无人值守的自动化处理。

常见问题与避坑指南

授权码 vs 密码:几乎所有主流邮箱(QQ、163、Gmail)在开启SMTP/IMAP服务后,都需要使用生成的授权码作为密码登录,直接使用网页登录密码会报错。

IMAP文件夹名称:默认收件箱是INBOX。其他文件夹(如“已发送”、“归档”)的名称可能因邮箱服务商而异,例如QQ邮箱的“已发送”可能是&XfJT0ZAB4这种编码形式。建议先使用mailbox.folder.list()打印所有文件夹名称。

附件编码att.payload返回的是原始二进制数据,直接写入文件即可。如果遇到附件名乱码,可以使用att.filename,该属性通常已经被imap-tools处理过。

性能考量:如果需要处理海量邮件,务必使用fetchlimitbulk参数。设置bulk=True可以减少与服务器的交互次数,但会占用更多内存。

到此这篇关于Python邮件自动化实战之发送附件和智能处理收件箱的文章就介绍到这了,更多相关Python邮件自动化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python实现自动化邮件发送过程详解

    Python实现自动化邮件发送过程详解

    这篇文章主要介绍了如何利用Python实现自动化邮件发送,可以让你摆脱繁琐的重复性业务,可以节省非常多的时间。感兴趣的小伙伴可以试一试
    2022-01-01
  • Python实现网格交易策略的过程

    Python实现网格交易策略的过程

    本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一个量化策略是怎么实现的吧
    2025-07-07
  • Python获取网页数据的五种方法

    Python获取网页数据的五种方法

    在 Python 中,爬虫用于自动化获取网页数据,你可以使用多种方法来抓取网页内容,具体使用哪种方法取决于网页的结构、内容类型以及你所需的精确度,以下是常见的 5 种获取网页数据的方式,需要的朋友可以参考下
    2025-01-01
  • Python实现批量提取Excel数据

    Python实现批量提取Excel数据

    在数据处理和分析的过程中,Excel 是一种广泛使用的数据存储格式,本文将详细介绍如何使用 pandas、openpyxl 和 xlrd 三种库来批量提取 Excel 数据,并提供相应的示例代码,需要的可以参考下
    2024-12-12
  • Python全栈之学习JS(1)

    Python全栈之学习JS(1)

    这篇文章主要为大家介绍了Python全栈之JS,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • 一文带你掌握Python性能分析工具Pyflame火焰图的实战指南

    一文带你掌握Python性能分析工具Pyflame火焰图的实战指南

    你是否曾经遇到过Python程序运行缓慢,却不知道问题出在哪里,Pyflame就是为解决这个问题而生的利器,下面小编就和大家详细讲讲Pyflame的具体使用吧
    2025-12-12
  • 利用Python如何生成hash值示例详解

    利用Python如何生成hash值示例详解

    这篇文章主要给大家介绍了关于利用Python如何生成hash值的相关资料,并且给大家分享了利用Python一句话校验软件哈希值的方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2017-12-12
  • django-celery-beat搭建定时任务的实现

    django-celery-beat搭建定时任务的实现

    本文主要介绍了django-celery-beat搭建定时任务的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Python使用pandas导入xlsx格式的excel文件内容操作代码

    Python使用pandas导入xlsx格式的excel文件内容操作代码

    这篇文章主要介绍了Python使用pandas导入xlsx格式的excel文件内容,基本导入是在Python中使用pandas导入.xlsx文件的方法是read_excel(),本文结合示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • Python xlwt库处理整数格式的陷阱与最佳实践

    Python xlwt库处理整数格式的陷阱与最佳实践

    在使用 Python 进行数据处理并导出到 Excel 时,xlwt 是一个经典且广泛使用的库,本文将深入探讨 xlwt 处理整数时的核心机制,分析常见陷阱,并提供一套完整的解决方案,希望对大家有所帮助
    2026-01-01

最新评论