影刀RPA 邮件发送的自动化:从简单文本到HTML模板
影刀RPA 邮件发送的自动化从简单文本到HTML模板作者林焱发邮件是RPA流程里最常见的收尾动作——采集完数据发邮件、生成报表发邮件、出错报警发邮件。但很多人写邮件自动化时卡在附件发不出去、中文标题乱码、HTML邮件排版难看、邮箱认证失败。这篇文章从简单到复杂讲清楚影刀RPA里邮件发送的完整方案。一、什么情况用什么场景推荐方案说明简单通知邮件纯文本邮件最简单几行代码搞定带表格的报表邮件HTML邮件表格排版好看带附件的邮件multipart邮件支持任意文件附件群发邮件抄送/密送设置cc/bcc适合通知多人定时日报邮件模板变量替换每天自动生成不同内容个性化群发逐个发送每人不同内容带图片的邮件HTML内嵌图片图片直接显示在邮件里二、怎么做2.1 最简单的纯文本邮件importsmtplibfromemail.mime.textimportMIMETextdefsend_simple_email(smtp_host,port,sender,password,receiver,subject,body):发送纯文本邮件msgMIMEText(body,plain,utf-8)msg[From]sender msg[To]receiver msg[Subject]subjecttry:serversmtplib.SMTP(smtp_host,port)server.starttls()server.login(sender,password)server.sendmail(sender,[receiver],msg.as_string())server.quit()print(邮件发送成功)returnTrueexceptExceptionase:print(f发送失败:{e})returnFalse# QQ邮箱示例使用授权码不是密码# send_simple_email(# smtp.qq.com, 587,# your_emailqq.com, your_auth_code,# receiverexample.com,# RPA流程完成通知,# 商品采集流程已执行完成共采集50条数据。# )常见SMTP服务器配置拼多多店群自动化报活动上架邮箱SMTP服务器端口说明QQ邮箱smtp.qq.com587用授权码163邮箱smtp.163.com587用授权码Gmailsmtp.gmail.com587用应用专用密码| Outlook | smtp.office365.com | 587 | 用账号密码 || 企业微信邮箱 | smtp.exmail.qq.com | 465 | SSL连接 |2.2 HTML邮件带表格importsmtplibfromemail.mime.textimportMIMETextfromdatetimeimportdatetimedefsend_html_email(smtp_host,port,sender,password,receiver,subject,html_content):发送HTML邮件msgMIMEText(html_content,html,utf-8)msg[From]sender msg[To]receiver msg[Subject]subjecttry:serversmtplib.SMTP(smtp_host,port)server.starttls()server.login(sender,password)server.sendmail(sender,[receiver],msg.as_string())server.quit()print(HTML邮件发送成功)returnTrueexceptExceptionase:print(f发送失败:{e})returnFalse# 生成HTML表格defbuild_report_html(title,data_rows,headers):构建HTML报表rows_htmlforrowindata_rows:cells.join(ftd stylepadding:8px;border:1px solid #ddd;{cell}/tdforcellinrow)rows_htmlftr{cells}/trheader_html.join(fth stylepadding:8px;border:1px solid #ddd;background:#f5f5f5;text-align:left;{h}/thforhinheaders)htmlf html body stylefont-family: Microsoft YaHei, Arial, sans-serif; color: #333; h2 stylecolor: #1890ff;{title}/h2 p stylecolor: #666; font-size: 14px;生成时间:{datetime.now().strftime(%Y-%m-%d %H:%M:%S)}/p table styleborder-collapse: collapse; width: 100%; margin: 20px 0; thead tr{header_html}/tr /thead tbody{rows_html}/tbody /table hr styleborder: none; border-top: 1px solid #eee; margin: 20px 0; p stylecolor: #999; font-size: 12px;此邮件由RPA流程自动发送请勿回复。/p /body /html returnhtml# 使用示例# headers [商品名称, 价格, 库存, 状态]# data [# [商品A, ¥99, 500, 在售],# [商品B, ¥199, 0, 缺货],# [商品C, ¥59, 120, 在售],# ]# html build_report_html(商品采集日报, data, headers)# send_html_email(smtp.qq.com, 587, youqq.com, auth_code, bosscompany.com, 商品采集日报, html)2.3 带附件的邮件importsmtplibfromemail.mime.textimportMIMETextfromemail.mime.multipartimportMIMEMultipartfromemail.mime.applicationimportMIMEApplicationimportosdefsend_email_with_attachments(smtp_host,port,sender,password,receiver,subject,body,attachmentsNone,ccNone):发送带附件的邮件msgMIMEMultipart()msg[From]sender msg[To]receiverifcc:msg[Cc]cc msg[Subject]subject# 邮件正文msg.attach(MIMEText(body,html,utf-8))# 添加附件ifattachments:forfile_pathinattachments:ifnotos.path.exists(file_path):print(f附件不存在跳过:{file_path})continuewithopen(file_path,rb)asf:attachmentMIMEApplication(f.read())# 设置附件文件名处理中文文件名filenameos.path.basename(file_path)attachment.add_header(Content-Disposition,attachment,filename(utf-8,,filename))msg.attach(attachment)print(f附件已添加:{filename})# 发送receivers[receiver]ifcc:receivers.extend(cc.split(,))try:serversmtplib.SMTP(smtp_host,port)server.starttls()server.login(sender,password)server.sendmail(sender,receivers,msg.as_string())server.quit()print(f邮件发送成功收件人:{receivers})returnTrueexceptExceptionase:print(f发送失败:{e})returnFalse# 使用示例# send_email_with_attachments(# smtp.qq.com, 587, youqq.com, auth_code,# bosscompany.com,# 周报,# h2本周工作周报/h2p详见附件。/p,# attachments[rD:\report\weekly_report.xlsx, rD:\report\chart.png],# cccolleaguecompany.com# )2.4 邮件模板系统每次发邮件都要重写HTML太麻烦。做一个模板系统只替换变量importosfromdatetimeimportdatetimeclassEmailTemplate:邮件模板管理# 日报模板DAILY_REPORT html body stylefont-family: Microsoft YaHei, Arial, sans-serif; color: #333; h2 stylecolor: #1890ff; {{title}}/h2 p stylecolor: #666;日期: {{date}}/p div stylebackground: #f6f8fa; padding: 15px; border-radius: 5px; margin: 15px 0; h3 stylemargin-top: 0;执行概要/h3 ul li流程状态: strong stylecolor: {{status_color}};{{status}}/strong/li li执行耗时: {{duration}}/li li处理数据量: {{data_count}} 条/li li成功率: {{success_rate}}%/li /ul /div {{table_html}} {{error_section}} hr styleborder: none; border-top: 1px solid #eee; margin: 20px 0; p stylecolor: #999; font-size: 12px;此邮件由RPA流程自动发送 | {{send_time}}/p /body /html # 错误报警模板ERROR_ALERT html body stylefont-family: Microsoft YaHei, Arial, sans-serif; color: #333; h2 stylecolor: #ff4d4f;⚠️ 流程异常报警/h2 div stylebackground: #fff2f0; padding: 15px; border-left: 4px solid #ff4d4f; margin: 15px 0; pstrong流程名称:/strong {{flow_name}}/p pstrong发生时间:/strong {{error_time}}/p pstrong错误信息:/strong/p pre stylebackground: #f5f5f5; padding: 10px; overflow-x: auto; font-size: 13px;{{error_message}}/pre /div p stylecolor: #666;请及时检查并处理。/p hr styleborder: none; border-top: 1px solid #eee; margin: 20px 0; p stylecolor: #999; font-size: 12px;RPA自动报警系统 | {{send_time}}/p /body /html classmethoddefrender(cls,template,**kwargs):渲染模板resulttemplateforkey,valueinkwargs.items():resultresult.replace(f{{{{{key}}}}},str(value))returnresult# 使用示例日报# html EmailTemplate.render(# EmailTemplate.DAILY_REPORT,# title商品采集日报,# datedatetime.now().strftime(%Y-%m-%d),# status成功 if success else 失败,# status_color#52c41a if success else #ff4d4f,# duration3分20秒,# data_count50,# success_rate96,# table_htmlp详见附件/p,# error_section,# send_timedatetime.now().strftime(%Y-%m-%d %H:%M:%S)# )# 使用示例错误报警# html EmailTemplate.render(# EmailTemplate.ERROR_ALERT,# flow_name商品采集_v3,# error_timedatetime.now().strftime(%Y-%m-%d %H:%M:%S),# error_messageTimeoutError: 翻页采集第3页时超时\n请检查网络连接,# send_timedatetime.now().strftime(%Y-%m-%d %H:%M:%S)# )2.5 HTML内嵌图片有时候需要把图片直接显示在邮件正文里不是附件importsmtplibfromemail.mime.textimportMIMETextfromemail.mime.multipartimportMIMEMultipartfromemail.mime.imageimportMIMEImageimportosdefsend_email_with_inline_image(smtp_host,port,sender,password,receiver,subject,html_body,image_path,image_cidreport_chart):发送带内嵌图片的HTML邮件msgMIMEMultipart(related)msg[From]sender msg[To]receiver msg[Subject]subject# HTML正文引用图片用cid:html_with_imagehtml_body.replace(f{{{{image}}}},fcid:{image_cid})msg.attach(MIMEText(html_with_image,html,utf-8))# 添加图片ifos.path.exists(image_path):withopen(image_path,rb)asf:imgMIMEImage(f.read())img.add_header(Content-ID,f{image_cid})img.add_header(Content-Disposition,inline,filenameos.path.basename(image_path))msg.attach(img)print(f图片已内嵌:{image_path})else:print(f图片不存在:{image_path})try:serversmtplib.SMTP(smtp_host,port)server.starttls()server.login(sender,password)server.sendmail(sender,[receiver],msg.as_string())server.quit()print(邮件发送成功)returnTrueexceptExceptionase:print(f发送失败:{e})returnFalse# HTML模板里用 {{image}} 引用图片位置# html # htmlbody# h2销售趋势图/h2# img src{{image}} stylemax-width: 600px;/# /body/html# # send_email_with_inline_image(# smtp.qq.com, 587, youqq.com, auth_code,# bosscompany.com, 销售周报,# html, rD:\charts\sales_trend.png# )三、有什么坑坑1QQ邮箱/163邮箱认证失败用登录密码直接连SMTP会报认证失败。QQ和163邮箱要求使用授权码。解决登录QQ邮箱→设置→账户→开启SMTP服务生成授权码代码里用授权码代替密码坑2中文附件名乱码直接用中文文件名作为附件有些邮箱客户端显示乱码。解决用编码方式设置文件名fromemail.utilsimportformataddrfromemail.headerimportHeader# 正确设置中文附件名attachment.add_header(Content-Disposition,attachment,filename(utf-8,,中文文件名.xlsx))坑3SSL连接 vs STARTTLS有些邮箱用465端口SSL有些用587端口STARTTLS。搞混了连不上。TEMU店群矩阵自动化运营核价报活动# 465端口SSL直连serversmtplib.SMTP_SSL(smtp_host,465)server.login(sender,password)# 587端口STARTTLSserversmtplib.SMTP(smtp_host,587)server.starttls()server.login(sender,password)坑4附件太大发送失败大多数邮箱对附件大小有限制QQ邮箱50MBGmail 25MB。解决大文件先压缩或者上传到网盘后在邮件里放链接importzipfileimportosdefcompress_files(file_paths,zip_path):压缩文件withzipfile.ZipFile(zip_path,w,zipfile.ZIP_DEFLATED)aszf:forfile_pathinfile_paths:ifos.path.exists(file_path):zf.write(file_path,os.path.basename(file_path))original_sizesum(os.path.getsize(f)forfinfile_pathsifos.path.exists(f))zip_sizeos.path.getsize(zip_path)print(f原始:{original_size/1024/1024:.1f}MB → 压缩:{zip_size/1024/1024:.1f}MB)returnzip_path坑5群发邮件被判定为垃圾邮件短时间内发大量邮件或者邮件内容有敏感词可能被邮箱服务商限制。解决控制发送频率每次间隔几秒群发用密送BCC收件人看不到其他人地址避免标题和内容有广告类关键词defsend_batch_emails(smtp_config,email_list,interval5):批量发送邮件带间隔importtime success_count0fori,email_datainenumerate(email_list):print(f[{i1}/{len(email_list)}] 发送给:{email_data[receiver]})resultsend_simple_email(smtp_config[host],smtp_config[port],smtp_config[sender],smtp_config[password],email_data[receiver],email_data[subject],email_data[body])ifresult:success_count1# 间隔等待ifilen(email_list)-1:time.sleep(interval)print(f发送完成:{success_count}/{len(email_list)}成功)总结邮件自动化的核心要点用授权码不用密码——QQ/163邮箱都用授权码HTML邮件用模板——写一次模板每次只换变量中文文件名要编码——否则附件名乱码大文件先压缩——避免超过邮箱附件限制批量发送加间隔——防止被判定为垃圾邮件

