Как (правильно) создать 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]");
Надеюсь, это поможет.
Приветствия.