Reach

Grow

Manage

Automate

Reach

Grow

Manage

Automate

S/MIME 第 4 部分:通过 SparkPost 入站中继 Webhook 轻松收集收件人公钥

2019年2月1日

电子邮件

1 min read

S/MIME 第 4 部分:通过 SparkPost 入站中继 Webhook 轻松收集收件人公钥

2019年2月1日

电子邮件

1 min read

S/MIME 第 4 部分:通过 SparkPost 入站中继 Webhook 轻松收集收件人公钥

在这个系列中,我们已经看到,包含 S/MIME 签名是相当直接的。发送 S/MIME 加密邮件则更复杂,因为您需要获取收件人的公钥。当您使用像 Thunderbird 这样的电子邮件客户端时,这是一回事,但应用程序生成的电子邮件流又如何运作呢?

part 1中,我们快速浏览了S/MIME,查看了在各种邮件客户端中签署和加密我们的消息流。Part 2带我们通过一个简单的命令行工具签署和加密电子邮件,然后通过SparkPost发送它们。Part 3展示了如何将安全邮件流注入到诸如Port25 PowerMTAMomentum之类的本地平台中。

在这个系列中,我们看到包含S/MIME签名是相当简单的。发送S/MIME加密邮件更复杂,因为你需要获得收件人的公钥。当你使用像Thunderbird这样的邮件客户端时,那是一回事——但应用生成的电子邮件流如何工作呢?应用生成的电子邮件,如用于约会平台的那些,需要睿智的策略来最大化参与度。看看约会应用如何创建引人入胜的触发邮件体验

但等等——进入Mordor获取那些密钥还有另一种方法。你的服务可以邀请你的客户(当然是通过邮件)给你发回一封未签名邮件到一个已知的客户服务地址。使用SparkPost Inbound Relay webhooks的神奇功能,我们将提取并存储供你使用的公钥。

我们可以将这总结为一个简单的用例:

  • 作为消息的接收者,我提供你的服务我的个人电子邮件签名,以便将来可以以S/MIME加密形式向我发送邮件。

从这里,我们来推导一些更详细的需求:

  • 我们需要一个始终在线的可靠入站电子邮件服务来接收这些签名电子邮件。

  • 邮件格式不应有特殊要求,除了它应该包含S/MIME签名。

  • 因为任何人都可以尝试向该服务发送邮件,它应该被设计成具有防御性的,例如,拒绝恶意行为者的“伪造”信息。需要有几个层次的检查。

  • 如果一切检查无误,服务将使用众所周知的纯文本隐私增强邮件(PEM)格式将证书存储在一个文件中。

还有一些非功能性需求:

  • 仅从对内部发生的响应来看,机器对机器的webhook服务可能很难看清。服务应提供详尽的人类可读的应用程序级日志。特别是,证书解析和检查应该被记录下来。

  • 我们为应用内部添加了测试案例,使用很好的Pytest框架,并在使用Travis CI与GitHub集成时自动运行那些测试。

好的——让我们开始吧!

1. 解决方案概览

这是整体解决方案的样子。

Diagram depicting a secure email flow illustrating how emails are verified using certificates for secure transmission.

2. 安装、配置和启动 web app

我们会从这一部分开始,因此在处理入站中继webhooks之前,我们将其充分测试。

网络应用程序包含在同一个GitHub项目中,与第1至3部分相同,因此如果您已经按照那些部分操作过了,那么您已经拥有它。这里是新的部分:

  • 程序 readSMIMEsig.py – 读取电子邮件并解析中间和用户证书。

  • 程序 webapp.py – 用于 SparkPost 入站中继 Webhooks 的简单 Flask 兼容网络应用程序。

  • webapp.ini – 上述的配置文件。配置文件使得相同的值可轻松传递到命令行和网络应用程序中。

您需要确保您的主机拥有正确的TCP端口号对外部世界的入站请求开放,以便SparkPost可以将消息POST到您的应用程序。如果您托管在AWS EC2上,例如,您将需要配置实例的安全组