相关新闻

影刀RPA 进程与窗口管理:系统级操作

影刀RPA 进程与窗口管理:系统级操作

影刀RPA 进程与窗口管理:系统级操作 作者:林焱 写RPA流程时,经常需要和系统打交道:启动一个外部程序、关闭卡死的进程、切换到指定窗口、等待某个程序启动完成。这些操作超出了网页自动化的范围,需要用到Windows系统级…

2026/7/25 7:17:08 阅读更多 →
如何高效使用Zotero PDF翻译插件:学术研究的终极翻译解决方案

如何高效使用Zotero PDF翻译插件:学术研究的终极翻译解决方案

如何高效使用Zotero PDF翻译插件:学术研究的终极翻译解决方案 【免费下载链接】zotero-pdf-translate Translate PDF, EPub, webpage, metadata, annotations, notes to the target language. Support 20 translate services. 项目地址: https://gitcode.com/gh_m…

2026/7/25 7:17:08 阅读更多 →
AI技术如何变革教材编写:降查重与提效实战

AI技术如何变革教材编写:降查重与提效实战

1. 教材编写行业的痛点与变革契机教材编写这个行当,干了十几年的人都知道有多折磨人。传统编写流程就像在走钢丝:既要保证内容权威性,又要控制查重率;既要符合教学大纲,又要体现创新性。我见过太多团队花半年时间写出来…

