python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python群发邮件并自动收发附件

基于Python实现一键群发邮件并自动收发附件功能

作者:爱分享的飘哥

在职场中,邮件是主要的沟通工具,但你有没有被它拖垮过效率?每月需要向几百个客户邮件群发促销信息,手动一封封发送,耗时巨大,需要定期发送提醒或通知,却总是忘记定时邮件,导致工作延误,将手把手教你如何基于Python实现一键群发邮件并自动收发附件功能

引入:邮件操作重复又耗时?你的沟通效率正在“掉链子”!

邮件操作重复又耗时?你的沟通效率正在“掉链子”!

在职场中,邮件是主要的沟通工具。但你有没有被它“拖垮”过效率?

每月需要向几百个客户邮件群发促销信息,手动一封封发送,或者复制粘贴修改内容,耗时巨大。

需要定期发送提醒或通知,却总是忘记定时邮件,导致工作延误。

这些重复、低效的邮件操作,不仅消耗你的精力,更影响你的沟通效率和办公自动化进程

我将带你进入邮件自动化的奇妙世界!我们将手把手教你如何利用Python的smtplib和imaplib/poplib库,轻松实现:

Python发送邮件: 批量发送、定制内容、附件自动发送。

Python接收邮件: 自动读取、筛选,并智能下载附件。

最终,你将拥有一个强大的**“智能邮件管家”**,

1.使用 smtplib库,完成你的自动化邮件!

要实现Python发送邮件,我们主要使用Python内置的smtplib库。SMTP是用于发送电子邮件的标准协议,smtplib就是Python对SMTP客户端的实现。

实现: smtplib通过连接到SMTP服务器,模拟邮件客户端的行为,将邮件发送出去。

1.1 准备:SMTP服务器配置与授权码获取

在编写代码之前,你需要获取一些信息:

SMTP服务器地址: 不同的邮箱服务商有不同的SMTP地址。

SMTP端口: 通常是25、465(SSL加密)或587(TLS加密)。
发件人邮箱和密码(或授权码): 强烈建议使用授权码而不是邮箱密码,授权码是专门为第三方客户端登录生成的专用密码,安全性更高。

[表格:常见邮箱服务商SMTP配置]

服务商SMTP服务器地址端口(SSL/TLS)备注
QQ邮箱smtp.qq.com465(SSL)/587(TLS)需要开启SMTP服务并获取授权码
163邮箱smtp.163.com465(SSL)/994(SSL)需要开启SMTP服务并获取授权码
Gmailsmtp.gmail.com465(SSL)/587(TLS)可能需要开启“两步验证”并生成应用专用密码
Outlooksmtp.office365.com587(TLS)

如何获取授权码(以QQ邮箱为例):

登录QQ邮箱网页版。
进入“设置” -> “账户”。

找到“POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务”,点击“开启”或“生成授权码”。

根据提示完成验证,即可获得授权码。

1.2 发送你的第一封自动化邮件:文字内容与标题

用Python发送一封简单的文本邮件。
代码:

import smtplib
from email.mime.text import MIMEText # 用于构建文本邮件
from email.header import Header # 用于处理邮件标题中的中文

def send_simple_email(sender_email, sender_password, receiver_email, subject, content):
    """
    发送一封简单的文本邮件。
    这是Python发送邮件的基础。
    :param sender_email: 发件人邮箱地址
    :param sender_password: 发件人邮箱授权码或密码
    :param receiver_email: 收件人邮箱地址
    :param subject: 邮件主题
    :param content: 邮件正文
    """
    # 邮件内容对象:MIMEText用于纯文本邮件,'plain'表示纯文本
    message = MIMEText(content, 'plain', 'utf-8')
    message['From'] = Header(f"Python自动化助手 <{sender_email}>", 'utf-8') # 设置发件人显示名称
    message['To'] = Header(f"收件人 <{receiver_email}>", 'utf-8') # 设置收件人显示名称
    message['Subject'] = Header(subject, 'utf-8') # 设置邮件主题

    try:
        # 连接到SMTP服务器(这里以QQ邮箱为例,使用SSL加密)
        smtp_server = "smtp.qq.com"
        smtp_port = 465 # SSL端口
        
        # 使用with语句确保SMTP连接被正确关闭
        with smtplib.SMTP_SSL(smtp_server, smtp_port) as smtp_obj: # SMTP_SSL用于SSL加密连接
            smtp_obj.login(sender_email, sender_password) # 登录邮箱
            smtp_obj.sendmail(sender_email, receiver_email, message.as_string()) # 发送邮件
        print(f"✅ 邮件已成功发送到:{receiver_email}")
    except Exception as e:
        print(f"❌ 邮件发送失败:{e}")
        print("请检查发件人邮箱、授权码、收件人地址和SMTP服务器配置。")

