Fix issue 6269: IMAP LOGIN failure

Some IMAP servers are broken and don't correctly handle string
literals with the LOGIN command.

This switches to using quoted strings instead.

This is what Thunderbird does.
This commit is contained in:
Joe Steele 2014-03-11 19:06:00 -04:00
parent 18da76f4aa
commit a7898fa2eb
1 changed files with 17 additions and 23 deletions

View File

@ -46,6 +46,7 @@ import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
@ -127,7 +128,6 @@ public class ImapStore extends Store {
private static final String CAPABILITY_AUTH_CRAM_MD5 = "AUTH=CRAM-MD5";
private static final String CAPABILITY_AUTH_PLAIN = "AUTH=PLAIN";
private static final String CAPABILITY_LOGINDISABLED = "LOGINDISABLED";
private static final String CAPABILITY_LITERAL_PLUS = "LITERAL+";
private static final String COMMAND_IDLE = "IDLE";
private static final String CAPABILITY_NAMESPACE = "NAMESPACE";
private static final String COMMAND_NAMESPACE = "NAMESPACE";
@ -2655,29 +2655,23 @@ public class ImapStore extends Store {
}
protected void login() throws IOException, MessagingException {
boolean hasLiteralPlus = hasCapability(CAPABILITY_LITERAL_PLUS);
String tag;
byte[] username = mSettings.getUsername().getBytes();
byte[] password = mSettings.getPassword().getBytes();
tag = sendCommand(String.format(Locale.US, "LOGIN {%d%s}",
username.length, hasLiteralPlus ? "+" : ""), true);
if (!hasLiteralPlus) {
readContinuationResponse(tag);
}
mOut.write(username);
mOut.write(String.format(Locale.US, " {%d%s}\r\n", password.length,
hasLiteralPlus ? "+" : "").getBytes());
if (!hasLiteralPlus) {
mOut.flush();
readContinuationResponse(tag);
}
mOut.write(password);
mOut.write('\r');
mOut.write('\n');
mOut.flush();
/*
* Use quoted strings which permit spaces and quotes. (Using IMAP
* string literals would be better, but some servers are broken
* and don't parse them correctly.)
*/
// escape double-quotes and backslash characters with a backslash
Pattern p = Pattern.compile("[\\\\\"]");
String replacement = "\\\\$0";
String username = p.matcher(mSettings.getUsername()).replaceAll(
replacement);
String password = p.matcher(mSettings.getPassword()).replaceAll(
replacement);
try {
receiveCapabilities(readStatusResponse(tag, "LOGIN", null));
} catch (MessagingException e) {
receiveCapabilities(executeSimpleCommand(
String.format("LOGIN \"%s\" \"%s\"", username, password), true));
} catch (ImapException e) {
throw new AuthenticationFailedException(e.getMessage());
}
}