Python内置的email
库存在更多问题。如果调用as_string
程序,则仅在当前类和子类(_payload
)中扫描标题以获取maxlinelength
!就像这样:
msgRoot (You call `to_string` during sending to smtp and headers will be checked)
->msgMix (headers will be not checked for maxlinelength)
-->msgAlt (headers will be not checked for maxlinelength)
--->msgText (headers will be not checked for maxlinelength)
--->msgHtml (headers will be not checked for maxlinelength)
-->msgSign (headers will be not checked for maxlinelength)
我已经签署了 msgMix.to_string()
,然后将签名的消息附加到 msgRoot
。但是在发送到 SMTP 时,msgMix
部分有所不同,msgMix
中的头部没有被分块。当然,签名是无效的。
我花了两天时间来理解一切... 这是我的代码,它可以用于发送自动邮件:
import smtplib, gnupg
from email import Charset, Encoders
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.message import Message
from email.generator import _make_boundary
EMAIL_SMTP = "localhost"
EMAIL_FROM = "Fusion Wallet <no-reply@fusionwallet.io>"
EMAIL_RETURN = "Fusion Wallet Support <support@fusionwallet.io>"
addr = 'some_target_email@gmail.com'
subject = 'test'
html = '<b>test</b>'
txt = 'test'
Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8')
msgTEXT = MIMEText(txt, 'plain', 'UTF-8')
msgHTML = MIMEText(html, 'html', 'UTF-8')
msgRoot = MIMEMultipart(_subtype="signed", micalg="pgp-sha512", protocol="application/pgp-signature")
msgMix = MIMEMultipart('mixed')
msgAlt = MIMEMultipart('alternative')
msgSIGN = Message()
msgOWNKEY = MIMEBase('application', "octet-stream")
msgRoot.add_header('From', EMAIL_FROM)
msgRoot.add_header('To', addr)
msgRoot.add_header('Reply-To', EMAIL_FROM)
msgRoot.add_header('Reply-Path', EMAIL_RETURN)
msgRoot.add_header('Subject', subject)
msgMix.add_header('From', EMAIL_FROM)
msgMix.add_header('To', addr)
msgMix.add_header('Reply-To', EMAIL_FROM)
msgMix.add_header('Reply-Path', EMAIL_RETURN)
msgMix.add_header('Subject', subject)
msgMix.add_header('protected-headers', 'v1')
ownKey = gpg.export_keys('6B6C0EBB6DC42AA4')
if ownKey:
msgOWNKEY.add_header("Content-ID", "<0x6B6C0EBB.asc>")
msgOWNKEY.add_header("Content-Disposition", "attachment", filename='0x6B6C0EBB.asc')
msgOWNKEY.set_payload(ownKey)
msgAlt.attach(msgTEXT)
msgAlt.attach(msgHTML)
msgMix.attach(msgAlt)
if ownKey:
msgMix.attach(msgOWNKEY)
gpg = gnupg.GPG()
msgSIGN.add_header('Content-Type', 'application/pgp-signature; name="signature.asc"')
msgSIGN.add_header('Content-Description', 'OpenPGP digital signature')
msgSIGN.add_header("Content-Disposition", "attachment", filename='signature.asc')
originalSign = gpg.sign(msgMix.as_string().replace('\n', '\r\n').strip()).data
spos = originalSign.index('-----BEGIN PGP SIGNATURE-----')
sign = originalSign[spos:]
msgSIGN.set_payload(sign)
msgRoot.set_boundary(_make_boundary(msgMix.as_string()))
msgRoot.set_payload(
"--%(boundary)s\n%(mix)s--%(boundary)s\n%(sign)s\n--%(boundary)s--\n" % {
'boundary':msgRoot.get_boundary(),
'mix':msgMix.as_string(),
'sign':msgSIGN.as_string(),
}
)
s = smtplib.SMTP(EMAIL_SMTP)
s.sendmail(EMAIL_FROM, addr, msgRoot.as_string())
s.quit()
email.generator
,我没有找到其他方法。 - Dmitry Shachnev