How to (correctly) create mailto URL (URI) in Java?
Asked Answered
G

3

17

Given:

String email1 = "[email protected]";

// legal email address according to wikipedia [1]
String email2 = "\"()<>[]:,;@\\\"!#$%&'*+-/=?^_`{}| ~.a\"@example.org";

What is the best/correct way to create a mailto: URI (in the form of a String object)?

I tried:

String uri = new URI("mailto", the_email_address, null).toString();

This is the closest I got, but it does not encode the question-mark (?) in the local part of the email address, but according to RFC 6068 it should. It also fails on examples in the RFC, like "not@me"@example.org or [email protected].

[1] Valid_email_addresses examples

PS: There is some useful information in Should plus be encoded in mailto: hyperlinks?


I settled for this as a solution:

import org.apache.http.client.utils.URIBuilder;
// from Apache HttpClient
// maven group: org.apache.httpcomponents artifact: httpclient

String emailURL = new URIBuilder().setScheme("mailto").setPath(the_email_address).toString();
Gaytan answered 8/5, 2015 at 21:39 Comment(3)
I notice that your example is creating a URI from email1 however it does not have a question mark, did you mean to use email2?Subarctic
The question mark is in other example. That comment was general: the used method doesn't work if the mail address has a question mark in it.Beisel
@DavidBalažic are you not able to use Apache commons URI builder? or is ur requirement different?Landbert
C
12

You have to manually percent encode/escape the ? and &.

String email2 = "\"()<>[]:,;@\\\"!#$%&'*+-/=?^_`{}| ~.a\"@example.org";
String uri2 = (new URI("mailto", email2, null)).toString().replace("?", "%3F").replace("&", "%26");

So it seems that the ? and & symbols are not being correctly escaped in the URI. Anything after the ? is ignored in the URI because that symbol is reserved for "query strings" in URLs. Reference here.

According to this and the reference documents, we need to escape & as well. For some reason, Java is not doing that for us. In fact, RFC 6068 even states:

A number of characters that can appear in MUST be percent-encoded. These are the characters that cannot appear in a URI according to [STD66] as well as "%" (because it is used for percent-encoding) and all the characters in gen-delims except "@" and ":" (i.e., "/", "?", "#", "[", and "]"). Of the characters in sub-delims, at least the following also have to be percent- encoded: "&", ";", and "=".

The way to fix it (somewhat of a hack, but it works) is to manually escape these characters using a % followed by 2 digit ASCII hex value for symbol. Reference this.

I tested by pasting the resulting string into Chrome and it correctly opened up my default email with an email to

"()<>[]:,; @\"!#$%&'*+-/=?^_`{}| ~.a"@example.org

More Research

So it seems that Java's URI class uses RFC 2396, which states:

If the data for a URI component would conflict with the reserved purpose, then the conflicting data must be escaped before forming the URI.

 reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
            "$" | ","

The "reserved" syntax class above refers to those characters that are allowed within a URI, but which may not be allowed within a particular component of the generic URI syntax;

Cholon answered 15/5, 2015 at 12:59 Comment(0)
L
4

You will have to use Apache Commons URI builder

The value is expected to be unescaped and may contain non ASCII characters.

You can not directly use java uri class Java URI doc says
All punctuation characters are Reserved together with those in the string "?/[]@" are reserved.

Java's URI class uses RFC 2396, which states:If the data for a URI component would conflict with the reserved purpose, then the conflicting data must be escaped before forming the URI.

 reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
            "$" | ","

You can use java.net.URLEncoder to encode the user_name and then use encoded username to create the URI String uri = new URI("mailto", the_email_address, null).toString(); or
You can manually percent encode/escape the ? and &.

String email2 = "\"()<>[]:,;@\\\"!#$%&'*+-/=?^_`{}| ~.a\"@example.org";
String uri2 = (new URI("mailto", email2, null)).toString().replace("?", "%3F").replace("&", "%26");

In JavaScript you can use the encodeURI() function. PHP has the rawurlencode() function, and ASP has the Server.URLEncode() function.


Landbert answered 18/5, 2015 at 10:40 Comment(0)
O
0

You probably want to use the URI.create(String uri) static method to create your mailto uri, instead of using the "new" constructor. For example, this returns a valid URI (I'm using jdk 7):

URI.create("mailto:[email protected]");

I hope it helps.

Cheers.

Onomasiology answered 20/5, 2015 at 23:42 Comment(1)
JavaDoc says: "This method is provided for use in situations where it is known that the given string is a legal URI" So I can use this method, when I already have a solution. ;)Beisel

© 2022 - 2024 — McMap. All rights reserved.