You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python发送含附件邮件时,发件人含德语变音符号触发合规错误

解决Python发送带附件邮件时发件人显示名含德语变音符号的RFC合规问题

问题场景

在Windows系统使用Python 3.11发送带附件邮件时,当发件人显示名(或邮箱地址)包含德语变音符号äöü,发送服务器会提示邮件不符合RFC 5321/5322标准;移除变音符号则可正常发送。相关最小复现代码如下:

import smtplib
import ssl
from email import encoders
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

message = MIMEMultipart()
message.set_charset('utf-8')
subject = 'Support-Nr. 1'
message["Subject"] = subject
body = 'testmail 123 äöüß'
message.attach(MIMEText(body, "plain"))
filename = 'VCARD_A & B.vcf'
with open(filename, "rb") as attachment:
    part = MIMEBase("application", "octet-stream")
    part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
    "Content-Disposition",
    f"attachment; filename= {filename}",
)
message.attach(part)
sender_email = 'email1@example.com'
receiver_email = 'email2@example.com'
displayname = 'Höhne'
message["From"] = displayname + '<' + sender_email + '>'
message["To"] = receiver_email
smtplogin = # loginname
smtppassword = # passwort
smtpserver = 'smtp.ionos.de'
smtpport = 465
context = ssl._create_unverified_context()
with smtplib.SMTP_SSL(smtpserver, smtpport, context=context) as server:
    server.login(smtplogin, smtppassword)
    server.sendmail(sender_email, receiver_email, message.as_string())

问题原因

直接拼接显示名与邮箱地址作为From头,会让非ASCII字符(如ö)以原始UTF-8格式出现在邮件头中。而RFC 5321/5322明确要求,邮件头中的非ASCII字符必须按照RFC 2047标准进行编码(quoted-printable或Base64格式),否则服务器会判定邮件不合规。

解决方案

使用Python标准库email.utils中的formataddr函数构造From头,该函数会自动检测并编码非ASCII字符,确保邮件头符合RFC标准。

修改后的代码

import smtplib
import ssl
from email import encoders
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# 新增导入
from email.utils import formataddr

message = MIMEMultipart()
message.set_charset('utf-8')
subject = 'Support-Nr. 1'
message["Subject"] = subject
body = 'testmail 123 äöüß'
message.attach(MIMEText(body, "plain"))
filename = 'VCARD_A & B.vcf'
with open(filename, "rb") as attachment:
    part = MIMEBase("application", "octet-stream")
    part.set_payload(attachment.read())
encoders.encode_base64(part)
# 可选:处理附件文件名的特殊字符编码
from email.header import encode_header
encoded_filename = encode_header(filename, 'utf-8').decode()
part.add_header(
    "Content-Disposition",
    f"attachment; filename= {encoded_filename}",
)
message.attach(part)
sender_email = 'email1@example.com'
receiver_email = 'email2@example.com'
displayname = 'Höhne'
# 替换原From头构造方式
message["From"] = formataddr((displayname, sender_email))
message["To"] = receiver_email
smtplogin = # loginname
smtppassword = # passwort
smtpserver = 'smtp.ionos.de'
smtpport = 465
context = ssl._create_unverified_context()
with smtplib.SMTP_SSL(smtpserver, smtpport, context=context) as server:
    server.login(smtplogin, smtppassword)
    server.sendmail(sender_email, receiver_email, message.as_string())

关键修改点

  1. 导入email.utils.formataddr函数,用于合规构造发件人地址
  2. 将原message["From"] = displayname + '<' + sender_email + '>'替换为message["From"] = formataddr((displayname, sender_email))
  3. (可选)用email.header.encode_header处理附件文件名,避免特殊字符引发的编码问题

内容的提问来源于stack exchange,提问作者Erbs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 02:10:54