Python脚本如何操作邮件收发

wen 实用脚本 1

Python脚本实现邮件自动化收发全攻略

目录导读

  1. 为什么要用Python操作邮件?
  2. 核心库选择:smtplib与imaplib的对比
  3. 发送邮件的完整代码拆解
  4. 接收并解析邮件的实战案例
  5. 常见问题解答(FAQ)
  6. SEO优化与安全建议

为什么要用Python操作邮件?

在日常工作中,我们常常需要批量发送通知邮件(如日报、报表)、自动读取验证码、监控收件箱中的关键信息(如订单确认、退款提醒),手动操作不仅耗时,还容易出错,Python通过内置库和第三方库,能够以极简代码实现邮件收发自动化,大幅提升效率。

Python脚本如何操作邮件收发

适用场景

  • 自动发送:定时推送周报、营销邮件、系统告警。
  • 自动接收:从收件箱提取附件、解析验证码、识别特定主题的邮件。
  • 数据集成:将邮件内容存入数据库或触发后续工作流(如添加工单)。

问题1:Python收发邮件需要开启什么协议? 解答:发送邮件需使用SMTP协议(如smtp.gmail.com),接收邮件需使用IMAP(推荐,支持管理服务器上的邮件)或POP3(仅下载),大多数邮箱需要开启“允许低安全性应用”或生成专用应用密码(如QQ邮箱、163邮箱的授权码)。


核心库选择:smtplib与imaplib的对比

Python官方库提供了两组核心模块:

功能模块 发送邮件 (smtplib) 接收邮件 (imaplib / poplib)
使用场景 构造并发送邮件 读取/搜索/删除服务器上的邮件
核心类 SMTP(或SMTP_SSL IMAP4(或IMAP4_SSL
常用方法 sendmail(), login() search(), fetch(), store()
编码配合 email.mime.text, email.mime.multipart email.parser, email.message_from_bytes

关键点

  • 发送时需构造MIME对象(可带附件、HTML正文)。
  • 接收时需先登录,选择收件箱(INBOX),再搜索指定条件的邮件(如“未读”、“来自某地址”)。

问题2:为什么有些邮箱用smtplib发送失败? 解答:常见原因包括:

  • 未使用SSL加密(端口465或587需TLS)。
  • 授权码错误(需用邮箱生成的专用密码,而非登录密码),包含敏感词或图片链接被服务器拦截,建议使用SMTP_SSL()并设置login()里填授权码。

发送邮件的完整代码拆解

以下代码展示如何发送一封带附件和HTML样式的邮件,适配主流邮箱(如Gmail、QQ、163):

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
# 邮箱配置
smtp_server = "smtp.qq.com"          # 发送服务器
port = 465                           # SSL端口
sender = "your@qq.com"
password = "你的授权码"               # 邮箱生成的授权码,非登录密码
receiver = "target@example.com"
# 构建邮件对象
msg = MIMEMultipart()
msg["From"] = sender
msg["To"] = receiver
msg["Subject"] = "Python自动化测试邮件 | 包含附件"
HTML格式)
body = """
<html>
  <body>
    <h2>这是一封自动发送的测试邮件</h2>
    <p>附件中是本周的销售数据表。</p>
  </body>
</html>
"""
msg.attach(MIMEText(body, "html", "utf-8"))
# 添加附件(以Excel为例)
filename = "data.xlsx"
try:
    with open(filename, "rb") as attachment:
        part = MIMEBase("application", "octet-stream")
        part.set_payload(attachment.read())
        encoders.encode_base64(part)
        part.add_header(
            "Content-Disposition",
            f"attachment; filename= {filename}",
        )
        msg.attach(part)
except FileNotFoundError:
    print(f"附件 {filename} 未找到,已跳过附件发送。")
# 发送
try:
    with smtplib.SMTP_SSL(smtp_server, port) as server:
        server.login(sender, password)          # 使用授权码登录
        server.sendmail(sender, receiver, msg.as_string())
    print("邮件发送成功!")
except smtplib.SMTPAuthenticationError:
    print("认证失败:请检查授权码是否正确,或邮箱是否允许SMTP服务。")
except smtplib.SMTPRecipientsRefused:
    print("收件人地址被拒绝,请确认邮箱格式。")

要点解析

  • 使用MIMEMultipart作为容器,可同时携带文本和附件。
  • 附件读取后需编码为Base64,避免中文乱码。
  • SMTP_SSL直接建立加密连接,避免明文传输。
  • 异常捕获(如认证失败、附件缺失)是生产环境的必要步骤。

问题3:可以发送多个收件人吗?如何实现? 解答:可以通过cc(抄送)和bcc(密送)实现,只需在msg["To"]中传入(逗号)分隔的地址,并分别设置msg["Cc"]msg["Bcc"]字段,但smtp.sendmail()的参数to_addrs必须包含所有收件人(包括Cc和Bcc地址)。


接收并解析邮件的实战案例

以下代码演示登录邮箱并读取最近3封未读邮件的摘要(发件人、主题、正文文本):

import imaplib
import email
from email.header import decode_header
# IMAP配置
imap_server = "imap.qq.com"
username = "your@qq.com"
password = "你的授权码"          # 同样是邮箱授权码
# 登录并选择收件箱
mail = imaplib.IMAP4_SSL(imap_server)
mail.login(username, password)
mail.select("INBOX")            # 选择收件箱
# 搜索未读邮件
status, messages = mail.search(None, "UNSEEN")
if status == "OK":
    email_ids = messages[0].split()
    # 只处理最近3封
    for e_id in email_ids[-3:]:
        res, msg_data = mail.fetch(e_id, "(RFC822)")
        for response_part in msg_data:
            if isinstance(response_part, tuple):
                msg = email.message_from_bytes(response_part[1])
                # 解码主题
                subject, encoding = decode_header(msg["Subject"])[0]
                if isinstance(subject, bytes):
                    subject = subject.decode(encoding if encoding else "utf-8")
                # 提取发件人
                from_ = msg.get("From")
                print(f"主题: {subject}")
                print(f"发件人: {from_}")
                # 获取正文(纯文本优先)
                if msg.is_multipart():
                    for part in msg.walk():
                        if part.get_content_type() == "text/plain":
                            body = part.get_payload(decode=True).decode("utf-8", errors="ignore")
                            break
                else:
                    body = msg.get_payload(decode=True).decode("utf-8", errors="ignore")
                print(f"正文前100字: {body[:100]}...")
                print("-" * 40)
# 关闭连接
mail.logout()

关键细节

  • 使用search(None, "UNSEEN")只抓取未读邮件,避免重复处理。
  • email.message_from_bytes()解析原始邮件数据。
  • 处理多部分邮件(含附件和HTML)时,需用walk()遍历子部分。
  • 记得decode_header处理编码主题,否则可能出现乱码。

问题4:如何处理邮件附件? 解答:在上方代码遍历msg.walk()时,判断part.get_content_maintype() == 'application'part.get_filename()不为空则视为附件,使用part.get_payload(decode=True)获得二进制数据,再保存到本地文件,示例:

if part.get_filename():
    filename = decode_header(part.get_filename())[0][0]
    if isinstance(filename, bytes):
        filename = filename.decode("utf-8")
    with open(filename, "wb") as f:
        f.write(part.get_payload(decode=True))

常见问题解答(FAQ)

Q1:发送邮件时频繁报错“535 Authentication failed”,如何解决? A:确认两点:① 使用邮箱的授权码(不是登录密码);② 在邮箱设置中开启“SMTP服务”或“POP3/IMAP/SMTP服务”,多数邮箱(如QQ、163)需在网页端“设置”-“账户”中生成授权码。

Q2:接收邮件时,为什么有邮件解析不出正文? A:可能原因是邮件是纯HTML多部分且无text/plain部分,或编码不是UTF-8,可尝试用get_content_type()判断,并回退到text/html再提取纯文本(用BeautifulSoup或正则去标签)。

Q3:脚本可以定时运行吗? A:可以,在Windows系统使用“任务计划程序”调用python your_script.py;Linux/Mac使用crontab设定时间(如0 8 * * * python /path/script.py每天8点执行),商业应用建议用APScheduler库实现更灵活的任务调度。

Q4:如何确保邮件发送的并发稳定? A:对于大量邮件(如千封以上),务必控制并发数(建议用线程池限制为5-10个连接),并加入重试机制(如失败后等待10秒重试2次),重点:部分邮箱对单日发送量有上限(如免费QQ邮箱每天500封),需提前规划发送频率。


SEO优化与安全建议

安全注意事项

  • 授权码保护:绝不可将授权码硬编码在公开仓库中,建议使用环境变量(os.getenv("EMAIL_PASSWORD"))或配置文件(.env)。
  • 连接加密:始终使用SSL/TLS端口(465或587),避免使用明文25端口,过滤**:避免发送大量垃圾邮件,否则IP会被邮箱服务器拉黑。
  • 收件规则限制:接收脚本应设置超时(mail.socket.setdefaulttimeout(10)),防止死循环。

代码性能优化

  • 批量发送:可循环遍历收件人列表,但每次发送完加入time.sleep(1)避免触发限速。
  • 接收全量邮件:使用search(None, "ALL")然后分页获取,每次只fetch 50封减少带宽消耗。
  • 使用现代库yagmail(简化发送)和imbox(简化接收)适合快速开发,但官方库更适合需要深度自定义的场景。

搜索引擎排名提示包含核心关键词**:如“Python邮件自动化”、“smtp发送邮件教程”。

  • 内链建设:在文章提到“SMTP协议”时链接到详细文档(如官方smtplib手册)。
  • 结构化数据:使用H2/H3层级标题,配合<ul><code>标签方便爬虫理解。
  • 示例代码可复制:将代码段放在<pre><code>中并提供简洁注释,提升用户停留时间。

通过本文的实战代码和最佳实践,您已掌握使用Python脚本操作邮件收发的核心技能,从单封发送到批量监控,从纯文本到多附件,按需组合这些模块,即可打造属于你自己的邮件自动化工作流。

抱歉,评论功能暂时关闭!