Мне нужна помощь со следующим вопросом:
Мне нужно выполнить поиск, используя не-ascii символы на Gmail ( Кириллица (например Русский или Украинский ) ). Когда я использую стандартную команду IMAP SEARCH, я получаю сообщение об ошибке:
A12 SEARCH CHARSET UTF-8 SUBJECT "текст" ALL
A12 BAD Could not parse command
В Java это выглядит как
Message[] foundMessages = imapFolder.search(new SubjectTerm("текст"));
Здесь я нашел некоторую помощь Поиск в IMAP не-ascii символов . Используя openssl s_client -crlf -connect imap.gmail.com:993
Я подключился к своему почтовому ящику через Terminal и получил следующие результаты:
A12 SEARCH CHARSET UTF-8 X-GM-RAW {10}
+ go ahead
текст
* SEARCH 226
A13 OK SEARCH completed (Success)
Главный вопрос - как это реализовать на Java?
UPDATE
Я провел некоторые исследования исходного кода JavaMail. Я нашел следующие строки
// if server supports UTF-8, enable it for client use
// note that this is safe to enable even if mail.mime.allowutf8=false
if (p.hasCapability("UTF8=ACCEPT") || p.hasCapability("UTF8=ONLY"))
p.enable("UTF8=ACCEPT");
}
и с сервера Gmail мы получаем следующие возможности
A1 LOGIN test@gmail.com password
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN
X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE ENABLE MOVE CONDSTORE ESEARCH
UTF8=ACCEPT LIST-EXTENDED LIST-STATUS
LITERAL-SPECIAL-USE APPENDLIMIT=35651584
Итак, JavaMail автоматически устанавливает mail.mime.allowutf8
в true
. Но в этом случае JavaMail выполняет поиск с помощью следующей команды
C6 SEARCH CHARSET UTF-8 X-GM-RAW "текст" ALL
И я получаю ошибку
C6 BAD Could not parse command
Я пошел вперед и исследовал
https://github.com/javaee/javamail/blob/52e04fc107d0b83fa794e6f622f7c76b9e85e395/mail/src/main/java/com/sun/mail/iap/Argument.java#L313
Argument.nastring(byte[] bytes, Protocol protocol, boolean doQuote)
boolean utf8 = protocol.supportsUtf8 (); -> Для Gmail это правда . Вот почему JavaMail не использует литерал.
byte b;
for (int i = 0; i < len; i++) {
b = bytes[i];
if (b == '\0' || b == '\r' || b == '\n' ||
(!utf8 && ((b & 0xff) > 0177))) {
// NUL, CR or LF means the bytes need to be sent as literals
literal(bytes, protocol);
return;
}
if (b == '*' || b == '%' || b == '(' || b == ')' || b == '{' ||
b == '"' || b == '\\' ||
((b & 0xff) <= ' ') || ((b & 0xff) > 0177)) {
quote = true;
if (b == '"' || b == '\\') // need to escape these characters
escape = true;
}
}
Я проверил другого провайдера электронной почты, у которого нет UTF8=ACCEPT
. И все отлично работает.
K11 SEARCH CHARSET UTF-8 SUBJECT {10}
+ continue
текст ALL
* SEARCH 1194
K11 OK SEARCH completed