使用smtplib发送邮件时Subject不显示的问题求助
邮件主题无法显示的问题排查与解决
Hey Bijan, 我仔细看了你的代码和问题描述,咱们来一步步找出邮件主题不显示的核心原因,同时优化下代码里的其他小问题。
需求说明
我的需求是读取包含收件人邮箱、抄送邮箱、邮件主题及内容的文本文件,批量发送多封邮件。
问题描述
目前邮件可正常发送,收件人、发件人信息显示正常,但邮件主题(Subject)无法显示。调试时发现msg对象的属性已正确设置,但主题并未传递至最终发送的邮件中。我已尝试调试smtplib和ssl相关文件,仍未找到问题根源,恳请各位提供帮助。
你的原始代码
import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart import pdb def emailSender(emailId, password, input): fromaddr = emailId emailFile = open(input, "r") # open the generated email file with read only access msgTxt = "" server = smtplib.SMTP('outbound.___.com') server.starttls() server.login(fromaddr, password) for line in emailFile: if line.__contains__("$to$"): toaddr = line[4:] elif line.__contains__("$cc$"): cc = line[4:] elif line.__contains__("$bcc$"): bcc = line[5:] elif line.__contains__("$subj$"): subject = line[6:] elif line.__contains__("$%$"): msg = MIMEMultipart() msg['From'] = fromaddr msg['To'] = toaddr subject = subject.encode('utf-8') msg['Subject'] = "hello world" msg['Cc'] = cc msg.attach(MIMEText(msgTxt, 'plain')) text = msg.as_string() server.sendmail(fromaddr, toaddr, text) msgTxt = "" elif not line.__contains__("--------------------------------------------------------------------"): msgTxt += line server.quit() if __name__ == '__main__': password = "****" emailId = "****" input = "input" emailSender(emailId, password, input)
问题根源分析
我发现了两个直接导致主题不显示的问题:
- 硬编码覆盖了读取的主题:你从文件里读取了
subject变量,但最后赋值给msg['Subject']的是固定字符串"hello world",等于白读了主题内容! - 错误的编码处理:你对
subject做了encode('utf-8'),但邮件头字段需要的是字符串类型,字节对象会导致邮件头格式损坏,客户端无法解析主题。
另外还有个隐形问题:你只给server.sendmail传了toaddr,抄送和密送的邮箱不会实际收到邮件(只是邮件头显示Cc,实际没发送)。
修复后的代码
import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.header import Header # 处理非ASCII主题 def emailSender(emailId, password, input): fromaddr = emailId with open(input, "r", encoding="utf-8") as emailFile: # 用with自动关闭文件,指定编码 msgTxt = "" server = smtplib.SMTP('outbound.___.com') server.starttls() server.login(fromaddr, password) for line in emailFile: line_stripped = line.strip() # 去除每行的换行和首尾空格 if line_stripped.startswith("$to$"): toaddr = line_stripped[4:].strip() elif line_stripped.startswith("$cc$"): cc = line_stripped[4:].strip() cc_list = [addr.strip() for addr in cc.split(',')] if cc else [] elif line_stripped.startswith("$bcc$"): bcc = line_stripped[5:].strip() bcc_list = [addr.strip() for addr in bcc.split(',')] if bcc else [] elif line_stripped.startswith("$subj$"): subject = line_stripped[6:].strip() elif line_stripped.startswith("$%$"): msg = MIMEMultipart() msg['From'] = fromaddr msg['To'] = toaddr # 修复主题:使用读取到的内容,非ASCII主题用Header处理 msg['Subject'] = Header(subject, 'utf-8') if subject else "无主题" if cc: msg['Cc'] = cc msg.attach(MIMEText(msgTxt.strip(), 'plain', 'utf-8')) text = msg.as_string() # 修复抄送/密送:把所有收件人(to+cc+bcc)加入发送列表 all_recipients = [toaddr] + cc_list + bcc_list server.sendmail(fromaddr, all_recipients, text) msgTxt = "" elif "--------------------------------------------------------------------" not in line: msgTxt += line # 保留原始换行格式 server.quit() if __name__ == '__main__': password = "****" emailId = "****" input = "input" emailSender(emailId, password, input)
关键修改点
- 主题修复:去掉硬编码的
"hello world",直接使用读取的subject,如果有非英文主题,用Header类确保编码正确。 - 编码规范:打开文件时指定
utf-8编码,避免乱码;邮件正文也指定编码。 - 抄送/密送功能完善:把Cc和Bcc的邮箱加入
sendmail的收件人列表,确保这些邮箱能实际收到邮件。 - 文件操作优化:用
with语句自动管理文件,避免忘记关闭文件。 - 格式处理:去除每行的多余空格和换行,避免邮箱地址或主题带无效字符。
内容的提问来源于stack exchange,提问作者blowtorch
相关产品推荐
相关产品推荐