配置和启动web应用程序的说明给出在这里 – 这非常简单。为了检查您的应用程序是否正运行且可以从外部世界访问,您可以使用 curl 从另一个主机发送(空白)请求,例如:

curl -X POST https://app.trymsys.net:8855/

您应该看到这样的响应:

{"message":"请求头中未知的内容类型"}

这是件好事——您的应用程序正在运行!

在您主机的 webapp.log 中,您将看到类似这样的输出:

2019-01-15 00:11:07,575,root,INFO, 请求来自 38.96.5.10,scheme=https,path=/ 2019-01-15 00:11:07,575,root,INFO,| len(headers)=3,len(body)=None 2019-01-15 00:11:07,575,root,INFO,| 未知内容类型:None

为了帮助您立即在应用程序中使用真实数据,您可以从项目仓库导入此特定Postman请求。这模拟了您的SparkPost账户的操作,即发送包含指定的、有效的证书(属于我一个测试账户)的https POST到您的应用程序。

您只需在请求中(上面的灰色框内)更改目标地址以匹配您的安装。如果您更改了 webapp.ini 中的令牌值,请调整 Postman 中的头值以匹配。

如果您的应用程序运行正常,您将在 Postman 中看到“200 OK”的响应。您的主机 webapp.log 文件将包含如下输出:

2019-01-15 00:11:48,554,root,INFO, 请求来自 38.96.5.10,scheme=https,path=/ 2019-01-15 00:11:48,554,root,INFO,| len(headers)=10,len(body)=14778 2019-01-15 00:11:48,555,root,INFO,| msg_from=bob.lumreeker@gmail.com,rcpt_to=secureme@inbound.thetucks.com,len(email_rfc822)=9223 2019-01-15 00:11:48,599,root,INFO,| from=bob.lumreeker@gmail.com,DKIM 验证通过 2019-01-15 00:11:48,600,root,INFO,| content-type=multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="------------ms010908020707040304020406",content-description=None 2019-01-15 00:11:48,600,root,INFO,| content-type=text/plain; charset=utf-8; format=flowed,content-description=None 2019-01-15 00:11:48,600,root,INFO,| content-type=application/pkcs7-signature; name="smime.p7s",content-description=S/MIME Cryptographic Signature 2019-01-15 00:11:48,600,root,INFO,| filename=smime.p7s,bytes=3998 2019-01-15 00:11:48,601,root,INFO,| Certificate: subject email_address=['bob.lumreeker@gmail.com'],not_valid_before=2018-10-03 00:00:00,not_valid_after=2019-10-03 23:59:59,hash_algorithm=sha256,key_size=2048 bytes, issuer={'countryName': 'GB', 'stateOrProvinceName': 'Greater Manchester', 'localityName': 'Salford', 'organizationName': 'COMODO CA Limited', 'commonName': 'COMODO RSA Client Authentication and Secure Email CA'} 2019-01-15 00:11:48,602,root,INFO,| Certificate: subject email_address=[],not_valid_before=2013-01-10 00:00:00,not_valid_after=2028-01-09 23:59:59,hash_algorithm=sha384,key_size=2048 bytes, issuer={'countryName': 'GB', 'stateOrProvinceName': 'Greater Manchester', 'localityName': 'Salford', 'organizationName': 'COMODO CA Limited', 'commonName': 'COMODO RSA Certification Authority'} 2019-01-15 00:11:48,616,root,INFO,| 写入文件 ./bob.lumreeker@gmail.com.crt,bytes=1870,ok=True

为了快速核对,请查看最后一行 - 如果它显示“写入文件”,那么您已成功。其余部分显示的是 DKIM 检查和证书验证过程。

我们会从这一部分开始,因此在处理入站中继webhooks之前,我们将其充分测试。