if __name__ == "__main__":
    # --- 请替换为你的实际邮箱信息和收件人 ---
    my_email = "你的QQ邮箱@qq.com" # 例如: 123456789@qq.com
    my_password = "你的邮箱授权码" # **非常重要,不要用邮箱登录密码!**
    target_email = "目标邮箱@example.com" # 例如: test_receiver@example.com

    send_simple_email(my_email, my_password, target_email, 
                      "来自Python自动化测试邮件", 
                      "这是一封由Python脚本自动发送的测试邮件。\n你好,世界!")

步骤:

获取授权码: 参照1.1节获取你的邮箱授权码。

修改代码信息: 复制上方代码到VS Code,保存为
send_simple_email.py。修改 my_email、my_password、target_email 等。

运行: 在VS Code终端运行 python send_simple_email.py。
检查: 检查目标邮箱是否收到邮件。

展示:

1.3 发送你的第一封自动化邮件:文字内容与标题

场景: 你需要向客户发送包含PDF报告、Excel数据或图片等附件的邮件,或者发送带有图文并茂的HTML格式邮件内容。

方案: email.mime.multipart 和 email.mime.application 模块能帮你构建复杂邮件,包括多部分内容和各种类型附件,实现邮件附件处理的自动化。

代码:

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.header import Header
import os

def send_email_with_attachment_and_html(sender_email, sender_password, receiver_email, subject, html_content, attachment_path=None):
    """
    发送带附件和HTML内容的邮件。
    这是Python发送邮件的高级功能,实现邮件群发和邮件附件处理。
    :param sender_email: 发件人邮箱地址
    :param sender_password: 发件人邮箱授权码或密码
    :param receiver_email: 收件人邮箱地址
    :param subject: 邮件主题
    :param html_content: 邮件正文 (HTML格式)
    :param attachment_path: 附件文件路径,可选
    """
    # 创建多部分邮件对象 (用于包含文本和附件)
    msg = MIMEMultipart('mixed') # 'mixed' 表示邮件包含不同类型的部分
    msg['From'] = Header(f"Python智能助手 <{sender_email}>", 'utf-8')
    msg['To'] = Header(f"重要收件人 <{receiver_email}>", 'utf-8')
    msg['Subject'] = Header(subject, 'utf-8')

    # 1. 添加HTML内容 (Part 1: HTML Body)
    html_part = MIMEText(html_content, 'html', 'utf-8') # 'html'表示HTML格式
    msg.attach(html_part) # 将HTML部分添加到邮件

    # 2. 添加附件 (Part 2: Attachment)
    if attachment_path and os.path.exists(attachment_path):
        try:
            with open(attachment_path, 'rb') as fp:
                # MIMEBase用于所有非文本附件
                attachment = MIMEBase('application', 'octet-stream')
                attachment.set_payload(fp.read()) # 读取附件内容
            
            encoders.encode_base64(attachment) # 编码附件内容
            
            # 设置附件文件名,确保中文文件名正常显示
            attachment.add_header('Content-Disposition', 'attachment', 
                                  filename=Header(os.path.basename(attachment_path), 'utf-8').encode())
            msg.attach(attachment) # 将附件添加到邮件
            print(f"   ✅ 附件 '{os.path.basename(attachment_path)}' 已添加。")
        except Exception as e:
            print(f"❌ 添加附件失败:{e}")
    else:
        print("   ℹ️ 未添加附件或附件文件不存在。")

    try:
        smtp_server = "smtp.qq.com"
        smtp_port = 465 # SSL端口
        with smtplib.SMTP_SSL(smtp_server, smtp_port) as smtp_obj:
            smtp_obj.login(sender_email, sender_password)
            smtp_obj.sendmail(sender_email, receiver_email, msg.as_string())
        print(f"✅ 邮件 (含附件/HTML) 已成功发送到:{receiver_email}")
    except Exception as e:
        print(f"❌ 邮件发送失败:{e}")
        print("请检查发件人邮箱、授权码、收件人地址和SMTP服务器配置。")

