在 第 1 部分,我们快速浏览了 S/MIME,查看了在多个邮件客户端中签名和加密我们的消息流的过程。 第 2 部分 向我们介绍了如何使用一个简单的命令行工具来签名和加密电子邮件,然后通过 SparkPost 发送。
在这部分中,我们将看看该工具如何适应将邮件流注入到本地平台,例如 Port25 PowerMTA 和 Momentum。
好的,开始吧!
1. 入门
安装工具、获取密钥等与之前完全相同。当您使用像 PowerMTA 或 Momentum 这样的本地电子邮件系统时,您已负责设置发送域、DKIM 密钥等。我们现在需要做的是提供某种方式,将完整格式的 S/MIME 消息注入到您的服务器中。
2. 针对 Port25 PowerMTA 的 SMTP 注入
PowerMTA 支持多种消息注入方式,包括文件“取件”目录、SMTP 和 API。这里使用的方法是 SMTP。
为了说明最简单的设置,我们将在与 PowerMTA 相同的服务器上安装 S/MIME 工具。我们将消息注入到监听器中,默认情况下它开放在 TCP 端口 25,只接受本地流量。
export SMTP_HOST=localhost
(如果您忘记了此步骤,运行时会看到:“环境变量 SMTP_HOST 未设置 – 停止” )
我们已经有发送者的私钥 (steve@thetucks.com.pem) 和接收者的公钥 (steve.tuck@sparkpost.com.crt)。消息文件的前几行是:
收件人: SteveT <steve.tuck@sparkpost.com> 发件人: Steve <steve@thetucks.com> 主题: 这是使用 HEML 创建的消息 MIME-Version: 1.0 Content-Type: text/html; charset=utf-8 Content-Language: en-GB Content-Transfer-Encoding: 7bit
我们发送消息:
./sparkpostSMIME.py tests/fancy-HTML-to-smt.eml --sign --encrypt --send_smtp
我们看到了:
已打开到 localhost 的 SMTP 连接(明文),端口 25,用户="", 密码="" 正在发送 tests/fancy-HTML-to-smt.eml 发件人: Steve <steve@thetucks.com> 收件人: SteveT <steve.tuck@sparkpost.com> OK - 用时 0.028 秒
消息很快到达收件箱,并在 Mac Mail 中报告为已签名和加密。
附加功能:与 PowerMTA 的 DKIM
DKIM 的配置相当简单,并且与 S/MIME 完美共存。步骤如下:
使用 PowerMTA DKIM 向导 网站创建发送域私钥(在我的情况下,为 mypmta.thetucks.com.pem)和公共 DNS TXT 记录内容。
设置 DNS TXT 记录,选择选择器。例如,我使用选择器 pmta201811。有效的选择器字符在 这里 定义。
将 mypmta.thetucks.com.pem 文件放在 /etc/pmta 目录的服务器上。
将以下内容添加到我的 /etc/pmta/config 中并重启 pmta 服务。(在这里,这些指令以全局范围写入;在生产系统中,您可能会倾向于在虚拟 MTA 下添加它们。)
host-name thetucks.com domain-key pmta201811,*,/etc/pmta/mypmta.thetucks.com.pem <domain *> dkim-sign 是 </domain>
DNS 记录在 MX Toolbox 上检查通过,DKIM 现在已激活。
3. 针对 Momentum 的 SMTP 注入
Momentum 支持多种消息注入方式,包括 API 和 SMTP。这里使用的方法是 SMTP,目标是已在运行 Momentum 的主机。我们将保持其配置不变,因为它已具备接受来自其他已批准主机的传入注入的能力。
这是生产设置的一个较小版本,其中“生成”节点和 MTA 节点是分开的,但通过私有 VLAN 和负载均衡器保持紧密耦合,承载内部 SMTP 注入流量。
S/MIME 工具与之前相同地安装,我们将消息注入到 SMTP 主机(MTA)的地址:
export SMTP_HOST=xx.xx.xx.xx # 在此处设置您自己的 MTA / VIP 地址
与之前一样,我们已在“生成”节点上准备好了发件人的私钥 (steve@thetucks.com.pem) 和接收者的公钥 (steve.tuck@sparkpost.com.crt)。消息文件的前几行与这些地址匹配。
我们用完全相同的命令从“生成”节点发送消息,消息出现在收件箱中。
./sparkpostSMIME.py tests/fancy-HTML-to-smt.eml --sign --encrypt --send_smtp
正如您所期待的,S/MIME 也愉快地与 Momentum 的 DKIM 签名 共存。
4. 针对 SparkPost 的 SMTP 注入
在 第 2 部分 中,我们使用 SparkPost 传输 REST API 注入消息。当然,也可以通过 SMTP 将消息注入到 SparkPost。我们这样设置环境变量:
export SMTP_PASSWORD=<<您的 API 密钥在这里>> export SMTP_HOST=smtp.sparkpostmail.com export SMTP_USER=SMTP_Injection export SMTP_PORT=587
如果您正在使用 SparkPost 欧盟托管服务,则将 SMTP_HOST 设置为 smtp.eu.sparkpostmail.com.
(请参见此处 以获取更多选项 - 例如,您可以在端口 2525 而不是 587 进行注入。)
下面的输出显示正在使用 STARTTLS,连同用户名和密码。
./sparkpostSMIME.py tests/fancy-HTML-to-smt.eml --sign --encrypt --send_smtp
您将看到:
已打开到 smtp.sparkpostmail.com 的 SMTP 连接(STARTTLS),端口 587,用户="SMTP_Injection", 密码="****************************************" 正在发送 tests/fancy-HTML-to-smt.eml 发件人: Steve <steve@thetucks.com> 收件人: SteveT <steve.tuck@sparkpost.com> OK - 用时 0.057 秒
密码使用替代的 *** 字符打印,因此如果有人在您身边看着,也不会泄露您的密钥的隐私。
保护您的凭证
请注意,环境变量可以在脚本文件或类似文件中设置,以避免重新输入。如果您这样做,请通过限制对该文件的访问仅限自己来妥善保护您的密码/API 密钥。例如,如果您的凭证设置文件名为 my_envs.sh,您可以运行:
chmod 0700 my_envs.sh
您可能看到的 SMTP 相关警告
SparkPost 的 SMTP 注入相当严格,正如您所期望的那样,作为一个公共服务。如果您没有设置 SMTP 端口号,您将看到警告:
{'bob.lumreeker@gmail.com': (550, b'5.7.1 拒绝转发')}
如果您没有设置 SMTP 用户名或没有设置密码,您将看到:
(530, b'5.7.1 需要授权。参见 https://developers.sparkpost.com/api/index#header-smtp-relay-endpoints', 'steve@thetucks.com')
这些错误消息直接由 Python SMTP 库按原样报告,因此格式化如此。
哪个更快 - SMTP 还是 API?
坦率地说,S/MIME 不太可能是高容量的用例,但拥有同一工具的两个输出选项显然是要我们进行一场竞赛!
这里使用的“牛油果”电子邮件测试文件大约为 19KB。通过 bash 循环重复测试 10 次,显示 SMTP 和 API 的平均时间相似,约为每条消息 60 毫秒,这相当快。在这种情况下,我们从与 SparkPost.com 在同一托管区域的中型 EC2 实例中注入,这是一种保持网络往返时间低的好方法。
用一个更大的测试文件(577KB)重复测试,API 大约需要 200 毫秒,而 SMTP 每条消息则需要 280 毫秒 - 对于文件大小大约 30 倍的情况,这仍然令人印象深刻。当然,根据位置、互联网拥塞等,您的情况可能会有所不同,但性能不太可能是问题。
如果您真的需要最大性能,良好的起点是根据我们的 传输最佳实践 推荐发起一定数量的并发注入过程/会话 - 例如,从一个主管任务。
总结 …
我们已看到在 第 2 部分 中使用的基于 SparkPost API 的工具被更新为支持 SMTP 注入,以支持本地 MTA,如 Port25 PowerMTA 和 Momentum 提供多种配置,以及与 SparkPost 的结合。
就这样! 祝您发送愉快。