网络应用程序包含在同一个GitHub项目中,与第1至3部分相同,因此如果您已经按照那些部分操作过了,那么您已经拥有它。这里是新的部分:

  • 程序 readSMIMEsig.py – 读取电子邮件并解析中间和用户证书。

  • 程序 webapp.py – 用于 SparkPost 入站中继 Webhooks 的简单 Flask 兼容网络应用程序。

  • webapp.ini – 上述的配置文件。配置文件使得相同的值可轻松传递到命令行和网络应用程序中。

您需要确保您的主机拥有正确的TCP端口号对外部世界的入站请求开放,以便SparkPost可以将消息POST到您的应用程序。如果您托管在AWS EC2上,例如,您将需要配置实例的安全组

配置和启动web应用程序的说明给出在这里 – 这非常简单。为了检查您的应用程序是否正运行且可以从外部世界访问,您可以使用 curl 从另一个主机发送(空白)请求,例如:

curl -X POST https://app.trymsys.net:8855/

您应该看到这样的响应:

{"message":"请求头中未知的内容类型"}

这是件好事——您的应用程序正在运行!

在您主机的 webapp.log 中,您将看到类似这样的输出:

2019-01-15 00:11:07,575,root,INFO, 请求来自 38.96.5.10,scheme=https,path=/ 2019-01-15 00:11:07,575,root,INFO,| len(headers)=3,len(body)=None 2019-01-15 00:11:07,575,root,INFO,| 未知内容类型:None

为了帮助您立即在应用程序中使用真实数据,您可以从项目仓库导入此特定Postman请求。这模拟了您的SparkPost账户的操作,即发送包含指定的、有效的证书(属于我一个测试账户)的https POST到您的应用程序。

您只需在请求中(上面的灰色框内)更改目标地址以匹配您的安装。如果您更改了 webapp.ini 中的令牌值,请调整 Postman 中的头值以匹配。

如果您的应用程序运行正常,您将在 Postman 中看到“200 OK”的响应。您的主机 webapp.log 文件将包含如下输出:

2019-01-15 00:11:48,554,root,INFO, 请求来自 38.96.5.10,scheme=https,path=/ 2019-01-15 00:11:48,554,root,INFO,| len(headers)=10,len(body)=14778 2019-01-15 00:11:48,555,root,INFO,| msg_from=bob.lumreeker@gmail.com,rcpt_to=secureme@inbound.thetucks.com,len(email_rfc822)=9223 2019-01-15 00:11:48,599,root,INFO,| from=bob.lumreeker@gmail.com,DKIM 验证通过 2019-01-15 00:11:48,600,root,INFO,| content-type=multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="------------ms010908020707040304020406",content-description=None 2019-01-15 00:11:48,600,root,INFO,| content-type=text/plain; charset=utf-8; format=flowed,content-description=None 2019-01-15 00:11:48,600,root,INFO,| content-type=application/pkcs7-signature; name="smime.p7s",content-description=S/MIME Cryptographic Signature 2019-01-15 00:11:48,600,root,INFO,| filename=smime.p7s,bytes=3998 2019-01-15 00:11:48,601,root,INFO,| Certificate: subject email_address=['bob.lumreeker@gmail.com'],not_valid_before=2018-10-03 00:00:00,not_valid_after=2019-10-03 23:59:59,hash_algorithm=sha256,key_size=2048 bytes, issuer={'countryName': 'GB', 'stateOrProvinceName': 'Greater Manchester', 'localityName': 'Salford', 'organizationName': 'COMODO CA Limited', 'commonName': 'COMODO RSA Client Authentication and Secure Email CA'} 2019-01-15 00:11:48,602,root,INFO,| Certificate: subject email_address=[],not_valid_before=2013-01-10 00:00:00,not_valid_after=2028-01-09 23:59:59,hash_algorithm=sha384,key_size=2048 bytes, issuer={'countryName': 'GB', 'stateOrProvinceName': 'Greater Manchester', 'localityName': 'Salford', 'organizationName': 'COMODO CA Limited', 'commonName': 'COMODO RSA Certification Authority'} 2019-01-15 00:11:48,616,root,INFO,| 写入文件 ./bob.lumreeker@gmail.com.crt,bytes=1870,ok=True

