Sdk: Uri.toString() for "mailto" does not encode spaces properly (`+` instead of `%20`)

Created on 17 Oct 2020  路  4Comments  路  Source: dart-lang/sdk

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?

area-library library-core

Most helpful comment

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.

All 4 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

55555Mohit55555 picture 55555Mohit55555  路  3Comments

sgrekhov picture sgrekhov  路  3Comments

nex3 picture nex3  路  3Comments

gspencergoog picture gspencergoog  路  3Comments

jmesserly picture jmesserly  路  3Comments