Essentials icon indicating copy to clipboard operation
Essentials copied to clipboard

Email.ComposeAsync is not using the Default Mail App under IOS 14

Open rchavezn opened this issue 5 years ago • 29 comments

Bug report best practices: Submitting Issues

Description

The Email library in Xamarin Essentials does not use the Default Mail App when Composing Email Messages. In IOS 14 it defaults to Mail. In IOS 14.1 it throws a Feature Not Supported Exception.

Steps to Reproduce - IOS 14

  1. Using IOS 14, set Outlook as your Default Email App.
  2. Send an Email using Xamarin.Essentials.Email.ComposeAsync

Expected Behavior

ComposeAsync should use the Default Mail App as defined in IOS settings. In this particular case, it should have open the Compose dialog in in Outlook

Actual Behavior

Email opens up in Mail

Steps to Reproduce - IOS 14.01

  1. Using IOS 14.01, set Outlook as your Default Email App.
  2. Send an Email using Xamarin.Essentials.Email.ComposeAsync

Expected Behavior

ComposeAsync should use the Default Mail App as defined in IOS settings. In this particular case, it should have open the Compose dialog in in Outlook

Actual Behavior

No email opens up. Application throws a FeatureNotSupportedException

Basic Information

  • Version with issue:
  • Last known good version: N/A. Default Mail App is a new Feature in IOS
  • IDE: Visual Studio for Mac 8.8 build 2120
  • Platform Target Frameworks:
    • iOS: 14.01
  • Nuget Packages: Xamarin.Essentials 1.5.3.2
  • Affected Devices: iPad, likely iPhones running IOS 14+

rchavezn avatar Sep 29 '20 14:09 rchavezn

Thanks for writing in, yeah this is a complicated one....

Even though iOS 14 has a new "default" app... we use MFMailComposeViewController for the Email api, which will always use the apple email app -> https://developer.apple.com/forums/thread/653146 via what this thread says. You can use Launcher and "mailto:"

So, the recommended route would be to try to use the email app and then fallback to Launcher with mailto:

@mattleibow any thoughts on this?

jamesmontemagno avatar Sep 29 '20 15:09 jamesmontemagno

So if I understand this issue, if the default app is NOT Apple, then it is false? And always false? Even when I have an account set up in the mail app?

Basically, is there a way to detect if the Apple app is not the default vs not used at all?

mattleibow avatar Sep 30 '20 01:09 mattleibow

Yeah so we could potentially check MFMailComposeViewController.CanSendEmail to see if it's false, and if so we can do mailto: instead?

Redth avatar Oct 01 '20 18:10 Redth

Ahh we already do this.

I'm not sure there is anything we need to or can do here?

Redth avatar Oct 01 '20 18:10 Redth

The OP says:

In IOS 14.1 it throws a Feature Not Supported Exception

Interesting...

@rchavezn maybe the NuGet is not being installed into the app properly?

mattleibow avatar Oct 01 '20 18:10 mattleibow

Yeah, i mean we just have to document it that is all you know.

jamesmontemagno avatar Oct 02 '20 23:10 jamesmontemagno

I assume if the user deletes the Mail app then it would return false there....

jamesmontemagno avatar Oct 02 '20 23:10 jamesmontemagno

The only other hack around would be to introduce a flag or option on ios not to use it... but idk

jamesmontemagno avatar Oct 02 '20 23:10 jamesmontemagno

I actually just was reading about known issues in iOS 14:

Apps that rely on MFMailComposeViewController will be directed to the Mail app even when the default mail app is set to a different mail app. This is an iOS14 issue, Apple is aware of the issue.

also:

mailto:// links will launch the Mail app if the Mail app has an account profile, even when the default mail app is set to a different mail app. This is an iOS14 issue, Apple is aware of the issue.

https://blog.expta.com/2020/09/list-of-known-issues-with-ios-14.html

Not sure how legit it is......

jamesmontemagno avatar Oct 02 '20 23:10 jamesmontemagno

I just updated to iOS 14.1 and we shall see what happens. Hopefully we can do something here.

mattleibow avatar Oct 23 '20 00:10 mattleibow

I think I see something even more worrying...

In our check, we have UIApplication.SharedApplication.CanOpenUrl(NSUrl.FromString("mailto:")). That returns false. But, if I remove that, the Outlook app still opens to the compose screen. There are no attachments, since there is no way to do that via a URI, but it still opens.

So why did CanOpenUrl return false?

mattleibow avatar Oct 23 '20 14:10 mattleibow

Looking at the docs, I think I found out the issue. You can't query from mailto:// unless you declare it in the plist:

	<key>LSApplicationQueriesSchemes</key>
	<array>
		<string>mailto</string>
	</array>

If your app is linked on or after iOS 9.0, you must declare the URL schemes you pass to this method by adding the LSApplicationQueriesSchemes key to your app's Info.plist file. This method always returns NO for undeclared schemes, whether or not an appropriate app is installed.

https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl?language=objc#discussion

mattleibow avatar Oct 23 '20 19:10 mattleibow

I tested with just a mailto:// and a default mail app of Outlook AND have an account set up in Mail. So the only issue right now is the fact that MFMailComposeViewController will always open the Mail app. I am not sure if there is a way to detect the default mail app.

