This seems impossible to find, unless perhaps there isn't one for it. But anyone know (if there is one) the iOS URL Scheme for opening the Microsoft Outlook Mobile App right to the Compose Screen with pre-defined TO_EMAIL, SUBJECT and BODY?
Here is a link I found that helped me out with the IOS Outlook URL Scheme.
From that I was able to come up with this code:
// Create an array of recipients for the email.
NSArray* emailRecipients = #[#"example#email.com", #"example2#email.com"];
// Create a mutable string to hold all of the recipient email addresses and add the first one.
NSMutableString* emailTo = [[NSMutableString alloc] initWithString:emailRecipients[0]];
// Loop through all of the email recipients except for the first one.
for (int index = 1; index < emailRecipients.count; index++)
{
// Add a semicolon and then the email address at the current index.
[emailTo appendFormat:#";%#", emailRecipients[index]];
}
// Get the email subject from the subject text field.
NSString* emailSubject = fieldSubject.text;
// Encode the string for URL.
NSString* encodedSubject = [emailSubject stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
// Get the email body from the body text field.
NSString* emailBody = fieldBody.text;
// Encode the string for URL.
NSString* encodedBody = [emailBody stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
// See if the subject or body are empty.
if (![emailSubject length] || ![emailBody length])
{
// Exit.
return;
}
// Create a string with the URL scheme and email properties.
NSString *stringURL = [NSString stringWithFormat:#"ms-outlook://compose?to=%#&subject=%#&body=%#", emailTo, encodedSubject, encodedBody];
// Convert the string to a URL.
NSURL *url = [NSURL URLWithString:stringURL];
// Open the app that responds to the URL scheme (should be Outlook).
[[UIApplication sharedApplication] openURL:url];
The URL scheme for Outlook is: ms-outlook://compose?to=example#email.com&subject=Subject&body=Message
Hope this helps!
Swift
func outlookDeepLink(subject: String, body: String, recipients: [String]) throws -> URL {
enum MailComposeError: Error {
case emptySubject
case emptyBody
case unexpectedError
}
guard !subject.isEmpty else { throw MailComposeError.emptySubject }
guard !body.isEmpty else { throw MailComposeError.emptyBody }
let emailTo = recipients.joined(separator: ";")
var components = URLComponents()
components.scheme = "ms-outlook"
components.host = "compose"
components.queryItems = [
URLQueryItem(name: "to", value: emailTo),
URLQueryItem(name: "subject", value: subject),
URLQueryItem(name: "body", value: body),
]
guard let deepURL = components.url else { throw MailComposeError.unexpectedError }
return deepURL
}
Usage
try! UIApplication.shared.open(
outlookDeepLink(
subject: "subject",
body: "body",
recipients: ["example#email.com", "example2#email.com"]
)
)
Note that:
Don't forget to tell iOS you are going to call ms-outlook. (Add it to LSApplicationQueriesSchemes in info.plist, Otherwise, You will get an clear error message in console if you forget it)
Also don't forget to check if the app actually exists before trying to open the url. (canOpenURL is here to help)
Related
I am trying to use UIActivityViewController for outlook only...I was able to get my UIActivityViewController working like so:
//Define HTML String
var htmlString = ""
//Add the headings to HTML String table
htmlString += "<table border = '1' cellspacing='0' align = 'center'><tr><th>Job #</th><th>Task</th><th>Date</th></tr>"
//For each item in punch list data array
for i in 0..<punchListData.count {
//If the item is selected
if punchListData[i].cellSelected {
//Add data to the HTML String
htmlString += "<tr><td>" + jobList[i % jobList.count] + "</td><td align = 'center'>" + taskData[i / jobList.count] + "</td><td>" + (punchListData[i].stringData)! + "</td></tr>"
}
}
//Close the HTML table in the HTML String
htmlString += "</table><h5>Please contact me if you have any questions <br /> Thank you.</h5>"
let activityViewController = UIActivityViewController(activityItems : [htmlString], applicationActivities: nil)
activityViewController.setValue("Schedule for Community", forKey: "Subject")
activityViewController.popoverPresentationController?.barButtonItem = self.shareButton
self.present(activityViewController, animated: true, completion: nil)
But I have a few issues:
The subject line is not working, I did some research and apparently setValue will not work for Outlook and that the first line can be the subject line, but I have no idea how to do that.
Is there away to exclude all activities except for Outlook?
Previously I was just using MFMailComposeViewController to compose an email, is there away of doing this for Outlook? Without UIActivityViewController?
Thanks,
You can build your own UI and present it as you like, then convert arguments to a deeplink URL and pass it to the outlook app:
// MARK: - Errors
enum MailComposeError: Error {
case emptySubject
case emptyBody
case unexpectedError
}
// MARK: - Helper function
func outlookDeepLink(subject: String, body: String, recipients: [String]) throws -> URL {
guard !subject.isEmpty else { throw MailComposeError.emptySubject }
guard !body.isEmpty else { throw MailComposeError.emptyBody }
let emailTo = recipients.joined(separator: ";")
var components = URLComponents()
components.scheme = "ms-outlook"
components.host = "compose"
components.queryItems = [
URLQueryItem(name: "to", value: emailTo),
URLQueryItem(name: "subject", value: subject),
URLQueryItem(name: "body", value: body),
]
guard let deepURL = components.url else { throw MailComposeError.unexpectedError }
return deepURL
}
Usage
try! UIApplication.shared.open(
outlookDeepLink(
subject: "subject",
body: "body",
recipients: ["example#email.com", "example2#email.com"]
)
)
At last, Note that:
Don't forget to tell iOS you are going to call ms-outlook. (Add it to LSApplicationQueriesSchemes in info.plist, Otherwise, You will get an clear error message in console if you forget it)
Also don't forget to check if the app actually exists before trying to open the url. (canOpenURL is here to help)
Gmail client does not recognize line breaks within text from UIApplication.shared.openURL(url)
I have a function that returns a tuple of available email clients (validated by UIApplication.shared.canOpen) and the associated URL. It's for an error reporting feature, so the arguments array contains the text that will autopopulate email fields.
There are no issues with launching any of the three email clients, but gmail is the only one that doesn't process the line breaks. Does gmail use a different method?
enum EmailClient {
case gmail
case outlook
case mail
var title: String {
switch self {
case .gmail: return "Gmail"
case .outlook: return "Outlook"
case .mail: return "Mail"
}
}
//Creates url used by UIapplciation.shared to launch the client and autopopulate the email
func url(error: CustomError?) -> URL? {
guard let username = CredentialManager.username,
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
return nil
}
let arguments = [
username,
UIDevice().modelName,
UIDevice.current.systemVersion,
appVersion,
error?.description ?? "N/A" //When called from the settings page, no error is passed in
]
var urlFormat: String
switch self {
case .gmail: urlFormat = "googlegmail:///co?to=%#&subject=%#&body=%#"
case .outlook: urlFormat = "ms-outlook://compose?to=%#&subject=%#&body=%#"
case .mail: urlFormat = "mailto:%#?subject=%#&body=%#"
}
return URL(string: String(format: urlFormat, arguments: [
EMAIL_RECIPIENT,
EMAIL_SUBJECT.replacingOccurrences(of: " ", with: "%20"),
String(format: EMAIL_BODY_FORMAT, arguments: arguments).replacingOccurrences(of: " ", with: "%20").replacingOccurrences(of: "\n", with: "%0A")
]))
}
}
It seems that using "\r\n" instead of "\n" fixes the problem
1) Add the the scheme to your info.plist
We can do this through the beautiful thing that is the Info.plist file. Add a new key called LSApplicationQueriesSchemes as an array. Then you can enter your apps within the array. The Mail app doesn’t need to go in here, presumably because it is an Apple app. Your entry should look like the below
func openGmail(withFrom: String?, withSubject: String?) {
var gmailUrlString = "googlegmail:///"
if let from = withFrom {
gmailUrlString += "co?to=\(from)"
}
if let subject = withSubject {
gmailUrlString += "&subject=\(subject)"
}
}
One last thing we will need to do is URL encode the subject line before we pass it into the URL. We can do this by calling subjectString?.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed) on the string.
In my iOS app I am opening links using the code below:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",myurl]]];
The links come dynamically and HTTP/HTTPS is not provided.
I cannot hardcode HTTP or HTTPS because I don't know if the URL has HTTP or HTTPS. How can I open a URL without specifying HTTP or HTTPS?
Solution for Swift:
let urlString = "example.com"
let urlHasHttpPrefix = urlString.hasPrefix("http://")
let urlHasHttpsPrefix = urlString.hasPrefix("https://")
let validUrlString = (urlHasHttpPrefix || urlHasHttpsPrefix) ? urlString : "http://\(urlString)"
I think this a better approach than the ones presented here, since it avoids string comparison & manipulation.
public extension URL {
var sanitise: URL {
if var components = URLComponents(url: self, resolvingAgainstBaseURL: false) {
if components.scheme == nil {
components.scheme = "http"
}
return components.url ?? self
}
return self
}
}
Who said you don't know whether url contain http or not? You can find out...
In prefixheader.pch write below.
#define contains(str1, str2) ([str1 rangeOfString: str2 ].location != NSNotFound)
Then in your .m write below.
if (!contains(myurl, "http")) {
myurl = [NSString stringWithFormat:#"http://%#", myurl];
}
You are done!!!
Let me know if you need anything else.
Matching with rangeOfString is not a good approach.
You can match it as:
NSString *urlScheme = [url scheme];
if (urlScheme == nil) {
url = [NSURL URLWithString:[NSString stringWithFormat:#"http://%#",urlString]];
}
And you don't have to worry about whether it's http or https. whenever you'll hit a url on http it'll automatically redirects to https
I need to retrieve the text from a specific website. However, I only need a few parts of it. How can I accomplish this using swift.
I have found the following in objective-c, but am not sure it provides how to reference it from a specific site:
NSString *webString = [webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.innerText"];
NSScanner *stringScanner = [NSScanner scannerWithString:webString];
NSString *content = [[NSString alloc] init];
while ([stringScanner isAtEnd] == NO) {
[stringScanner scanUpToString:#"Start of the text you want" intoString:null];
[stringScanner scanUpToString:#"End of the text you want" intoString:&content];
}`
I have put an example of what I mean below:
Again, I would like to accomplish this using Swift.
If your HTML was easily targetable with identifiers or class names, I would suggest using a library such as Kanna. But I've had a look at your page and the text you need is lost amidst an ocean of divs...
So I've quickly hacked a way to get your text with componentsSeparatedByString: I'm cutting the HTML in blocks until I get to the part we're interested in.
Note that it's far from being the most efficient way: instead of using componentsSeparatedByString you should come with a way of identifying the HTML block you want and search for it with NSScanner.
That being said, here's my example of a working hack, tested in a Playground:
enum CustomErrors : String, ErrorType {
case InvalidURL = "Invalid URL"
}
do {
let str = "http://www.golfwrx.com/328370/mizuno-to-offer-custom-grips-at-no-additional-charge/"
guard let url = NSURL(string: str) else { throw CustomErrors.InvalidURL }
let html = try String(contentsOfURL: url)
let separator1 = "<div class='mailmunch-forms-before-post' style='display: none !important;'></div><p>"
let temp = html.componentsSeparatedByString(separator1)
let separator2 = "</p>\n<p>"
let temp2 = temp[1].componentsSeparatedByString(separator2)
let separator3 = "</p><div class='mailmunch-forms-in-post-middle'"
let separated = temp2[1].componentsSeparatedByString(separator3)
let result = separated[0]
print(result)
} catch {
print(error)
}
Note: my example is in Swift 2 (Xcode 7).
Sorry about the specifics, I'm an Objective-C guy. but, here is an example of how to use NString to get the contents of a websites HTML
NSString *url = #"http://www.example.com"; // Your URL
NSURL *urlRequest = [NSURL URLWithString:url]; // Make a request with your URL
NSError *err = nil; // Error handler
NSString *html = [NSString stringWithContentsOfURL:urlRequest encoding:NSUTF8StringEncoding error:&err]; // Try to get the HTML in the string
if(err)
{
//Do something as it didn't work! Maybe a connection problem
}
else
{
// Use NScanner on html string
}
http://nshipster.com/nsscanner/ is a good place to learn about NScanner for swift
EDIT: Here is the above translated to swift
var err: NSError? // Error handler
let url: NSURL = NSURL(string: "http://www.example.com") // NSURL, put your website URL in here
let string = NSString(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &err) // String will now hold your HTML
// Now use NScanner (See Link) to parse the HTML output
My swift is rusty. but this might help you. This is roughly translated but outlines exactly what you need
How do I make a call to this number *199*123456789# on iOS?
I used the following code but it doesn't work.
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"tel:*199*123456789#"]];
Reposted and modified from my answer to the now-closed question "iOS - I want to call phone number "#51234" in Xcode useing telprompt":
At least as of iOS 11, one can dial numbers with a hashtag (#) or asterisk (*).
Make calls with these characters by first encoding the phone number, then adding the tel: prefix, and finally turning the resulting string into a URL.
Swift 4, iOS 11
// 1) set up the dial sequence as a String
let dialSequence = "*199*123456789#"
// 2) "percent encode" the dial sequence with the "URL Host Allowed" character set
guard let encodedDialSequence =
dialSequence.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else {
print("Unable to encode the dial sequence.")
return
}
// 3) add the `tel:` url scheme to the front of the encoded string
// NOTE: the '//' part is optional: either 'tel:' or 'tel://' will work.
let dialURLString = "tel:\(encodedDialSequence)"
// 4) set up the URL with the scheme+encoded number string
guard let dialURL = URL(string: dialURLString) else {
print("Couldn't convert the dial string into an URL.")
return
}
// 5) dial the URL
UIApplication.shared.open(dialURL, options: [:]) { success in
if success { print("SUCCESSFULLY OPENED DIAL URL") }
else { print("COULDN'T OPEN DIAL URL") }
}
Objective-C, iOS 11
// 1) set up the dial sequence as a String
NSString *dialSequence = #"*199*123456789#";
// 2) "percent encode" the dial sequence with the "URL Host Allowed" character set
NSCharacterSet *urlHostAllowed = [NSCharacterSet URLHostAllowedCharacterSet];
NSString *encodedDialSequence = [dialSequence stringByAddingPercentEncodingWithAllowedCharacters:urlHostAllowed];
// 3) add the 'tel:' url scheme to the front of the encoded string
// NOTE: the '//' part is optional: either 'tel:' or 'tel://' will work.
NSString *dialURLString = [NSString stringWithFormat:#"tel:%#", encodedDialSequence];
// 4) set up the URL with the scheme+encoded number string
NSURL *dialURL = [NSURL URLWithString:dialURLString];
// 5) set up an empty dictionary for the options parameter
NSDictionary *optionsDict = [[NSDictionary alloc] init];
// 6) dial the URL
[[UIApplication sharedApplication] openURL:dialURL
options:optionsDict
completionHandler:^(BOOL success) {
if (success) { NSLog(#"SUCCESSFULLY OPENED DIAL URL"); }
else { NSLog(#"COULDN'T OPEN DIAL URL"); }
}];
Replace * with %2A and # with %23:
NSURL *tel = [NSURL URLWithString:#"tel:%2A199%2A123456789%23"];
[[UIApplication sharedApplication] openURL:tel];
You need to use tel:// not just tel: