Hi.
This ticket was first opened on flutter bug tracker: https://github.com/flutter/flutter/issues/68406
It seems Uri.toString() convert spaces to + in subject and body for mailto scheme.
final uri = Uri(
scheme: 'mailto',
path: '[email protected]',
queryParameters: {
'subject': 'Example Subject & Symbols are allowed!'
}
);
print(uri.toString());
// mailto:[email protected]?subject=Example+Subject+%26+Symbols+are+allowed%21
This seems to be a problem, when the link is opened with url_launcher for example then the subject displayed in the mail app is like this:
Example+Subject+&+Symbols+are+allowed!
For some reason, the app does not handle + symbols in the uri as expected. However, it works fine if %20 is used instead.
I tested this with url_launcher v5.7.5, flutter v1.23.0, dart v2.10.0, Android v8.0.0 and opening the link with Gmail app.
Should the spaces be automatically converted to %20 instead to ensure portability?
The Dart Uri class does not recognize most schemes specially. The mailto: scheme is treated the same as any other scheme, so the query part is encoded using URL encoding, which is why it uses + for spaces.
Same here. How to fix it?
The lazy approach would be:
print(uri.toString().replaceAll("+", "%20"));
A more intricate approach could be:
final uri = Uri.parse('mailto:[email protected]?subject=' +
'Example Subject & Symbols are allowed!'.replaceAll(" ", "%20"));
print(uri.toString());
or
final uri = Uri(
scheme: 'mailto',
path: '[email protected]',
query:
'subject=Example Subject & Symbols are allowed!'.replaceAll(" ", "%20")
);
print(uri.toString());
There currently is no way to use the queryParameters argument and get what you want. There is no way to configure the URI to not use standard URL encoding for query parameters.
(If we do a complete rewrite of the Uri class at some point, which we want to for several reasons, mainly compatibility with the browser Url class, then we will likely start recognizing "web" URIs - http and web sockets - specifically, and not treat all other URIs as if they are necessarily the same as HTTP. Until such time, we are unlikely to make any breaking changes to the Uri class.)
I'm personally constructing the uri string myself by calling Uri.encodeComponent() for each parameter. It encodes " " to "%20" while Uri.encodeQueryComponent() (which I guess is used internally by Uri.toString()) encodes it to "+".
final subject = Uri.encodeComponent("Example Subject & Symbols are allowed!")
final uri = "mailto:[email protected]?subject=$subject";
It seems to work fine.
Most helpful comment
I'm personally constructing the
uristring myself by callingUri.encodeComponent()for each parameter. It encodes" "to"%20"whileUri.encodeQueryComponent()(which I guess is used internally byUri.toString()) encodes it to"+".It seems to work fine.