python 使用smtp发送带附件的邮件
根据从网上搜索到的信息,我几乎是完成了发送邮件的主体过程,但是关于邮件附件的名称,让我陷入了难题,名称不被正确识别,并且部分邮件客户端还会不显示附件。
我知道大家不想看过程,我直接贴出解决方法:就是删除_header的第一个元素:
def main(): html_content = 组装邮件正文消息() # print(html_content) send_user = 'xxxx' receiver = ['xxxx'] cc=['xxxx',] # message=MIMEText(html_content,'html','utf-8') message=MIMEMultipart() message['From']=Header(send_user,'utf-8') # message['To']=Header(receiver,'utf-8') message['To']=','.join(receiver) message['Cc']=','.join(cc) #抄送 #邮件主题 subject="{}-xx装置-近24小时在线情况".format(datetime.datetime.now().strftime('%Y年%m月%d日')) message['Subject']=Header(subject,'utf-8') message.attach(MIMEText(html_content,'html','utf-8')) #附件 file_path = 保存离线明细数据() part=MIMEText(open(file_path,'rb').read(),'base64','utf-8') #↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓关键↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ del part._headers[0] #↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ #↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑然后解释下为啥要删除,因为它默认就生成了Content-Type属性,位于最前面,邮件客户端在读取的时候会发现两个Content-Type,会合并在一起并且对其进行解码,然后就会解码错误,有些客户端会给一个默认名称,ATT001之类,有些客户端根本不显示出来。 part.add_header('Content-Disposition','attachment', filename=f"{os.path.basename(file_path)}") part.add_header('Content-Type','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', name=f'{os.path.basename(file_path)}') #↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑我发送的是xlsx表格,我从邮件客户端将邮件原文下载下来,用文本编辑器打开发现它是使用这个类型。 message.attach(part) smtobj=smtplib.SMTP() smtobj.connect('smtp.sc.sgcc.com.cn',25) smtobj.login('gwscdky-gy-ztjc@sc.sgcc.com.cn','abcd-1235') to_addrs=receiver+cc smtobj.sendmail(send_user,to_addrs,message.as_string()) if __name__ == "__main__": main()

1 def 构造table_html代码(在线率数据:list)->str: 2 html_table='''\n <table> 3 <tr> 4 <th rowspan="2" class="tb_chinese">序号</th> 5 <th rowspan="2" class="tb_chinese">单位</th> 6 <th colspan="3" class="tb_chinese">输电</th> 7 <th colspan="3" class="tb_chinese">配电</th> 8 </tr> 9 <tr> 10 <th class="tb_chinese">装置数</th> 11 <th class="tb_chinese">在线数</th> 12 <th class="tb_chinese">在线率</th> 13 <th class="tb_chinese">装置数</th> 14 <th class="tb_chinese">在线数</th> 15 <th class="tb_chinese">在线率</th> 16 </tr>\n''' 17 idx=1 18 for data in 在线率数据: 19 try: 20 data[3] = "{:.2f}".format(float(data[3])) 21 data[3]=str(data[3])+'%' 22 except Exception as e: 23 pass 24 try: 25 data[6] = "{:.2f}".format(float(data[6])) 26 data[6]=str(data[6])+'%' 27 except Exception as e: 28 pass 29 if(data[0] != '总计'): 30 code_line = """ <tr> 31 <td class="tb_number">{}</td><td class="tb_chinese">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td> 32 </tr>\n""".format(idx,data[0],data[1],data[2],data[3],data[4],data[5],data[6]) 33 idx+=1 34 else: 35 code_line = """ <tr> 36 <td colspan="2" class="tb_chinese">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td><td class="tb_number">{}</td> 37 </tr>\n""".format(data[0],data[1],data[2],data[3],data[4],data[5],data[6]) 38 html_table+=code_line 39 html_table+='</table>\n' 40 return html_table; 41 def 组装邮件正文消息(): 42 在线率数据=重整在线率列表(获取在线率数据()) 43 总计= 在线率数据[-1] 44 总体情况="""<p class="chinese">截至{}<span class="number">14</span>点整,输配电线路共计接入导线覆冰检测装置<span class="number">{}</span>套,输电在线率为<span class="number">{:.2f}%</span>""".format(datetime.datetime.now().strftime("<span class=\"number\">%Y</span>年<span class=\"number\">%m</span>月<span class=\"number\">%d</span>日"),(int(总计[1])+int(总计[4])),float(总计[3])) 45 主网_确定是否有低于百分之九十的地市=确定是否有低于百分之九十的地市(在线率数据,False) 46 if(not 主网_确定是否有低于百分之九十的地市[0]): 47 总体情况+='。' 48 else: 49 总体情况+=",{}在线率较低。".format("、".join([data[0] for data in 主网_确定是否有低于百分之九十的地市[1]])) 50 配网_确定是否有低于百分之九十的地市=确定是否有低于百分之九十的地市(在线率数据,True) 51 if(not 配网_确定是否有低于百分之九十的地市[0]): 52 总体情况+='配电在线率为<span class="number">{:.2f}%<span>。'.format(float(总计[-1])) 53 else: 54 总体情况+='配电在线率为<span class="number">{:.2f}%<span>,{}在线率较低。'.format(float(总计[-1]),"、".join([data[0] for data in 配网_确定是否有低于百分之九十的地市[1]])) 55 在线率数据_html=构造table_html代码(在线率数据) 56 html_content=""" 57 <html> 58 <head> 59 <style> 60 h1 {{ 61 font-family: "SimHei", "Arial", sans-serif; /* 黑体(SimHei) */ 62 font-size: 16pt; /* 三号字体 */ 63 font-weight: bold; /* 加粗 */ 64 text-align: left; 65 }} 66 p{{ 67 font-size: 16pt; /* 三号字体 */ 68 text-indent: 4em; /* 缩进2字符 */ 69 }} 70 .chinese {{ 71 font-family: "FangSong", "仿宋", serif; /* 仿宋 */ 72 font-size: 16pt; /* 三号字体 */ 73 text-indent: 2em; /* 缩进2字符 */ 74 }} 75 /* 控制英文和数字的字体 */ 76 .number {{ 77 font-family: "Times New Roman", Times, serif; /* Times New Roman */ 78 font-size: 16pt; /* 三号字体 */ 79 }} 80 .tb_chinese {{ 81 font-family: "FangSong", "仿宋", serif; /* 仿宋 */ 82 font-size: 12pt; /* 小四字号 */ 83 font-weight: normal; /* 常规 */ 84 }} 85 .tb_number {{ 86 font-family: "Times New Roman", Times, serif; /* Times New Roman */ 87 font-size: 12pt; /* 小四字号 */ 88 }} 89 table {{ 90 border-collapse: collapse; /* 边框合并 */ 91 width: auto; /* 自动调整宽度 */ 92 margin-left: 0; /* 左对齐 */ 93 }} 94 th, td {{ 95 border: 1px solid #ccc; /* 边框宽度 */ 96 text-align: center; /* 水平居中 */ 97 padding: 5px; /* 内边距 */ 98 vertical-align: middle; /* 垂直居中 */ 99 }} 100 </style> 101 </head> 102 <body> 103 <h1>一、总体情况</h1> 104 <!-- 总体情况 --> 105 {} 106 <br> 107 {} 108 <br> 109 <h1>二、离线装置明细</h1> 110 <p class="chinese">装置离线明细请见附件。</p> 111 <br> 112 </body> 113 </html> 114 """.format(总体情况,在线率数据_html) 115 return html_content;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?