Python 邮件发送
Python: 使用 SMTP 发送电子邮件
Section titled “Python: 使用 SMTP 发送电子邮件”简单邮件传输协议(SMTP)是用于发送电子邮件的标准互联网协议。Python 的内置 smtplib 模块提供了客户端功能,用于连接到 SMTP 服务器并发送电子邮件。
为了健壮地构建电子邮件消息(处理头部信息、不同内容类型、附件),强烈推荐使用标准的 email.message 模块,而不是手动进行字符串格式化。
连接到 SMTP 服务器
Section titled “连接到 SMTP 服务器”您可以使用 smtplib.SMTP 或 smtplib.SMTP_SSL(对于需要一开始就使用 SSL 连接的服务器)创建一个 SMTP 客户端会话对象。尽可能使用加密连接(SSL/TLS)至关重要。
import smtplib
# 选项 1: 连接标准 SMTP 端口,然后升级到 TLS# smtp_server = smtplib.SMTP(host, port)# smtp_server.starttls() # 保护连接
# 选项 2: 直接使用 SSL 连接# smtp_server = smtplib.SMTP_SSL(host, port)
# Gmail 示例 (如果启用了两步验证,需要应用专用密码)# host = 'smtp.gmail.com'# port = 465 # 用于 SSL# smtp_server = smtplib.SMTP_SSL(host, port)
# 本地调试服务器示例 (无加密)# python -m smtpd -c DebuggingServer -n localhost:1025# smtp_server = smtplib.SMTP('localhost', 1025)SMTP() / SMTP_SSL() 的参数:
连接后,通常需要进行身份验证:
# smtp_server.login(sender_email, password)安全提示: 避免在脚本中直接硬编码凭据。请使用环境变量、配置文件或安全的秘密管理工具。
发送简单文本电子邮件
Section titled “发送简单文本电子邮件”使用 email.message.EmailMessage 类构建电子邮件结构。
import smtplibimport osfrom email.message import EmailMessage
# --- 配置 (安全加载,例如从环境变量) ---SMTP_HOST = 'smtp.example.com' # 替换为您的 SMTP 主机SMTP_PORT = 587 # 替换为您的 SMTP 端口 (TLS)SENDER_EMAIL = 'your_email@example.com' # 替换SENDER_PASSWORD = os.environ.get('EMAIL_PASSWORD') # 示例: 从环境变量获取RECEIVER_EMAIL = 'recipient@example.com' # 替换# --------------------------------------------------------------------
if not SENDER_PASSWORD: print("Error: 环境变量 EMAIL_PASSWORD 中未设置邮箱密码") exit()
# 创建邮件消息对象msg = EmailMessage()msg['Subject'] = 'Test Email from Python'msg['From'] = SENDER_EMAILmsg['To'] = RECEIVER_EMAILmsg.set_content('This is a plain text email sent using Python.')
try: # 连接,登录,并发送 with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.starttls() # 保护连接 (如果使用端口 587) server.login(SENDER_EMAIL, SENDER_PASSWORD) server.send_message(msg) print("电子邮件发送成功!")
except smtplib.SMTPAuthenticationError: print("认证失败。请检查邮箱/密码或应用专用密码设置。")except smtplib.SMTPException as e: print(f"发生 SMTP 错误: {e}")except Exception as e: print(f"发生错误: {e}")关键步骤:
发送 HTML 电子邮件
Section titled “发送 HTML 电子邮件”要发送 HTML 内容,使用 msg.add_alternative()。
import smtplibimport osfrom email.message import EmailMessage
# --- 配置 (同上) ---SMTP_HOST = 'smtp.example.com'SMTP_PORT = 587SENDER_EMAIL = 'your_email@example.com'SENDER_PASSWORD = os.environ.get('EMAIL_PASSWORD')RECEIVER_EMAIL = 'recipient@example.com'# ----------------------------------
if not SENDER_PASSWORD: print("Error: 未设置邮箱密码。") exit()
msg = EmailMessage()msg['Subject'] = 'HTML Email Test from Python'msg['From'] = SENDER_EMAILmsg['To'] = RECEIVER_EMAIL
# 设置纯文本内容 (客户端不支持 HTML 时的备用)msg.set_content('这是纯文本版本。')
# 添加 HTML 备用html_content = """<html> <body> <p>这是一封 **HTML** 电子邮件。</p> <h1>标题</h1> <p>使用 Python 的 <code>smtplib</code> 和 <code>email.message</code> 模块发送。</p> </body></html>"""msg.add_alternative(html_content, subtype='html')
try: with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.starttls() server.login(SENDER_EMAIL, SENDER_PASSWORD) server.send_message(msg) print("HTML 电子邮件发送成功!")except Exception as e: print(f"发生错误: {e}")add_alternative() 添加了相同内容的不同表示形式。电子邮件客户端通常会显示它们支持的最丰富格式(本例中是 HTML)。提供纯文本备用是良好的实践。
发送带附件的电子邮件
Section titled “发送带附件的电子邮件”使用 msg.add_attachment() 包含文件。
import smtplibimport osfrom email.message import EmailMessageimport mimetypes # 用于猜测文件类型
# --- 配置 (同上) ---SMTP_HOST = 'smtp.example.com'SMTP_PORT = 587SENDER_EMAIL = 'your_email@example.com'SENDER_PASSWORD = os.environ.get('EMAIL_PASSWORD')RECEIVER_EMAIL = 'recipient@example.com'# ----------------------------------
if not SENDER_PASSWORD: print("Error: 未设置邮箱密码。") exit()
ATTACHMENT_PATH = 'files/document.pdf' # 替换为您的文件路径
if not os.path.exists(ATTACHMENT_PATH): print(f"Error: 未找到附件文件 {ATTACHMENT_PATH}") exit()
msg = EmailMessage()msg['Subject'] = 'Email with Attachment from Python'msg['From'] = SENDER_EMAILmsg['To'] = RECEIVER_EMAILmsg.set_content('请查阅附件中的文档。')
# --- 添加附件 ---# 猜测 MIME 类型mime_type, _ = mimetypes.guess_type(ATTACHMENT_PATH)if mime_type is None: # 如果无法猜测类型,默认为通用二进制 mime_type = 'application/octet-stream'maintype, subtype = mime_type.split('/', 1)
with open(ATTACHMENT_PATH, 'rb') as fp: # 以二进制模式读取文件内容并添加为附件 msg.add_attachment(fp.read(), maintype=maintype, subtype=subtype, filename=os.path.basename(ATTACHMENT_PATH))# ---------------------
try: with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server: server.starttls() server.login(SENDER_EMAIL, SENDER_PASSWORD) server.send_message(msg) print("成功发送带附件的电子邮件!")except Exception as e: print(f"发生错误: {e}")附件的关键步骤: