影刀RPA 邮件附件处理:批量发送与下载

📅 2026/7/25 6:43:34
影刀RPA 邮件附件处理:批量发送与下载
拼多多店群自动化上架方案影刀RPA 邮件附件处理批量发送与下载署名林焱什么情况用什么RPA流程中经常需要处理邮件附件——每天采集的报表自动发送给相关人员从收件箱下载附件并处理批量发送不同附件给不同收件人。场景推荐方式特点发送带附件邮件smtplib email标准库无需安装下载邮件附件imaplibIMAP协议读取批量个性化发送smtplib 模板每人不同附件怎么做一发送带附件的邮件importsmtplibfromemail.mime.multipartimportMIMEMultipartfromemail.mime.textimportMIMETextfromemail.mime.baseimportMIMEBasefromemailimportencodersimportosdefsend_email_with_attachments(smtp_server,smtp_port,sender_email,sender_password,to_emails,subject,body,attachmentsNone,is_htmlFalse):发送带附件的邮件msgMIMEMultipart()msg[From]sender_email msg[To], .join(to_emails)ifisinstance(to_emails,list)elseto_emails msg[Subject]subject# 邮件正文content_typehtmlifis_htmlelseplainmsg.attach(MIMEText(body,content_type,utf-8))# 添加附件ifattachments:forfile_pathinattachments:ifnotos.path.exists(file_path):print(f附件不存在:{file_path})continuewithopen(file_path,rb)asf:partMIMEBase(application,octet-stream)part.set_payload(f.read())encoders.encode_base64(part)part.add_header(Content-Disposition,fattachment; filename{os.path.basename(file_path)})msg.attach(part)# 发送try:serversmtplib.SMTP(smtp_server,smtp_port)server.starttls()server.login(sender_email,sender_password)server.sendmail(sender_email,to_emails,msg.as_string())server.quit()print(f邮件发送成功:{subject})returnTrueexceptExceptionase:print(f发送失败:{e})returnFalse# 使用send_email_with_attachments(smtp_serversmtp.qq.com,smtp_port587,sender_emailsenderqq.com,sender_password授权码,# 注意QQ邮箱用授权码不是密码to_emails[recipientexample.com],subject2024年6月销售报表,body请查收附件中的月度销售报表。,attachments[rD:\报表\6月销售.xlsx,rD:\报表\6月利润.pdf])二下载邮件附件importimaplibimportemailimportosfromemail.headerimportdecode_headerdefdownload_attachments(imap_server,email_addr,email_password,folderINBOX,search_criteriaALL,save_dirrD:\附件,max_emails50):下载邮件附件os.makedirs(save_dir,exist_okTrue)# 连接IMAPmailimaplib.IMAP4_SSL(imap_server)mail.login(email_addr,email_password)mail.select(folder)# 搜索邮件status,messagesmail.search(None,search_criteria)mail_idsmessages[0].split()# 只取最近的N封mail_idsmail_ids[-max_emails:]iflen(mail_ids)max_emailselsemail_ids downloaded[]formail_idinreversed(mail_ids):status,msg_datamail.fetch(mail_id,(RFC822))forresponse_partinmsg_data:ifisinstance(response_part,tuple):msgemail.message_from_bytes(response_part[1])# 获取发件人和主题subjectdecode_header_str(msg[Subject])senderdecode_header_str(msg[From])# 遍历邮件部分forpartinmsg.walk():content_dispositionstr(part.get(Content-Disposition))ifattachmentincontent_disposition:filenamepart.get_filename()iffilename:filenamedecode_header_str(filename)# 保存附件filepathos.path.join(save_dir,filename)# 处理重名base,extos.path.splitext(filename)counter1whileos.path.exists(filepath):filepathos.path.join(save_dir,f{base}_{counter}{ext})counter1withopen(filepath,wb)asf:f.write(part.get_payload(decodeTrue))downloaded.append({filename:filename,path:filepath,from:sender,subject:subject})print(f下载:{filename}(来自:{sender}))mail.logout()returndownloadeddefdecode_header_str(value):解码邮件头部字符串ifvalueisNone:returndecodeddecode_header(value)result[]forpart,charsetindecoded:ifisinstance(part,bytes):result.append(part.decode(charsetorutf-8,errorsreplace))else:result.append(part)return.join(result)# 使用attachmentsdownload_attachments(imap_serverimap.qq.com,email_addrreceiverqq.com,email_password授权码,search_criteriaSUBJECT 报表,# 只下载标题含报表的邮件save_dirrD:\附件,max_emails20)print(f共下载{len(attachments)}个附件)三批量个性化发送importsmtplibfromemail.mime.multipartimportMIMEMultipartfromemail.mime.textimportMIMETextfromemail.mime.baseimportMIMEBasefromemailimportencodersimportos# yd_input: smtp_config, recipientssmtp_configyd_input.get(smtp_config,{server:smtp.qq.com,port:587,email:senderqq.com,password:授权码})recipientsyd_input.get(recipients,[])# recipients格式: [{email: ax.com, name: 张三, attachment: D:\\报表\\张三.xlsx}, ...]success0errors[]forrecipientinrecipients:try:msgMIMEMultipart()msg[From]smtp_config[email]msg[To]recipient[email]msg[Subject]f{recipient[name]}的月度报表# 个性化正文bodyf{recipient[name]}您好 附件是您的本月数据报表请查收。 如有疑问请回复此邮件。 此邮件由RPA系统自动发送。 msg.attach(MIMEText(body,plain,utf-8))# 添加附件attachment_pathrecipient.get(attachment,)ifattachment_pathandos.path.exists(attachment_path):withopen(attachment_path,rb)asf:partMIMEBase(application,octet-stream)part.set_payload(f.read())encoders.encode_base64(part)part.add_header(Content-Disposition,fattachment; filename{os.path.basename(attachment_path)})msg.attach(part)# 发送serversmtplib.SMTP(smtp_config[server],smtp_config[port])server.starttls()server.login(smtp_config[email],smtp_config[password])server.sendmail(smtp_config[email],recipient[email],msg.as_string())server.quit()success1print(f✓{recipient[name]}{recipient[email]})exceptExceptionase:errors.append(f{recipient.get(name,unknown)}:{e})print(f✗{recipient.get(name,unknown)}:{e})yd_output{status:ok,success:success,errors:errors,total:len(recipients)}有什么坑坑一QQ邮箱/网易邮箱登录报认证失败现象用邮箱密码登录SMTP/IMAP报Authentication failed。原因QQ邮箱、网易163邮箱等需要用授权码而不是登录密码。解决在邮箱设置中开启SMTP/IMAP服务并获取授权码# QQ邮箱授权码获取方式# 1. 登录QQ邮箱网页版# 2. 设置 → 账户 → POP3/IMAP/SMTP服务 → 开启# 3. 按提示用手机发短信获取授权码# 4. 代码中用授权码代替密码# 错误用QQ登录密码# server.login(senderqq.com, qq登录密码) ❌# 正确用授权码server.login(senderqq.com,授权码)# ✓# 常见SMTP服务器# QQ邮箱: smtp.qq.com, 端口587# 163邮箱: smtp.163.com, 端口587# Gmail: smtp.gmail.com, 端口587# Outlook: smtp-mail.outlook.com, 端口587# 企业微信邮箱: smtp.exmail.qq.com, 端口465(SSL)坑二中文附件名乱码现象附件文件名是中文如销售报表.xlsx收件人看到的文件名是乱码。原因邮件标准对非ASCII文件名的处理方式特殊需要用RFC 2231编码。解决fromemail.utilsimportformataddrfromemail.headerimportHeader# 方案1用Header编码文件名filename销售报表.xlsxencoded_filenameHeader(filename,utf-8).encode()part.add_header(Content-Disposition,fattachment; filename{encoded_filename})# 方案2用RFC 2231方式part.add_header(Content-Disposition,attachment,[video(video-B5ZstbUk-1784928796160)(type-csdn)(url-https://live.csdn.net/v/embed/524993)(image-https://v-![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/1b110f986a624baa865330b6cecf452f.png#pic_center)blog.csdnimg.cn/asset/a547123d88ad712dccba346c9217e237/cover/Cover0.jpg)(title-TEMU店群如何管理运营)]filename(utf-8,,filename)# 三元组(编码, 语言, 文件名))# 方案3同时提供ASCII和UTF-8文件名兼容性最好importurllib.parse ascii_namereport.xlsx# 纯英文备用名part.add_header(Content-Disposition,fattachment; filename{ascii_name}; filename*UTF-8\\{urllib.parse.quote(filename)})坑三附件太大导致发送失败现象附件超过20MB邮件发送失败。原因大多数邮箱服务商限制单封邮件大小通常20-50MB。解决压缩附件或拆分发送importzipfileimportosdefcompress_attachments(file_paths,output_zip):压缩多个文件为zipwithzipfile.ZipFile(output_zip,w,zipfile.ZIP_DEFLATED)aszf:forfile_pathinfile_paths:zf.write(file_path,os.path.basename(file_path))returnoutput_zip# 压缩后发送files[rD:\报表\大文件1.xlsx,rD:\报表\大文件2.xlsx]zip_pathrD:\temp\报表压缩包.zipcompress_attachments(files,zip_path)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/c29927df993c49f2908d91c9b643901a.png#pic_center)# 检查压缩后大小sizeos.path.getsize(zip_path)/(1024*1024)# MBifsize20:print(f压缩后仍超过20MB ({size:.1f}MB)考虑上传到网盘分享链接)# 上传到网盘邮件中放链接else:send_email_with_attachments(...,attachments[zip_path])# 清理临时文件os.remove(zip_path)坑四IMAP读取邮件时编码混乱现象下载的附件文件名乱码或邮件主题乱码。原因邮件头部的编码方式多样Base64、Quoted-Printable等需要正确解码。解决用decode_header正确处理fromemail.headerimportdecode_headerdefsafe_decode(value):安全解码邮件头部ifvalueisNone:returnifisinstance(value,str):# 先尝试直接返回try:partsdecode_header(value)except:returnvalueelse:partsdecode_header(value)result[]![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/88009f6537724430b98f3f0dd9d415b8.png#pic_center)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/2983b890ea4c492b8d6e6891761c30a6.png#pic_center)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b6e0cf39c5024a67af617e91c807d96c.png#pic_center)forpart,charsetinparts:ifisinstance(part,bytes):# 尝试多种编码forencin[charset,utf-8,gbk,gb2312,latin-1]:ifenc:try:result.append(part.decode(enc))breakexcept(UnicodeDecodeError,LookupError):continueelse:result.append(part.decode(latin-1,errorsreplace))else:result.append(str(part))return.join(result)