if __name__ == "__main__":
    # --- 请替换为你的实际邮箱信息和收件人 ---
    my_email = "你的QQ邮箱@qq.com" 
    my_password = "你的邮箱授权码" 
    target_email = "目标邮箱@example.com" 

    # HTML邮件内容
    html_body = """
    <html>
    <body>
        <p>尊敬的客户:</p>
        <p>您好!</p>
        <p>这是您的<b>最新销售报告</b>,请查收附件。</p>
        <p>感谢您的支持!</p>
        <img src="https://via.placeholder.com/150" alt="占位符图片">
        <p>Python自动化团队 敬上</p>
    </body>
    </html>
    """
    
    # 附件文件 (准备一个测试PDF或图片文件)
    test_attachment_path = os.path.expanduser("~/Desktop/test_report.pdf")
    if not os.path.exists(test_attachment_path):
        # 简单创建模拟PDF附件
        import fitz; doc=fitz.open(); doc.new_page().insert_text((50,50),"附件内容"); doc.save(test_attachment_path); doc.close()
        print(f"临时附件文件 '{os.path.basename(test_attachment_path)}' 已创建。")

    send_email_with_attachment_and_html(my_email, my_password, target_email, 
                                        "【Python自动化】2023年度销售报告", 
                                        html_body, 
                                        test_attachment_path)

步骤:

获取授权码: 参照1.1节获取你的邮箱授权码。
准备附件: 在桌面创建一个test_report.pdf文件(或任何其他文件)。

修改代码信息: 修改 my_email、my_password、target_email、test_attachment_path 等。

运行: 运行 python send_email_attachment_html.py。

检查: 检查目标邮箱是否收到带附件和HTML内容的邮件。

效果展示:

2. 邮件接收核心:Python imaplib / poplib库,完成自动化收件

发送邮件只是自动化的一半。要实现真正的邮件自动化和自动收发附件,自动登录邮箱,读取邮件,甚至智能下载附件!

作用:

IMAP (Internet Message Access Protocol): 更推荐,邮件保留在服务器上,多设备同步,功能更强大(可以操作文件夹)。
POP3 (Post Office Protocol version 3): 邮件通常下载到本地后从服务器删除,适合单设备收取。

2.1 准备: IMAP vs. POP3:选择你的“收件方式”

[表格:IMAP与POP3对比]

特性IMAPPOP3
邮件存储邮件保留在服务器,本地是同步副本邮件下载到本地后通常从服务器删除
多设备同步✅ 完美支持❌ 不支持,易造成混乱
功能强大,可操作服务器文件夹、标记已读/未读简单,仅下载邮件
推荐现代邮件客户端首选旧式,不推荐多设备使用

结论: 对于自动化收取邮件和多设备同步,IMAP是更优的选择。

2.2 连接邮箱与读取邮件:让程序处理你的收件箱

场景: 你需要定期检查邮箱,筛选出特定发件人或主题的邮件,读取其内容。

方案: imaplib(或poplib)能让Python登录你的邮箱,读取邮件的元信息(发件人、主题、日期)和正文,实现Python接收邮件的自动化。

代码:

import imaplib
import email
from email.header import decode_header
import os

