Как (правильно) создать URL-адрес mailto (URI) в Java?

Дано:

String email1 = "[email protected]";

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

Каков наилучший/правильный способ создания mailto: URI (в форме объекта String)?

Я пробовал:

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

Это ближайший я получил, но он не кодирует вопросительный знак (?) в локальной части адреса электронной почты, но согласно RFC 6068. Он также терпит неудачу на примерах в RFC, например, "[email protected]" @example.org" или маловероятно[email protected]

[1] Valid_email_addresses examples

PS: Есть некоторая полезная информация в Должны ли плюс быть закодированы в mailto: гиперссылки?


Я решил для этого как решение:

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();

Ответы

Ответ 1

Вы должны вручную процитировать/вывести ? и &.

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

Поэтому кажется, что символы ? и & не корректно экранированы в URI. Все, что после ? игнорируется в URI, потому что этот символ зарезервирован для "строк запроса" в URL-адресах. Ссылка здесь.

В соответствии с this и справочными документами нам нужно также выйти &. По какой-то причине Java не делает этого для нас. Фактически, RFC 6068 даже утверждает:

Число символов, которые могут отображаться в ДОЛЖНО быть        проценты-кодированию. Это символы, которые не могут        URI в соответствии с [STD66], а также "%" (поскольку он используется для        процентное кодирование) и всех символов в gen-delims кроме "@"        и ":" (т.е. "/", "?", "#", "[" и "]" ). Из персонажей        в суб-делимах, по крайней мере, следующие также должны быть процентами,        закодированы: "&", ";" и "=".

Способ исправления (в некоторой степени взлома, но он работает) заключается в том, чтобы вручную вывести эти символы с помощью %, за которым следует двухзначное шестнадцатеричное значение ASCII для символа. Ссылка this.

Я протестировал, вставив полученную строку в Chrome и правильно открыл свой email по умолчанию с сообщением электронной почты

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

Дополнительные исследования

Итак, кажется, что Java URI-класс использует RFC 2396, в котором говорится:

Если данные для компонента URI будут конфликтовать с    зарезервированной цели, тогда конфликтующие данные должны быть экранированы до    формирование URI.

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

"Сдержанный" класс синтаксиса выше относится к тем символам, которые    разрешено внутри URI, но который может не допускаться в пределах    конкретный компонент общего синтаксиса URI;

Ответ 2

Вам нужно будет использовать Apache Commons URI builder

Ожидается, что значение будет неизолировано и может содержать не ASCII символы.

Вы не можете напрямую использовать класс java uri Java URI doc говорит
Все знаки пунктуации зарезервированы вместе с символами в строке "?/[] @" ​​ зарезервировано.

Java URI class использует RFC 2396, в котором говорится: если данные для компонента URI будут конфликтовать с    зарезервированной цели, тогда конфликтующие данные должны быть экранированы до    формирование URI.

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

Вы можете использовать java.net.URLEncoder для кодирования имени пользователя, а затем используйте закодированное имя пользователя для создания URI String uri = new URI("mailto", the_email_address, null).toString();или
Вы можете вручную процитировать/убрать код? и &.

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

В JavaScript вы можете использовать функцию encodeURI(). PHP имеет rawurlencode(), а ASP имеет функцию Server.URLEncode().


Ответ 3

Вероятно, вы захотите использовать статический метод URI.create(String uri), чтобы создать свой почтовый uri, вместо использования "нового" конструктора. Например, это возвращает допустимый URI (я использую jdk 7):

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

Надеюсь, это поможет.

Приветствия.