Adding Support Mail
While including a flow for contacting support often comes as a last minute after-thought,
having a great complaining experience can be instrumental in further improving the app.
It is by no means a complex task, but there are a few gotchas along the way.
Gathering Context
Feedback is often caused by a regression, introduced in a certain release version,
or only occurs in a specific environment.
Therefore, it’s useful to include this sort of data in the initial support request.
This avoids unnecessary back and forth.
Here’s an example of gathering some commonly required context.
var app: String {
Bundle.main.info("CFBundleDisplayName") + " " +
Bundle.main.info("CFBundleShortVersionString")
}
var os: String {
#if os(iOS)
let platform = "iOS "
#elseif os(macOS)
let platform = "MacOS "
#endif
return platform + ProcessInfo.processInfo.operatingSystemVersionString
}
I’m using this extension to make fetching data from the app’s bundle more convenient.
extension Bundle {
func info(_ key: String) -> String {
infoDictionary.flatMap { $0[key] as? String }
?? "Missing " + key
}
}
Constructing Link
The mailto: URI scheme supports specifying subject and body using query parameters,
which are then parsed by the user’s default mail client.
var mailTo: URL {
URL(string: "mailto:\(supportEmail)")!
.appending(
queryItems: [
URLQueryItem(name: "subject", value: "Support: \(app)"),
URLQueryItem(name: "body", value: "\n\n\nOS: \(os)\nApp: \(app)"),
]
)
}
User Interface
When all is done, SwiftUI offers various ways of opening the constructed link:
Button
Using openURL environment variable
struct ContactSupportView: View {
@Environment(\.openURL) private var openURL
var body: some View {
Button("Contact Support") { openURL(mailTo) }
}
}
Inline
Since iOS 15 SwiftUI supports limited markdown rendering, with one caveat.
If we want to use anything else than simple string literals (like interpolation),
LocalizedStringKey(stringLiteral:)
initialiser has to be used explicitly.
Text(
LocalizedStringKey(
stringLiteral: "Contact us [\(supportEmail)](\(mailTo))!"
)
)
Link
The simplest option!
Link("Contact Support", destination: mailTo)
Result
Now users can create a simple mail template with a single tap!
As a bonus, consistent titles allow for some automation when handling support.
Especially in cases where multiple apps are served by a single email address.