mattleibow avatar Oct 23 '20 19:10 mattleibow

I don't think "ComposeWithUrl" supports attachments either.

We could put in a setting in EmailMessage for "BuiltIn" or "System" lol... kinda like browser....

I'll document the key.

jamesmontemagno avatar Oct 25 '20 01:10 jamesmontemagno

I don't think that there is a way to detect it at all. We could introduce this enum in there and default to systemprefered as the default.

jamesmontemagno avatar Oct 25 '20 01:10 jamesmontemagno

🤢

I think we need to take a step back and see what we are trying to do. What would an iOS dev using swift do? Just drop attachment support across the board? Or do we say that there is less chance of a user having BOTH Mail and Outlook? Or do we add an enum as @jamesmontemagno suggests and have the option to basically say "always ignore the default if there is a system app". I suppose there will be some sort of control...

mattleibow avatar Oct 26 '20 15:10 mattleibow

So im seeing a slightly different issue, when I add "mailto" to the LSApplicationQueriesSchemes it properly opens the default mail app (Gmail in this case) but the "to" field doesn't populate. Is anyone else seeing this?

JaridKG avatar Nov 11 '20 22:11 JaridKG

@JaridKG Which version is this happening on?

mattleibow avatar Nov 12 '20 23:11 mattleibow

@mattleibow 1.5.3.2

JaridKG avatar Nov 16 '20 18:11 JaridKG

@JaridKG, just tested with Outlook, I get the To. Testing with Gmail...

mattleibow avatar Nov 16 '20 21:11 mattleibow

@JaridKG ~it might be a bug with Gmail as nothing works... But it all works with Outlook.~

EDIT: I think I had a bad setup. I reset and now I see your problem.

mattleibow avatar Nov 16 '20 21:11 mattleibow

@JaridKG I think I have fixed it, and it works on all the platforms (need to restart my PC to test Tizen) on both Google and Outlook.

mattleibow avatar Nov 16 '20 22:11 mattleibow

Cool! Yeah was working with outlook for us, luckily one of our QA Guys had Gmail as his default client

JaridKG avatar Nov 16 '20 22:11 JaridKG

I've tested Essentials 1.6.1-preview1 and using iOS 14.3 on a physical iPhone 7 my app loads Mail and not the Default Mail App which is set to Outlook.

Not sure if the fix is included in Essentials 1.6.1-preview1, or still pending.

DawidBester avatar Jan 20 '21 10:01 DawidBester

@JaridKG I confirmed empty To field issue when no account configured for Mail.app and Gmail is installed. It reproduced on Japan's COVID-19 Contact-Confirming Application. https://github.com/cocoa-mhlw/cocoa/issues/18

ypresto avatar Feb 03 '21 11:02 ypresto

Yes, this is on Apple's end still.

The only real work around is to call "mailto:" directly with launcher.

jamesmontemagno avatar Feb 03 '21 23:02 jamesmontemagno

So a work around is by going into settings on iOS, tapping your name, tapping iCloud and disabling Mail (if you don't have Mail installed, you will need to do so before this step, after installing Mail you may need to reboot your device).

Next you need to set Outlook as your default mail app.

From there Xamarin should be able to launch Outlook as expected.

I know this is a little convoluted, but if you work in corporate and can control such variables it is a workaround at least.

wil313 avatar Mar 10 '21 17:03 wil313

When Outlook is the Default Mail App on my test iPhone, setting message.BodyFormat = EmailBodyFormat.PlainText and calling await Email.ComposeAsync(message) launches Outlook as expected. Note: I also had to also disable Mail in iCloud.

When Outlook is the Default Mail App on the same device, setting message.BodyFormat = EmailBodyFormat.Html results in a FeatureNotSupportedException when calling await Email.ComposeAsync(message) .

Unfortunately when using message.BodyFormat = EmailBodyFormat.PlainText email attachments are not added when Outlook launches.

So on FeatureNotSupportedException my workaround is to Share the attachment file, which allows the user to choose how they want to share the attachment:

await Share.RequestAsync(new ShareFileRequest
 {
                                    Title = subject,
                                    File = new ShareFile(emailAttachment)
});

DawidBester avatar Mar 16 '21 03:03 DawidBester

@DawidBester

I witness slightly different behaviour while running iOS 15 on an iPhone 6s. Despite disabling iCloud-Mail, uninstalling Mail and setting Outlook as the default mail program the API prompts to navigate to the APP store to set up the Mail app.

Unfortunately when using message.BodyFormat = EmailBodyFormat.PlainText email attachments are not added when Outlook launches.

Are you sure the cause lies within the BodyFormat property/Have you ever gotten Outlook to actually receive attachments through the E-Mail API (not the Share API)?

Though unable to reproduce atm with my current device, falling back to "mailto:" by default is actually a huge pitfall as it doesn't support attachments as @jamesmontemagno correctly pointed out. That being said, I wonder if the default fallback implemented here should rather be something in control of calling via URL if desired. I'd rather force a user to install the Mail app then have attachments not being sent at all.

marwalsch avatar Aug 17 '22 10:08 marwalsch