时间: 2020-08-23|42次围观|0 条评论

如何在iOS上通过电子邮件进行无缝的“无密码”身份验证。

Apple平台上的邮件和日历集成

在macOS和iOS上查看电子邮件时,邮件会在检测到的日期和时间下划线 。您可以与他们互动以创建新的日历事件。如果您在“日历”中打开此类活动,则会在其扩展详细信息中看到“在邮件中显示”链接。单击此链接可将您带回到原始电子邮件。

此功能可以追溯到iPhone的发布。它将被纳入当年的 Mac OS X版本(Leopard)中, 这将标志着许多移动功能中的第一个进入台式机。

如果要将“魔术” URL复制到粘贴板并在文本编辑器中查看,则会看到以下内容:

"message:%3C1572873882024.NSHIPSTER%40mail.example.com%3E"

经验丰富的iOS开发人员将立即意识到使用 自定义URL方案。其中精通网络的用户可以对主机进行百分比解码,并识别出它类似于电子邮件地址,但事实并非如此。

因此,如果没有电子邮件地址,我们在这里看什么?
这是另一个不同的电子邮件字段,称为<dfn style="box-sizing: border-box;">Message-ID</dfn>。

消息ID

RFC 5322§3.6.4 规定,每封电子邮件应该 具有“消息ID:”字段包含单个唯一消息标识符。该标识符的语法本质上是一个带有尖括号(<>)的电子邮件地址。

尽管该规范未包含任何有关生成良好Message-ID的规范性指导,但 1998年的IETF草案草稿还是很不错的。

让我们看一下如何在Swift中执行此操作:

生成随机消息ID

前述文档中描述的第一种技术涉及生成带有64位随机数的随机消息ID,该消息ID带有时间戳,以进一步减少冲突的机会。我们可以使用Swift 5内置的随机数生成器API和String(_:radix:uppercase:)初始化程序来轻松完成此操作 :

import Foundationlet timestamp = String(Int(Date().timeIntervalSince1970 * 1000))let nonce = String(UInt64.random(in: 0..<UInt64.max), radix: 36, uppercase: true)let domain = "mail.example.com"let MessageID = "<\(timestamp).\(nonce)@\(domain)>"//"<1572873882024.NSHIPSTER@mail.example.com>"

然后,我们可以将生成的Message-ID与关联的记录一起保存,以便以后链接到它。但是,在许多情况下,一种更简单的选择是使消息ID具有确定性,并且可以从其现有状态进行计算。

生成确定性消息ID

考虑符合Identifiable协议 且其关联ID类型为 UUID的记录结构 。您可以这样生成消息ID:

import Foundationfunc messageID<Value>(for value: Value, domain: String) -> String    where Value: Identifiable, Value.ID == UUID{    return "<\(value.id.uuidString)@\(domain)>"}

如果缺少持久性标识符(或任何其他区别功能),则可以改用消息正文本身的摘要来生成消息ID。这是使用新的CryptoKit框架的示例实现 :

import Foundationimport CryptoKitlet body = #"""Lorem ipsum dolor sit amet, consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laborisnisi ut aliquip ex ea commodo consequat."""#let digest = Data(SHA256.hash(data: body.data(using: .utf8)!))                .map { String($0, radix: 16, uppercase: true) }                .joined()let domain = "ADF""<\(digest)@\(domain)>"// "<F52380112175FCE8ECF2731C193EB8A7CC8642E53C68D292CD88531D42F145@mail.example.com>"

移动深层链接

iOS和macOS上的常规Mail客户端都将尝试message:通过启动到前台并尝试使用编码的Message-ID字段打开消息来使用自定义方案打开URL 。

生成具有消息ID的邮件深层链接

掌握了Message-ID之后,最后的任务是创建一个深层链接,您可以使用该深层链接将Mail打开到关联的消息。唯一的技巧是 在URL中对消息ID 进行 百分比编码。您可以使用方法来执行此操作 ,但是我们更愿意将所有操作委托给-这具有进一步的优势,即无需使用格式字符串就可以完整构建URL 。adding<wbr style="box-sizing: border-box;">Percent<wbr style="box-sizing: border-box;">Encoding(with<wbr style="box-sizing: border-box;">Allowed<wbr style="box-sizing: border-box;">Characters:)URLComponents

import Foundationvar components = URLComponents()components.scheme = "message"components.host = MessageIDcomponents.string!// "message://%3C1572873882024.NSHIPSTER%40mail.example.com%3E"

据我们所知,自定义message:方案后是否存在双斜杠不会对邮件深层链接解析产生任何影响。

打开邮件深层链接

如果您message:在iOS上打开URL,并且可以从 其中一个帐户的inbox轻松访问链接的消息,则Mail将立即启动该消息。如果找不到该消息,则该应用程序将启动并在后台异步加载该消息,并在可用时将其打开。
相比之下,尝试在macOS上打开到尚未加载的邮件的邮件深层链接会导致显示警报模式。因此,我们建议仅在iOS上使用邮件深层链接。

例如, 飞行学校 使用无密码身份验证系统来执行此操作。要访问书籍的电子副本,请输入用于购买书籍的电子邮件地址。提交表单后,iOS上的用户将看到一个深层链接,用于打开指向包含“魔术登录链接”✨的电子邮件的Mail应用程序。

其他系统可能使用消息ID通过通用链接简化其本机应用或网站的无密码身份验证 ,或者将其合并为<abbr title="两要素认证" style="box-sizing: border-box; font-variant: small-caps; text-transform: lowercase;">2fa</abbr>策略的一部分 (因为出于此目的,不再认为<abbr title="短消息服务" style="box-sizing: border-box; font-variant: small-caps; text-transform: lowercase;">sms</abbr>是安全的)。

如果您在Web应用程序中使用Rails,则 ActiveMailer拦截器 提供了一种方便的方式来Message-ID为无密码验证流注入字段。


与苹果平台上如此众多的私人集成(仍然是第一方应用程序的专有领域)不同,“在邮件中显示”的秘密之处在于我们所有人都能参与进来。尽管没有记录,但是由于该功能与系统的深度集成以及植根于基本Web标准中,因此该功能不太可能很快被删除。

另外,如果你想一起进阶,不妨添加一下交流群1012951431,选择加入一起交流,一起学习。期待你的加入!(进群可领取学习礼包)

浏览器供应商社交媒体公司政府(甚至有时甚至是苹果公司)的每个人都 试图拆开开放的网络并控制我们可以看到和执行的操作时,很高兴得知电子邮件 将近50年了,保持互联网自由和分散的能力仍然坚决。

翻译地址: https://nshipster.com/message-id/

文章转载于:https://www.jianshu.com/p/c2984e05243e

原著是一个有趣的人,若有侵权,请通知删除

本博客所有文章如无特别注明均为原创。
复制或转载请以超链接形式注明转自起风了,原文地址《iOS和macOS上的Message-ID和Mail.app深度链接
   

还没有人抢沙发呢~