如何在Python中发送带有发件人和收件人头部的邮件?
关于Python SMTP邮件实现的规范与优化建议
Hey there! 首先得说,你已经通过smtplib实现了带发件人/收件人头部的邮件发送,这已经迈出了关键一步👍。不过咱们来看看现有实现里可以优化的地方,让代码更规范、健壮,复用性也更高:
现有实现的几个待优化点
1. 导入语句放在函数内部
把import smtplib这类导入语句放在函数里,会导致每次调用函数都重复导入模块——这既不高效,也不符合Python的代码规范。建议把所有模块导入移到文件的最顶部。
2. Logging配置重复执行
logging.basicConfig(level=logging.DEBUG)放在函数内部,每次调用函数都会重新配置日志系统,可能导致日志重复输出,或者覆盖之前设置的日志级别。最好把日志配置移到函数外部,只在程序启动时执行一次。
3. 硬编码的邮件元数据
你把邮件主题、发件人都硬编码在函数里了,这会让函数的复用性大打折扣。比如下次要发送其他主题的邮件,就得修改函数内部代码。建议把这些作为参数传入函数。
4. 缺少异常处理与资源管理
SMTP操作很容易遇到各种问题:网络连接失败、认证错误、收件人地址无效等等。当前代码没有任何异常处理,一旦出错程序就会崩溃。另外,SMTP连接需要妥善关闭,最好用with语句自动管理连接资源。
5. 未明确SMTP认证逻辑
你的代码里看不到SMTP认证的部分,实际生产环境中几乎所有SMTP服务器都需要用户名和密码认证才能发送邮件,这部分逻辑需要补充。
优化后的示例代码
import logging import smtplib import os from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart # 全局配置日志,仅执行一次 logging.basicConfig(level=logging.DEBUG) def send_simple_message(sender, recipient, subject, mailtext, mailhtml): logging.debug(f"Mailhtml content: {mailhtml}") # 创建多部分邮件对象,指定utf-8编码避免乱码 msg = MIMEMultipart('alternative') msg['Subject'] = subject msg['From'] = sender # 处理单个/多个收件人:列表转逗号分隔字符串 if isinstance(recipient, list): msg['To'] = ', '.join(recipient) else: msg['To'] = recipient # 添加纯文本和HTML内容,指定编码 plain_part = MIMEText(mailtext, 'plain', 'utf-8') html_part = MIMEText(mailhtml, 'html', 'utf-8') msg.attach(plain_part) msg.attach(html_part) # 使用with语句自动管理SMTP连接,无需手动关闭 try: # 从环境变量读取敏感信息,避免硬编码 smtp_server = os.getenv('SMTP_SERVER', 'smtp.domain.in') smtp_port = int(os.getenv('SMTP_PORT', 587)) smtp_user = os.getenv('SMTP_USER', 'creditcards@domain.in') smtp_pass = os.getenv('SMTP_PASSWORD') with smtplib.SMTP(smtp_server, smtp_port) as server: server.starttls() # 启用TLS加密,保障传输安全 server.login(smtp_user, smtp_pass) # 发送邮件时,收件人需要是列表格式 to_recipients = recipient if isinstance(recipient, list) else [recipient] server.sendmail(sender, to_recipients, msg.as_string()) logging.info("邮件发送成功!") except smtplib.SMTPException as e: logging.error(f"SMTP相关错误:{str(e)}") except Exception as e: logging.error(f"邮件发送失败:{str(e)}") # 调用示例 send_simple_message( sender="creditcards@domain.in", recipient=["me@domain.in", "finance@domain.in"], subject="Summary of Credit Card payments due", mailtext="这是信用卡待还款汇总的纯文本版本,方便不支持HTML的邮箱查看", mailhtml="<h1>信用卡待还款汇总</h1><p>本月待还款总额:<b>¥5000</b></p>" )
额外的优化建议
- 敏感信息安全存储:永远不要把SMTP用户名、密码硬编码在代码里,用环境变量或者专门的配置文件(比如
config.ini)来存储,避免泄露。 - 支持附件扩展:如果后续需要发送附件,可以使用
email.mime.base.MIMEBase类来添加附件内容,记得设置正确的MIME类型。 - 测试环境隔离:开发阶段可以使用测试SMTP服务器(比如本地的邮件捕获工具)来测试,避免误发邮件给真实用户。
- 添加邮件头部信息:可以根据需求添加
X-Priority(优先级)、Reply-To(回复地址)等头部,让邮件功能更完善。
内容的提问来源于stack exchange,提问作者Joel G Mathew




