Reach

Grow

Manage

Automate

Reach

Grow

Manage

Automate

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

电子邮件

1 min read

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

电子邮件

1 min read

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

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

第1部分中,我们快速浏览了S/MIME,了解了在各种邮件客户端中对信息流进行签名和加密的方法。第2部分介绍了如何通过一个简单的命令行工具签名和加密电子邮件,然后通过SparkPost发送。第3部分展示了如何将安全邮件流注入到如Port25 PowerMTAMomentum等本地平台。

在这个系列中,我们看到包括S/MIME签名是相对简单的。发送S/MIME加密邮件更加复杂,因为您需要获取收件人的公钥。当您使用如Thunderbird这样的邮件客户端时,这还可行——但应用生成的邮件流该如何运作呢?

但是等等——还有另一种方法可以进入Mordor获取那些密钥。您的服务可以邀请您的客户(通过电子邮件,当然)发送一封签名邮件到已知的客户服务地址。使用SparkPost Inbound Relay webhooks的神奇力量,我们会为您提取并存储该公钥以供使用。

我们可以用一个简单的使用案例来总结:

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

从中,让我们推导一些更详细的要求:




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

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

  • 因为任何人都可以尝试向该服务发送邮件,所以应防御性设计,例如,拒绝来自不良行为者的“欺骗”消息。需要有多层检查。

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

有一些非功能性要求:

  • 机器对机器的webhook服务,仅从响应中了解内部发生的事情可能很困难。服务应提供广泛的人类可读的应用程序级日志。特别是,证书解析和检查应被记录。

  • 我们为应用程序内部添加测试用例,使用不错的Pytest框架,并使用Travis CI与GitHub集成自动运行这些测试。

好吧——让我们开始吧!

1. 解决方案概览

这是整体解决方案的外观。

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

我们将从这部分开始,因此我们在处理入站中继 webhook 之前先对其进行全面测试。

该 web 应用程序包含在同一个 GitHub 项目中作为第 1 - 3 部分的一部分,因此,如果您已经遵循了这些部分,您已经拥有它。以下是新增的部分:

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

  • 程序 webapp.py – 简单的与 Flask 兼容的 web 应用程序,用于 SparkPost 入站中继 Webhook。

  • webapp.ini – 上述程序的配置文件。配置文件使得可以很容易地将相同的值传递到命令行和 web 应用程序中。




您需要确保主机具有正确的 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 加密签名 2019-01-15 00:11:48,600,root,INFO,| filename=smime.p7s,bytes=3998 2019-01-15 00:11:48,601,root,INFO,| 证书:主题 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 客户认证和安全电子邮件 CA'} 2019-01-15 00:11:48,602,root,INFO,| 证书:主题 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 认证机构'} 2019-01-15 00:11:48,616,root,INFO,| 文件已写入 ./bob.lumreeker@gmail.com.crt,bytes=1870,ok=True

为了快速的完整性检查,请查看最后一行 – 如果上面写着“文件已写入”,那么您就没问题了。其余的是显示 DKIM 检查和证书验证过程。

我们将从这部分开始,因此我们在处理入站中继 webhook 之前先对其进行全面测试。

该 web 应用程序包含在同一个 GitHub 项目中作为第 1 - 3 部分的一部分,因此,如果您已经遵循了这些部分,您已经拥有它。以下是新增的部分:

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

  • 程序 webapp.py – 简单的与 Flask 兼容的 web 应用程序,用于 SparkPost 入站中继 Webhook。

  • webapp.ini – 上述程序的配置文件。配置文件使得可以很容易地将相同的值传递到命令行和 web 应用程序中。




您需要确保主机具有正确的 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 加密签名 2019-01-15 00:11:48,600,root,INFO,| filename=smime.p7s,bytes=3998 2019-01-15 00:11:48,601,root,INFO,| 证书:主题 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 客户认证和安全电子邮件 CA'} 2019-01-15 00:11:48,602,root,INFO,| 证书:主题 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 认证机构'} 2019-01-15 00:11:48,616,root,INFO,| 文件已写入 ./bob.lumreeker@gmail.com.crt,bytes=1870,ok=True

为了快速的完整性检查,请查看最后一行 – 如果上面写着“文件已写入”,那么您就没问题了。其余的是显示 DKIM 检查和证书验证过程。

我们将从这部分开始,因此我们在处理入站中继 webhook 之前先对其进行全面测试。

该 web 应用程序包含在同一个 GitHub 项目中作为第 1 - 3 部分的一部分,因此,如果您已经遵循了这些部分,您已经拥有它。以下是新增的部分:

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

  • 程序 webapp.py – 简单的与 Flask 兼容的 web 应用程序,用于 SparkPost 入站中继 Webhook。

  • webapp.ini – 上述程序的配置文件。配置文件使得可以很容易地将相同的值传递到命令行和 web 应用程序中。




您需要确保主机具有正确的 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 加密签名 2019-01-15 00:11:48,600,root,INFO,| filename=smime.p7s,bytes=3998 2019-01-15 00:11:48,601,root,INFO,| 证书:主题 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 客户认证和安全电子邮件 CA'} 2019-01-15 00:11:48,602,root,INFO,| 证书:主题 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 认证机构'} 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记录

你需要访问特定的互联网服务提供商账户。完成后,你可以使用 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" }




3.3 创建一个中继Web挂钩

使用相关的 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记录。







就是这样!管道设置完成。你现在应该能够将证书发送到你的入站地址,它们将被处理并显示在你的网络应用程序主机上 – 在这种情况下,一个名为 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加密形式的消息。

就到这里!发送愉快。

加入我们的Newsletter。

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

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

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

加入我们的Newsletter。

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

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

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

加入我们的Newsletter。

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

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

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

Pinterest 标志
Uber 标志
Square 徽标
Adobe 标志
Meta logo
PayPal 标志

Newsletter

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

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

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

Uber 标志
Square 徽标
Adobe 标志
Meta logo

Newsletter

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

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

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

Uber 标志
Adobe 标志
Meta logo

Reach

Grow

Manage

Automate

资源

公司

Newsletter

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

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

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