2026/7/25 7:16:07 阅读更多 →

最新新闻

现代C++并发编程实战:用锁排序策略优雅解决哲学家就餐问题

现代C++并发编程实战:用锁排序策略优雅解决哲学家就餐问题

1. 项目概述:从经典难题到现代C的优雅解法 哲学家就餐问题,这个在操作系统和并发编程教材里躺了快半个世纪的经典死锁案例,估计每个学过计算机的朋友都绕不开。我第一次接触它是在大学课堂,老师用一堆晦涩的伪代码和流程图讲得云里…

2026/7/25 7:31:12 阅读更多 →
C++仿函数与Lambda:从STL算法到现代回调机制的核心技术

C++仿函数与Lambda:从STL算法到现代回调机制的核心技术

1. 项目概述:为什么我们需要“仿函数”?在C的日常开发里,尤其是当你开始接触标准库算法(STL)时,std::sort、std::for_each、std::transform这些函数你一定不陌生。它们的强大之处在于,你可以传递…

2026/7/25 7:31:12 阅读更多 →
LoRA与PEFT技术:消费级显卡微调大模型实战

LoRA与PEFT技术:消费级显卡微调大模型实战

1. 项目概述:当大模型遇上消费级显卡三年前训练一个基础语言模型需要数十张专业计算卡,如今借助LoRA(Low-Rank Adaptation)和PEFT(Parameter-Efficient Fine-Tuning)技术,在单张消费级显卡上就能…