def read_emails_imap(email_address, email_password, imap_server="imap.qq.com"):
    """
    通过IMAP协议连接邮箱,并读取邮件列表和基本信息。
    这是Python接收邮件的基础。
    :param email_address: 邮箱地址
    :param email_password: 邮箱授权码或密码
    :param imap_server: IMAP服务器地址
    """
    try:
        # 连接IMAP服务器 (SSL加密)
        mail = imaplib.IMAP4_SSL(imap_server)
        mail.login(email_address, email_password) # 登录邮箱
        mail.select("inbox") # 选择收件箱 (inbox)

        # 搜索所有邮件 (ALL) 或特定条件的邮件 (e.g., 'FROM', 'SUBJECT')
        # status, email_ids = mail.search(None, 'FROM', 'sender@example.com') # 筛选发件人
        status, email_ids = mail.search(None, 'ALL') # 搜索所有邮件
        email_id_list = email_ids[0].split() # 邮件ID列表

        print(f"🚀 正在读取邮箱 '{email_address}' 的邮件...")
        print(f"   共找到 {len(email_id_list)} 封邮件。")

        # 遍历邮件ID,获取邮件信息
        for i, email_id in enumerate(email_id_list[-5:]): # 只处理最近5封邮件,避免处理太多
            status, msg_data = mail.fetch(email_id, '(RFC822)') # 获取邮件的完整内容
            raw_email = msg_data[0][1].decode('utf-8') # 解码邮件内容
            msg = email.message_from_string(raw_email) # 解析邮件

            subject, encoding = decode_header(msg['Subject'])[0]
            if isinstance(subject, bytes):
                subject = subject.decode(encoding if encoding else 'utf-8')
            
            sender, encoding = decode_header(msg['From'])[0]
            if isinstance(sender, bytes):
                sender = sender.decode(encoding if encoding else 'utf-8')

            print(f"--- 邮件 {i+1} ---")
            print(f"   发件人: {sender}")
            print(f"   主题: {subject}")
            # print(f"   日期: {msg['Date']}") # 邮件日期

            # 获取邮件正文
            # for part in msg.walk():
            #     ctype = part.get_content_type()
            #     cdispo = str(part.get('Content-Disposition'))
            #     if ctype == 'text/plain' and 'attachment' not in cdispo:
            #         body = part.get_payload(decode=True).decode('utf-8')
            #         print("   正文片段:", body[:100], "...") # 打印部分正文
            #         break
        
        mail.logout() # 登出邮箱
        print("✨ 邮件读取完成!")
    except Exception as e:
        print(f"❌ 读取邮件失败:{e}")
        print("请检查邮箱地址、授权码、IMAP服务器地址和网络连接。")

if __name__ == "__main__":
    # --- 请替换为你的实际邮箱信息 ---
    my_email = "你的QQ邮箱@qq.com" 
    my_password = "你的邮箱授权码" 
    
    read_emails_imap(my_email, my_password)

步骤:

获取授权码: 参照1.1节获取你的邮箱授权码,并确保IMAP服务已开启。
修改代码信息: 复制上方代码到VS Code,保存为read_emails_imap.py。修改 my_email 和 my_password。

运行: 在VS Code终端运行 python read_emails_imap.py。

展示:

2.3 智能附件处理:自动下载重要报告,告别手动!

场景: 每天都需要从邮件中下载特定的报告(如“日报”、“月度报告”),但附件多、邮件杂,手动查找下载耗时耗力。

方案: 结合邮件解析和文件操作,Python能帮你自动识别邮件中的附件,筛选出你需要的附件类型或名称,并自动下载到指定文件夹,实现邮件附件处理的自动化!

代码:

import imaplib
import email
from email.header import decode_header
import os