为了快速核对,请查看最后一行 - 如果它显示“写入文件”,那么您已成功。其余部分显示的是 DKIM 检查和证书验证过程。

我们会从这一部分开始,因此在处理入站中继webhooks之前,我们将其充分测试。

网络应用程序包含在同一个GitHub项目中,与第1至3部分相同,因此如果您已经按照那些部分操作过了,那么您已经拥有它。这里是新的部分:

  • 程序 readSMIMEsig.py – 读取电子邮件并解析中间和用户证书。

  • 程序 webapp.py – 用于 SparkPost 入站中继 Webhooks 的简单 Flask 兼容网络应用程序。

  • webapp.ini – 上述的配置文件。配置文件使得相同的值可轻松传递到命令行和网络应用程序中。

您需要确保您的主机拥有正确的TCP端口号对外部世界的入站请求开放,以便SparkPost可以将消息POST到您的应用程序。如果您托管在AWS EC2上,例如,您将需要配置实例的安全组

配置和启动web应用程序的说明给出在这里 – 这非常简单。为了检查您的应用程序是否正运行且可以从外部世界访问,您可以使用 curl 从另一个主机发送(空白)请求,例如:

curl -X POST https://app.trymsys.net:8855/

您应该看到这样的响应:

{"message":"请求头中未知的内容类型"}

这是件好事——您的应用程序正在运行!

在您主机的 webapp.log 中,您将看到类似这样的输出:

2019-01-15 00:11:07,575,root,INFO, 请求来自 38.96.5.10,scheme=https,path=/ 2019-01-15 00:11:07,575,root,INFO,| len(headers)=3,len(body)=None 2019-01-15 00:11:07,575,root,INFO,| 未知内容类型:None

为了帮助您立即在应用程序中使用真实数据,您可以从项目仓库导入此特定Postman请求。这模拟了您的SparkPost账户的操作,即发送包含指定的、有效的证书(属于我一个测试账户)的https POST到您的应用程序。

您只需在请求中(上面的灰色框内)更改目标地址以匹配您的安装。如果您更改了 webapp.ini 中的令牌值,请调整 Postman 中的头值以匹配。

如果您的应用程序运行正常,您将在 Postman 中看到“200 OK”的响应。您的主机 webapp.log 文件将包含如下输出:

2019-01-15 00:11:48,554,root,INFO, 请求来自 38.96.5.10,scheme=https,path=/ 2019-01-15 00:11:48,554,root,INFO,| len(headers)=10,len(body)=14778 2019-01-15 00:11:48,555,root,INFO,| msg_from=bob.lumreeker@gmail.com,rcpt_to=secureme@inbound.thetucks.com,len(email_rfc822)=9223 2019-01-15 00:11:48,599,root,INFO,| from=bob.lumreeker@gmail.com,DKIM 验证通过 2019-01-15 00:11:48,600,root,INFO,| content-type=multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-256; boundary="------------ms010908020707040304020406",content-description=None 2019-01-15 00:11:48,600,root,INFO,| content-type=text/plain; charset=utf-8; format=flowed,content-description=None 2019-01-15 00:11:48,600,root,INFO,| content-type=application/pkcs7-signature; name="smime.p7s",content-description=S/MIME Cryptographic Signature 2019-01-15 00:11:48,600,root,INFO,| filename=smime.p7s,bytes=3998 2019-01-15 00:11:48,601,root,INFO,| Certificate: subject email_address=['bob.lumreeker@gmail.com'],not_valid_before=2018-10-03 00:00:00,not_valid_after=2019-10-03 23:59:59,hash_algorithm=sha256,key_size=2048 bytes, issuer={'countryName': 'GB', 'stateOrProvinceName': 'Greater Manchester', 'localityName': 'Salford', 'organizationName': 'COMODO CA Limited', 'commonName': 'COMODO RSA Client Authentication and Secure Email CA'} 2019-01-15 00:11:48,602,root,INFO,| Certificate: subject email_address=[],not_valid_before=2013-01-10 00:00:00,not_valid_after=2028-01-09 23:59:59,hash_algorithm=sha384,key_size=2048 bytes, issuer={'countryName': 'GB', 'stateOrProvinceName': 'Greater Manchester', 'localityName': 'Salford', 'organizationName': 'COMODO CA Limited', 'commonName': 'COMODO RSA Certification Authority'} 2019-01-15 00:11:48,616,root,INFO,| 写入文件 ./bob.lumreeker@gmail.com.crt,bytes=1870,ok=True