2026/7/25 7:31:12 阅读更多 →
知识增强深度学习:原理、方法与应用实践

知识增强深度学习:原理、方法与应用实践

1. 知识增强深度学习概述知识增强深度学习(Knowledge-Augmented Deep Learning, KADL)是近年来兴起的一种新型人工智能范式,它通过将结构化知识注入深度学习模型,显著提升了模型的可解释性和推理能力。我在实际研究中发现&#xf…

2026/7/25 7:31:12 阅读更多 →
基于大数据爬虫+Hadoop的明星社交媒体影响力数据挖掘平台任务书

基于大数据爬虫+Hadoop的明星社交媒体影响力数据挖掘平台任务书

一、课题研究背景与意义 当前新媒体社交行业飞速发展,微博、抖音、小红书等社交媒体平台汇聚了海量明星相关动态、用户互动、舆论评论等数据,明星社交媒体影响力已成为流量评估、商业代言、粉丝运营、舆情管控的核心依据。明星社交数据具有更新快、体量巨…

2026/7/25 7:31:12 阅读更多 →
手机号码定位查询系统:3分钟掌握免费手机归属地查询技巧

手机号码定位查询系统:3分钟掌握免费手机归属地查询技巧

手机号码定位查询系统:3分钟掌握免费手机归属地查询技巧 【免费下载链接】location-to-phone-number This a project to search a location of a specified phone number, and locate the map to the phone number location. 项目地址: https://gitcode.com/gh_mi…

2026/7/25 7:30:11 阅读更多 →

日新闻

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是为了解决您的…

2026/7/25 0:00:35 阅读更多 →
C++ string类模拟实现:从深拷贝到内存管理的完整指南

C++ string类模拟实现:从深拷贝到内存管理的完整指南

1. 项目概述:为什么我们要“手撕”string类?在C的学习道路上,尤其是从C语言过渡到C的“初阶”阶段,string类绝对是一个绕不开的核心。标准库里的std::string用起来太方便了,、find、substr,几个操作符和函数…

2026/7/25 0:00:35 阅读更多 →
三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

1. 先搞清楚“三角洲寻宝鼠”到底是什么工具从名称来看,“三角洲寻宝鼠”更像是一个资源查找或文件检索类工具,而不是游戏或娱乐软件。这类工具的核心价值在于帮助用户快速定位特定资源,比如文档、图片、压缩包或特定格式的文件。如果你经常需…

2026/7/25 0:00:35 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/25 5:08:22 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/25 5:13:53 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 18:52:18 阅读更多 →

月新闻