Last active
May 26, 2022 09:10
-
-
Save serjooo/9628e6cc7eec4d0d16433660aa5184ad to your computer and use it in GitHub Desktop.
Check and Deep link into supported mail apps on iOS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum MailClient: CaseIterable { | |
case gmail | |
case outlook | |
case yahoo | |
case spark | |
case apple | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
protocol URLHandlerProtocol { | |
func canOpenURL(_ url: URL) -> Bool | |
func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any], completionHandler completion: ((Bool) -> Void)?) | |
} | |
extension UIApplication: URLHandlerProtocol {} | |
// GIST is sponsored by the following StackOverflow answer: | |
// https://stackoverflow.com/a/55765362 | |
struct MailClientProvider { | |
let content: MailContent | |
let urlHandler: URLHandlerProtocol | |
func getFirstSupportedMailClientURL() -> URL? { | |
getAllSupportedMailClients() | |
.first | |
.flatMap(getURL(for:)) | |
} | |
func openFirstSupportedMailClient(completion: ((Bool) -> Void)?) { | |
guard let firstSupportedMailClientURL = getFirstSupportedMailClientURL() else { | |
print("Failed to open any mail client, none of them are supported") | |
completion?(false) | |
return | |
} | |
urlHandler.open(firstSupportedMailClientURL, options: [:], completionHandler: completion) | |
} | |
func getAllSupportedMailClients() -> [MailClient] { | |
return MailClient.allCases.filter(canOpenMailClient(_:)) | |
} | |
func canOpenMailClient(_ client: MailClient) -> Bool { | |
guard let url = getURL(for: client) else { | |
print("Mail Client URL corrupted \(client)") | |
return false | |
} | |
return urlHandler.canOpenURL(url) | |
} | |
func getURL(for client: MailClient) -> URL? { | |
let toURLPart = "to=\(content.recipientEmail)" | |
let subjectURLPart = "subject=\(content.subject)" | |
let bodyURLPart = "body=\(content.body)" | |
let subjectAndBodyPart = [subjectURLPart, bodyURLPart].joined(separator: "&") | |
let fullURLPart = [toURLPart, subjectURLPart, bodyURLPart].joined(separator: "&") | |
switch client { | |
case .gmail: | |
return URL(string: "googlegmail://co?\(fullURLPart)") | |
case .outlook: | |
return URL(string: "ms-outlook://compose?\(fullURLPart)") | |
case .yahoo: | |
return URL(string: "ymail://mail/compose?\(fullURLPart)") | |
case .spark: | |
return URL(string: "readdle-spark://compose?recipient=\(content.recipientEmail)&\(subjectAndBodyPart)") | |
case .apple: | |
return URL(string: "mailto:\(content.recipientEmail)?\(subjectAndBodyPart)") | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct MailContent { | |
let recipientEmail: String | |
@URLPercentEncoded var body: String | |
@URLPercentEncoded var subject: String | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MARK: - Extension | |
extension String { | |
var urlPercentEncoded: String { | |
addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? self | |
} | |
} | |
// MARK: - Property Wrapper | |
@propertyWrapper | |
struct URLPercentEncoded { | |
var wrappedValue: String { | |
didSet { | |
wrappedValue = wrappedValue.urlPercentEncoded | |
} | |
} | |
init(wrappedValue: String) { | |
self.wrappedValue = wrappedValue.urlPercentEncoded | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment