如何在iOS上通過電子郵件進行無縫的“無密碼”身份驗證。 Apple平臺上的郵件和日曆集成 在macOS和iOS上查看電子郵件時,郵件會在[檢測到的日期和時間]下劃線 。您可以與他們互動以創建新的日曆事件。如果您在“日曆”中打開此類活動,則會在其擴展詳細信息中看到“在郵件中顯示”鏈接。單擊此鏈接可將 ...
如何在iOS上通過電子郵件進行無縫的“無密碼”身份驗證。
Apple平臺上的郵件和日曆集成
在macOS和iOS上查看電子郵件時,郵件會在[檢測到的日期和時間]下劃線 。您可以與他們互動以創建新的日曆事件。如果您在“日曆”中打開此類活動,則會在其擴展詳細信息中看到“在郵件中顯示”鏈接。單擊此鏈接可將您帶回到原始電子郵件。此功能可以追溯到iPhone的發佈。它將被納入當年的 [Mac OS X版本(Leopard)中,] 這將標志著許多移動功能中的第一個進入台式機。
如果要將“魔術” URL複製到粘貼板併在文本編輯器中查看,則會看到以下內容:
"message:%3C1572873882024.NSHIPSTER%40mail.example.com%3E"
經驗豐富的iOS開發人員將立即意識到使用 [自定義URL方案]。其中精通網路的用戶可以對主機進行百分比解碼,並識別出它類似於電子郵件地址,但事實並非如此。
因此,如果沒有電子郵件地址,我們在這裡看什麼?
這是另一個不同的電子郵件欄位,稱為Message-ID。
另外,如果你想一起進階,不妨添加一下交流群[1012951431],選擇加入一起交流,一起學習。期待你的加入!(進群可領取學習禮包)
消息ID
[RFC 5322§3.6.4]規定,每封電子郵件應該 具有“消息ID:”欄位包含單個唯一消息標識符。該標識符的語法本質上是一個帶有尖括弧(< >)的電子郵件地址。
儘管該規範未包含任何有關生成良好Message-ID的規範性指導,但 1998年的[IETF草案草稿]還是很不錯的。
讓我們看一下如何在Swift中執行此操作:
生成隨機消息ID
前述文檔中描述的第一種技術涉及生成帶有64位隨機數的隨機消息ID,該消息ID帶有時間戳,以進一步減少衝突的機會。我們可以使用Swift 5內置的隨機數生成器API和[String(_:radix:uppercase:)初始化]程式來輕鬆完成此操作 :
import Foundation let 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)>" //"<[email protected]>"
然後,我們可以將生成的Message-ID與關聯的記錄一起保存,以便以後鏈接到它。但是,在許多情況下,一種更簡單的選擇是使消息ID具有確定性,並且可以從其現有狀態進行計算。
生成確定性消息ID
考慮符合[Identifiable協議]且其關聯`ID`類型為 [UUID]的記錄結構 。您可以這樣生成消息ID:
import Foundation func messageID<Value>(for value: Value, domain: String) -> String where Value: Identifiable, Value.ID == UUID { return "<\(value.id.uuidString)@\(domain)>" }
如果缺少持久性標識符(或任何其他區別功能),則可以改用消息正文本身的摘要來生成消息ID。這是使用新的[CryptoKit框架]的示例實現 :
import Foundation import CryptoKit let 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 laboris nisi 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 PercentEncoding(withAllowedCharacters:)`][`URLComponents`]
import Foundation var components = URLComponents() components.scheme = "message" components.host = MessageID components.string! // "message://%3C1572873882024.NSHIPSTER%40mail.example.com%3E"
據我們所知,自定義`message:`方案後是否存在雙斜杠不會對郵件深層鏈接解析產生任何影響。
打開郵件深層鏈接
如果您`message:`在iOS上打開URL,並且可以從 其中一個帳戶的inbox輕鬆訪問鏈接的消息,則Mail將立即啟動該消息。如果找不到該消息,則該應用程式將啟動併在後臺非同步載入該消息,併在可用時將其打開。相比之下,嘗試在macOS上打開到尚未載入的郵件的郵件深層鏈接會導致顯示警報模式。因此,我們建議僅在iOS上使用郵件深層鏈接。例如, [飛行學校]使用無密碼身份驗證系統來執行此操作。要訪問書籍的電子副本,請輸入用於購買書籍的電子郵件地址。提交表單後,iOS上的用戶將看到一個深層鏈接,用於打開指向包含“魔術登錄鏈接”✨的電子郵件的Mail應用程式。
其他系統可能使用消息ID通過[通用鏈接]簡化其本機應用或網站的無密碼身份驗證 ,或者將其合併為2fa策略的一部分 (因為[出於此目的,不再認為][sms是安全的])。如果您在Web應用程式中使用Rails,則 [ActiveMailer攔截器]提供了一種方便的方式來Message-ID為無密碼驗證流註入欄位。
與蘋果平臺上如此眾多的私人集成(仍然是第一方應用程式的專有領域)不同,“在郵件中顯示”的秘密之處在於我們所有人都能參與進來。儘管沒有記錄,但是由於該功能與系統的深度集成以及植根於基本Web標準中,因此該功能不太可能很快被刪除。
從[瀏覽器供應商], [社交媒體公司]到 [政府](甚至有時甚至是蘋果[公司)的]每個人都 試圖拆開開放的網路並控制我們可以看到和執行的操作時,很高興得知電子郵件 [將近50年了],保持互聯網自由和分散的能力仍然堅決。
翻譯地址: https://nshipster.com/message-id/