为了快速核对,请查看最后一行 - 如果它显示“写入文件”,那么您已成功。其余部分显示的是 DKIM 检查和证书验证过程。

3. SparkPost inbound relay webhooks 设置

首先,我们选择一个域名作为我们的入站消息地址——在这里,它将是 inbound.thetucks.com。按照此指南设置您的域名。我使用的详细步骤如下:

3.1 添加 MX 记录

您需要访问您的特定 Internet 服务提供商帐户。完成后,您可以使用 dig 检查它们——这是我的域名的命令。

dig +short MX inbound.thetucks.com

您应该看到:

10 rx3.sparkpostmail.com. 10 rx1.sparkpostmail.com. 10 rx2.sparkpostmail.com.

3.2 创建入站域

使用 SparkPost Postman API 集合,选择入站域/创建 .. 调用。POST 请求的主体包含您的域,例如:

{    "domain": "inbound.thetucks.com" }

Postman desktop application with an open tab displaying a 'Create an Inbound Domain' API request, featuring fields such as domain input, several header options, and a JSON payload, aimed at testing and automating API workflows.


3.3 创建中继 Webhook

使用相关的 Postman 调用创建一个入站中继 webhook。就我而言,消息主体包含:

{ "name": "Certificate Collection Webhook", "target": "https://app.trymsys.net:8855/", "auth_token": "t0p s3cr3t t0k3n", "match": { "protocol": "SMTP", "domain": "inbound.thetucks.com" } }

如前所述,我建议设置一个 auth_token为您自己的秘密值,如您主机上的 webapp.ini 文件中设置。

您的“target”值需要与您托管 Web 应用程序的主机地址和 TCP 端口匹配。

您的“domain”值需要与步骤 1 中设置的 MX 记录匹配。

Postman interface, showing the process of creating a relay webhook with detailed JSON configuration, with sections including request method, parameters, and code snippet.


就是这样!管道连接完成。您现在应该可以将证书发送到您的入站地址,它们将被处理并显示在您的 Web 应用程序主机上——在这种情况下,文件名为 bob.lumreeker@gmail.com.crt。

现在,您可以使用本系列第 2 和第 3 部分中描述的工具向 Bob 发送加密电子邮件。

您可以使用以下方式检查证书内容:

openssl x509 -inform PEM -in bob.lumreeker\@gmail.com.crt -text -noout

4. Internals: DKIM 检查, 证书验证

该应用程序检查接收到的电子邮件是否具有有效的DKIM,并检查证书本身的有效性,如此处所述。 其中还有实现说明和进一步工作的想法。

总结…

我们已经看到如何使用电子邮件轻松收集收件人的公钥,这是通过转入中继webhooks地址完成的。完成后,这些收件人可以接收S/MIME加密形式的消息。

就到这里!发送愉快。

让我们为您联系Bird专家。
在30分钟内见证Bird的全部威力。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

Newsletter

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

让我们为您联系Bird专家。
在30分钟内见证Bird的全部威力。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

Newsletter

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。

让我们为您联系Bird专家。
在30分钟内见证Bird的全部威力。

通过提交,您同意 Bird 可能会就我们的产品和服务与您联系。

您可以随时取消订阅。查看Bird的隐私声明以获取有关数据处理的详细信息。

R

Reach

G

Grow

M

Manage

A

Automate

Newsletter

通过每周更新到您的收件箱,随时了解 Bird 的最新动态。