def download_attachments_from_emails(email_address, email_password, imap_server="imap.qq.com", 
                                     search_subject="", download_folder="Downloaded_Attachments"):
    """
    通过IMAP协议连接邮箱,搜索特定主题的邮件,并自动下载附件。
    这是Python接收邮件和邮件附件处理的核心功能。
    :param email_address: 邮箱地址
    :param email_password: 邮箱授权码或密码
    :param imap_server: IMAP服务器地址
    :param search_subject: 要搜索的邮件主题关键词 (留空则搜索所有邮件)
    :param download_folder: 附件下载保存的文件夹
    """
    os.makedirs(download_folder, exist_ok=True) # 确保下载文件夹存在

    try:
        mail = imaplib.IMAP4_SSL(imap_server)
        mail.login(email_address, email_password)
        mail.select("inbox")

        # 搜索邮件 (可以按主题、发件人等搜索)
        if search_subject:
            status, email_ids = mail.search(None, 'SUBJECT', f'"{search_subject}"')
        else:
            status, email_ids = mail.search(None, 'ALL')
        
        email_id_list = email_ids[0].split()

        print(f"🚀 正在搜索并下载附件,主题关键词:'{search_subject}'...")
        if not email_id_list:
            print("   ℹ️ 未找到符合条件的邮件。")
        else:
            print(f"   找到 {len(email_id_list)} 封符合条件的邮件。")

        for email_id in email_id_list:
            status, msg_data = mail.fetch(email_id, '(RFC822)')
            raw_email = msg_data[0][1].decode('utf-8')
            msg = email.message_from_string(raw_email)

            subject, _ = decode_header(msg['Subject'])[0]
            subject = subject.decode(_) if isinstance(subject, bytes) else subject
            sender, _ = decode_header(msg['From'])[0]
            sender = sender.decode(_) if isinstance(sender, bytes) else sender
            
            print(f"--- 处理邮件 (主题: {subject}) ---")

            for part in msg.walk():
                # 跳过非附件部分
                if part.get_content_maintype() == 'multipart' or part.get('Content-Disposition') is None:
                    continue
                
                filename = part.get_filename()
                if filename: # 如果是附件
                    filename, _ = decode_header(filename)[0] # 解码附件文件名中的中文
                    filename = filename.decode(_) if isinstance(filename, bytes) else filename

                    file_path = os.path.join(download_folder, filename)
                    
                    try:
                        with open(file_path, 'wb') as f:
                            f.write(part.get_payload(decode=True)) # 写入附件内容
                        print(f"   ✅ 附件已下载:'{filename}'")
                    except Exception as e:
                        print(f"   ❌ 下载附件 '{filename}' 失败:{e}")
        
        mail.logout()
        print("✨ 附件下载完成!")
    except Exception as e:
        print(f"❌ 收取邮件或下载附件失败:{e}")
        print("请检查邮箱地址、授权码、IMAP服务器地址和网络连接。")

if __name__ == "__main__":
    # --- 请替换为你的实际邮箱信息 ---
    my_email = "你的QQ邮箱@qq.com" 
    my_password = "你的邮箱授权码" 
    
    download_folder_path = os.path.expanduser("~/Desktop/Downloaded_Reports")
    os.makedirs(download_folder_path, exist_ok=True) # 确保下载目录存在

    # 示例:搜索主题包含“销售报告”的邮件,并下载附件
    # 建议先手动给你的邮箱发送几封带附件(如PDF、Excel)且主题包含“销售报告”的测试邮件
    download_attachments_from_emails(my_email, my_password, 
                                     search_subject="销售报告", 
                                     download_folder=download_folder_path)

步骤:

获取授权码: 参照1.1节获取你的邮箱授权码,确保IMAP服务已开启。
准备测试邮件: 手动向你的邮箱发送几封带附件(例如PDF、Excel文件)且主题包含你设定的关键词(例如“销售报告”)的测试邮件。

修改代码信息: 复制上方代码到VS Code,保存为download_attachments.py。修改 my_email、my_password、search_subject 和 download_folder。

运行: 在VS Code终端运行 python download_attachments.py。

展示:

成果:你的智能邮件助手!

恭喜你!通过本篇文章,你已经掌握了邮件自动化的各项核心魔法,亲手打造了一个能够一键群发邮件,自动收发附件的智能邮件助手!

我们深入学习了smtplib和imaplib / poplib等库,实现了:

总结与展望:邮件自动化,沟通效率倍增的秘密!

通过本篇文章,你已经掌握了邮件自动化的强大能力,为你的办公自动化之旅又增添了一个重量级技能!你学会了如何利用Python的邮件发送和接收库,高效地管理和处理邮件。

除了今天学到的邮件自动化功能,你还希望Python能帮你实现哪些更复杂的邮件管理需求?比如:自动回复特定邮件?根据邮件内容自动分类归档?

以上就是基于Python实现一键群发邮件并自动收发附件功能的详细内容,更多关于Python群发邮件并自动收发附件的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文