Python自动发邮件:从基础群发到带附件的完整方案

📂 文章

办公场景中邮件的痛点

每个职场人都有过这样的经历:月底了,要给50个客户发账单邮件,每封都要改名字、附附件、调格式。手动做,半天就没了。

Python可以帮你把这件事自动化。核心用到两个库:smtplib(发送邮件)和email(构建邮件内容),都是Python内置的,不需要额外安装。

基础:发送一封纯文本邮件

import smtplib
from email.mime.text import MIMEText

def send_text_email(to_addr, subject, body):
    """发送纯文本邮件"""
    # 邮件配置
    smtp_server = "smtp.qq.com"  # QQ邮箱SMTP服务器
    smtp_port = 465              # SSL端口
    sender = "your@qq.com"
    password = "your_auth_code"  # 授权码,不是登录密码
    
    # 构建邮件
    msg = MIMEText(body, "plain", "utf-8")
    msg["Subject"] = subject
    msg["From"] = sender
    msg["To"] = to_addr
    
    # 发送
    with smtplib.SMTP_SSL(smtp_server, smtp_port) as server:
        server.login(sender, password)
        server.sendmail(sender, [to_addr], msg.as_string())
    print(f"邮件已发送至 {to_addr}")

# 使用
send_text_email(
    "boss@company.com",
    "周报提交",
    "领导好,本周工作周报已附件,请查收。"
)

进阶:发送HTML格式邮件

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

def send_html_email(to_addr, subject, html_content):
    """发送HTML格式邮件"""
    msg = MIMEMultipart()
    msg["Subject"] = subject
    msg["From"] = "your@qq.com"
    msg["To"] = to_addr
    
    # HTML内容
    html = MIMEText(html_content, "html", "utf-8")
    msg.attach(html)
    
    # 发送(同上)
    with smtplib.SMTP_SSL("smtp.qq.com", 465) as server:
        server.login("your@qq.com", "your_auth_code")
        server.sendmail("your@qq.com", [to_addr], msg.as_string())

# 使用:发送带表格的HTML邮件
html = """


    

月度销售报告

以下是本月销售数据汇总:

产品销量金额
产品A150¥45,000
产品B89¥26,700
产品C234¥70,200

详细数据请查看附件。

""" send_html_email("client@example.com", "7月销售报告", html)

实战:带附件发送

from email.mime.base import MIMEBase
from email import encoders
import os

def send_with_attachment(to_addr, subject, body, file_path):
    """发送带附件的邮件"""
    msg = MIMEMultipart()
    msg["Subject"] = subject
    msg["From"] = "your@qq.com"
    msg["To"] = to_addr
    
    # 正文
    msg.attach(MIMEText(body, "plain", "utf-8"))
    
    # 附件
    if os.path.exists(file_path):
        with open(file_path, "rb") as f:
            attachment = MIMEBase("application", "octet-stream")
            attachment.set_payload(f.read())
            encoders.encode_base64(attachment)
            filename = os.path.basename(file_path)
            attachment.add_header(
                "Content-Disposition",
                f"attachment; filename={filename}"
            )
            msg.attach(attachment)
        print(f"附件已添加:{filename}")
    
    # 发送
    with smtplib.SMTP_SSL("smtp.qq.com", 465) as server:
        server.login("your@qq.com", "your_auth_code")
        server.sendmail("your@qq.com", [to_addr], msg.as_string())

批量群发:给50个客户发账单

import pandas as pd
import time

def batch_send_bills():
    """批量发送客户账单"""
    # 读取客户列表
    clients = pd.read_excel("客户账单.xlsx")
    
    for _, row in clients.iterrows():
        name = row["客户姓名"]
        email = row["邮箱"]
        amount = row["账单金额"]
        bill_file = row["账单文件路径"]
        
        # 个性化邮件内容
        body = f"""{name},您好!

您本月账单已出,详情如下:
- 账单金额:¥{amount:,.2f}
- 账单日期:2026年7月

详细账单请查看附件。如有疑问请随时联系。

祝好!
"""
        try:
            send_with_attachment(
                email,
                f"【账单】{name} - 2026年7月",
                body,
                bill_file
            )
            print(f"✓ 已发送给 {name}")
            time.sleep(2)  # 间隔2秒,避免被限流
        except Exception as e:
            print(f"✗ 发送失败 {name}: {e}")

batch_send_bills()

注意事项

授权码:QQ邮箱、163邮箱都需要开启SMTP服务并获取授权码,不是登录密码。

发送频率:每封邮件间隔2-5秒,否则可能被判定为垃圾邮件。

退订机制:群发商业邮件务必提供退订方式,这是法律要求。

测试先行:批量发送前先发给自己测试,确认格式和附件没问题。