影刀RPA 邮件合并:批量发送个性化邮件的完整方案

0 阅读3分钟

影刀RPA 邮件合并:批量发送个性化邮件的完整方案

作者:林焱

在这里插入图片描述

需要给客户发500封邮件,每封的内容不一样(收件人姓名、金额、订单号都不同)。这就是邮件合并——用模板+数据源,自动生成个性化邮件并发送。

邮件合并的三要素

  • 模板:邮件的骨架(固定部分)

  • 数据源:Excel或数据库里的个性化数据(变量部分)

  • 合并引擎:Python代码,把模板和数据组装成最终邮件

  • 在这里插入图片描述

[video(video-JYzyE1IM-1784928598474)(type-csdn)(url-live.csdn.net/v/embed/525…)]

基于Excel数据源的邮件合并

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

# 读取数据源
def load_recipients(excel_path):
    wb = openpyxl.load_workbook(excel_path)
    ws = wb.active
    headers = [cell.value for cell in ws[1]]
    
    recipients = []
    for row in ws.iter_rows(min_row=2, values_only=True):
        recipients.append(dict(zip(headers, row)))
    
    return recipients

# 邮件模板
template = """
尊敬的{姓名}:

您好!

您在{日期}的订单(订单号:{订单号})已发货,预计{预计到达}送达。

订单详情:
- 商品:{商品名称}
- 数量:{数量}
- 金额:¥{金额}

物流单号:{物流单号}

如有问题请联系客服。

祝好!
"""

# 发送
def send_merged_emails(recipients, template, smtp_config):
    for person in recipients:
        # 填充模板
        body = template.format(**person)
        
        msg = MIMEMultipart()
        msg["Subject"] = f"订单{person['订单号']}发货通知"
        msg["From"] = smtp_config["from_email"]
        msg["To"] = person["邮箱"]
        msg.attach(MIMEText(body, "plain", "utf-8"))
        
        with smtplib.SMTP_SSL(smtp_config["server"], smtp_config["port"]) as s:
            s.login(smtp_config["from_email"], smtp_config["password"])
            s.sendmail(smtp_config["from_email"], person["邮箱"], msg.as_string())
        
        print(f"已发送:{person['姓名']} ({person['邮箱']})")
        time.sleep(2)  # 控制发送频率,避免被限

# 使用
smtp_config = {
    "server": "smtp.qq.com",
    "port": 465,
    "from_email": "your@qq.com",
    "password": "授权码"
}

recipients = load_recipients("客户名单.xlsx")
send_merged_emails(recipients, template, smtp_config)

带附件的邮件合并

在这里插入图片描述

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

def send_with_attachment(person, template, attachment_path, smtp_config):
    msg = MIMEMultipart()
    msg["Subject"] = f"您的账单-{person['姓名']}"
    msg["From"] = smtp_config["from_email"]
    msg["To"] = person["邮箱"]
    
    # 正文
    body = template.format(**person)
    msg.attach(MIMEText(body, "plain", "utf-8"))
    
    # 附件
    with open(attachment_path, "rb") as f:
        part = MIMEBase("application", "octet-stream")
        part.set_payload(f.read())
        encoders.encode_base64(part)
        part.add_header(
            "Content-Disposition",
            f"attachment; filename={person['姓名']}_账单.pdf"
        )
        msg.attach(part)
    
    # 发送
    with smtplib.SMTP_SSL(smtp_config["server"], smtp_config["port"]) as s:
        s.login(smtp_config["from_email"], smtp_config["password"])
        s.sendmail(smtp_config["from_email"], person["邮箱"], msg.as_string())

错误处理与重试

def safe_send(recipients, template, smtp_config, max_retries=3):
    success = []
    failed = []
    
    for person in recipients:
        for attempt in range(max_retries):
            try:
                send_merged_emails([person], template, smtp_config)
                success.append(person)
                break
            except Exception as e:
                if attempt == max_retries - 1:
                    person["error"] = str(e)
                    failed.append(person)
                    ![在这里插入图片描述](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/98c17c04953d4e5dbfef623588bc6ace~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5p6X54SxUlBB:q75.awebp?rk3s=f64ab15b&x-expires=1786434337&x-signature=yHSYqTSWCFVNSxbXJp4lVam3jvc%3D)

                time.sleep(5)  # 等5秒再重试
        
        time.sleep(1)  # 发送间隔
    
    # 生成发送报告
    print(f"发送完成:成功{len(success)},失败{len(failed)}")
    if failed:
        with open("发送失败列表.txt", "w") as f:
            for p in failed:
                f.write(f"{p['姓名']} {p['邮箱']}: {p.get('error', '未知错误')}\n")
    
    return success, failed

踩坑实录

坑1:str.format() 和花括号冲突

如果你的邮件模板里有{}(比如JSON数据),str.format()会把它当成占位符导致报错。转义花括号:{{ 表示 {}} 表示 }

[video(video-VaNTNf1N-1784928605309)(type-csdn)(url-live.csdn.net/v/embed/524…)] 在这里插入图片描述

坑2:SMTP发送频率限制

QQ邮箱限制每小时发送量、每分钟发送量。大量发送邮件可能会触发临时封禁。建议每条间隔2-3秒,每小时不超过50封。如果量大,用企业邮箱或SendCloud等服务。

坑3:收件人邮箱无效导致发送中断

某个收件人的邮箱不存在或格式错误,整个流程会卡住。用try/except包住每条发送,记录失败的继续下一条。

在这里插入图片描述

坑4:邮件被标记为垃圾邮件

原因包括:短时间内大量发送、邮件内容包含大量链接、From地址没有SPF/DKIM记录。解决方法:

  • 发送间隔不要太密
  • 内容少用链接和图片
  • 使用企业邮箱(而非个人免费邮箱)
  • 在这里插入图片描述

写在最后

邮件合并是客户运营和内部通知的利器。影刀负责把最新数据写入Excel,Python负责读取数据并发送个性化邮件——你只需要维护好模板和数据源,剩下的全自动。 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述