2008-11-01 17:32:06 -04:00
|
|
|
|
2014-12-18 03:33:09 -05:00
|
|
|
package com.fsck.k9.mail.store.pop3;
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2015-01-05 17:24:24 -05:00
|
|
|
import android.annotation.SuppressLint;
|
2008-11-01 17:32:06 -04:00
|
|
|
import android.util.Log;
|
2010-03-03 23:00:30 -05:00
|
|
|
|
2009-12-14 21:50:53 -05:00
|
|
|
import com.fsck.k9.mail.*;
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
import com.fsck.k9.mail.filter.Base64;
|
|
|
|
import com.fsck.k9.mail.filter.Hex;
|
2009-12-14 21:50:53 -05:00
|
|
|
import com.fsck.k9.mail.internet.MimeMessage;
|
2014-12-17 09:28:48 -05:00
|
|
|
import com.fsck.k9.mail.CertificateValidationException;
|
2014-12-12 10:02:59 -05:00
|
|
|
import com.fsck.k9.mail.MessageRetrievalListener;
|
2015-03-08 07:05:53 -04:00
|
|
|
import com.fsck.k9.mail.ServerSettings.Type;
|
2014-12-17 11:42:22 -05:00
|
|
|
import com.fsck.k9.mail.ssl.TrustedSocketFactory;
|
2014-12-18 03:33:09 -05:00
|
|
|
import com.fsck.k9.mail.store.RemoteStore;
|
|
|
|
import com.fsck.k9.mail.store.StoreConfig;
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2009-12-09 22:16:42 -05:00
|
|
|
import javax.net.ssl.SSLException;
|
2014-02-28 12:47:43 -05:00
|
|
|
|
2009-12-09 22:16:42 -05:00
|
|
|
import java.io.*;
|
|
|
|
import java.net.*;
|
|
|
|
import java.security.GeneralSecurityException;
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
import java.security.MessageDigest;
|
|
|
|
import java.security.NoSuchAlgorithmException;
|
2009-12-09 22:16:42 -05:00
|
|
|
import java.util.ArrayList;
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
import java.util.Arrays;
|
2014-10-04 05:37:30 -04:00
|
|
|
import java.util.Collections;
|
2010-05-30 17:20:47 -04:00
|
|
|
import java.util.Date;
|
2010-04-21 22:20:35 -04:00
|
|
|
import java.util.LinkedList;
|
2009-12-09 22:16:42 -05:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashSet;
|
2010-04-21 22:20:35 -04:00
|
|
|
import java.util.List;
|
2014-03-03 10:40:23 -05:00
|
|
|
import java.util.Locale;
|
2011-06-28 07:20:48 -04:00
|
|
|
import java.util.Map;
|
2014-02-15 17:48:35 -05:00
|
|
|
import java.util.Set;
|
2009-12-09 22:16:42 -05:00
|
|
|
|
2014-12-16 06:51:52 -05:00
|
|
|
import static com.fsck.k9.mail.K9MailLib.DEBUG_PROTOCOL_POP3;
|
|
|
|
import static com.fsck.k9.mail.K9MailLib.LOG_TAG;
|
2014-12-17 09:28:48 -05:00
|
|
|
import static com.fsck.k9.mail.CertificateValidationException.Reason.MissingCapability;
|
2014-12-16 06:51:52 -05:00
|
|
|
|
2014-12-11 22:23:32 -05:00
|
|
|
public class Pop3Store extends RemoteStore {
|
2011-06-06 22:07:50 -04:00
|
|
|
|
2011-07-17 08:13:04 -04:00
|
|
|
private static final String STLS_COMMAND = "STLS";
|
|
|
|
private static final String USER_COMMAND = "USER";
|
|
|
|
private static final String PASS_COMMAND = "PASS";
|
2011-08-28 18:25:47 -04:00
|
|
|
private static final String CAPA_COMMAND = "CAPA";
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
private static final String AUTH_COMMAND = "AUTH";
|
2011-07-17 08:13:04 -04:00
|
|
|
private static final String STAT_COMMAND = "STAT";
|
|
|
|
private static final String LIST_COMMAND = "LIST";
|
|
|
|
private static final String UIDL_COMMAND = "UIDL";
|
|
|
|
private static final String TOP_COMMAND = "TOP";
|
|
|
|
private static final String RETR_COMMAND = "RETR";
|
|
|
|
private static final String DELE_COMMAND = "DELE";
|
|
|
|
private static final String QUIT_COMMAND = "QUIT";
|
|
|
|
|
|
|
|
private static final String STLS_CAPABILITY = "STLS";
|
|
|
|
private static final String UIDL_CAPABILITY = "UIDL";
|
|
|
|
private static final String TOP_CAPABILITY = "TOP";
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
private static final String SASL_CAPABILITY = "SASL";
|
|
|
|
private static final String AUTH_PLAIN_CAPABILITY = "PLAIN";
|
|
|
|
private static final String AUTH_CRAM_MD5_CAPABILITY = "CRAM-MD5";
|
2014-05-25 16:45:14 -04:00
|
|
|
private static final String AUTH_EXTERNAL_CAPABILITY = "EXTERNAL";
|
2008-11-01 17:32:06 -04:00
|
|
|
|
|
|
|
/**
|
2011-06-06 18:08:43 -04:00
|
|
|
* Decodes a Pop3Store URI.
|
|
|
|
*
|
|
|
|
* <p>Possible forms:</p>
|
|
|
|
* <pre>
|
2014-05-25 16:45:14 -04:00
|
|
|
* pop3://auth:user:password@server:port ConnectionSecurity.NONE
|
|
|
|
* pop3+tls+://auth:user:password@server:port ConnectionSecurity.STARTTLS_REQUIRED
|
|
|
|
* pop3+ssl+://auth:user:password@server:port ConnectionSecurity.SSL_TLS_REQUIRED
|
2011-06-06 18:08:43 -04:00
|
|
|
* </pre>
|
2008-11-01 17:32:06 -04:00
|
|
|
*/
|
2011-06-07 10:09:15 -04:00
|
|
|
public static ServerSettings decodeUri(String uri) {
|
2011-06-06 18:08:43 -04:00
|
|
|
String host;
|
|
|
|
int port;
|
|
|
|
ConnectionSecurity connectionSecurity;
|
|
|
|
String username = null;
|
|
|
|
String password = null;
|
2014-05-25 16:45:14 -04:00
|
|
|
String clientCertificateAlias = null;
|
2011-06-06 18:08:43 -04:00
|
|
|
|
|
|
|
URI pop3Uri;
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2011-06-06 18:08:43 -04:00
|
|
|
pop3Uri = new URI(uri);
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (URISyntaxException use) {
|
2011-06-06 18:08:43 -04:00
|
|
|
throw new IllegalArgumentException("Invalid Pop3Store URI", use);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
2011-06-06 18:08:43 -04:00
|
|
|
String scheme = pop3Uri.getScheme();
|
Eliminate the 'if available' connection security options
These options originated in the AOSP email client from which K-9 Mail was
forked. They provide an odd combination of 2 features:
1. Don't bother to authenticate the server's certificate (applies to both
SSL/TLS and STARTTLS); i.e., blindly accept all certificates. This is
generally a bad security policy which is susceptible to MITM attacks.
2. If STARTTLS is selected but the server doesn't claim to support
STARTTLS, then proceed without using encryption. This, too, is a bad
security policy which is susceptible to MITM attacks.
Since the time that K-9 Mail was forked, a couple things have changed:
> K-9 Mail has implemented the ability for users to review and permanently
accept individual certificates that would otherwise fail authentication.
With this ability, there is no need for a user to subject themselves to
the ongoing risks of feature 1. above. Hence, this commit removes feature
1.
> The AOSP email client has changed its behavior and no longer permits a
security downgrade to an unencrypted connection if the server doesn't
claim to support STARTTLS (i.e., they eliminated feature 2. above). K-9
Mail should do the same. It's unlikely that a server is going to provide
STARTTLS on an intermittent basis, so providing a contingency for such
unusual behavior is an unnecessary risk. Hence, this commit removes that
feature as well.
Effect on existing users:
If the old connection security setting was "SSL/TLS (if available)" (which
now gets remapped to "SSL/TLS"), and the server does not provide a
certificate that can be authenticated, then a "Certificate error for
<account name>" notification is generated telling the user to check their
server settings. Tapping the notification takes the user to the relevant
server settings, where the user can tap "Next" to review the certificate
and choose to permanently accept it. This process would occur during the
first syncing of folders after application upgrade or (in the case of
SMTP) during the first attempt to send a message.
If the connection security setting was "STARTTLS (if available)" (which
now gets remapped to "STARTTLS"), and the server does not provide a
certificate that can be authenticated, then the same process as above
would occur.
If the old connection security setting was "STARTTLS (if available)", and
the server doesn't claim to support STARTTLS, then the user would get a
certificate error notification which would lead them to the server's
settings. There they would need to choose a different connection security
-- most likely "NONE". If they didn't change anything but instead just
tapped "Next", the server settings would be checked again and a dialog
would pop up saying, "Cannot connect to server. (STARTTLS connection
security not available)". (The implementation of notifications when
STARTTLS is not available is not actually included here -- it's in the
commit that follows.)
Regarding the changes to providers.xml: in cases where the scheme ended
with "+ssl", the schemes were simply updated by appending "+". In cases
where the scheme ended with "+tls", a check of the server was made to
assure that STARTTLS was available before appending "+" to the scheme.
Domains paran.com and nate.com failed the check and were removed because
no current information could be found. Domains me.com and mac.com also
failed and were updated based on http://support.apple.com/kb/ht4864.
2014-02-26 16:50:21 -05:00
|
|
|
/*
|
|
|
|
* Currently available schemes are:
|
|
|
|
* pop3
|
|
|
|
* pop3+tls+
|
|
|
|
* pop3+ssl+
|
|
|
|
*
|
|
|
|
* The following are obsolete schemes that may be found in pre-existing
|
|
|
|
* settings from earlier versions or that may be found when imported. We
|
|
|
|
* continue to recognize them and re-map them appropriately:
|
|
|
|
* pop3+tls
|
|
|
|
* pop3+ssl
|
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
if (scheme.equals("pop3")) {
|
2011-06-06 18:08:43 -04:00
|
|
|
connectionSecurity = ConnectionSecurity.NONE;
|
2015-03-08 07:05:53 -04:00
|
|
|
port = Type.POP3.defaultPort;
|
Eliminate the 'if available' connection security options
These options originated in the AOSP email client from which K-9 Mail was
forked. They provide an odd combination of 2 features:
1. Don't bother to authenticate the server's certificate (applies to both
SSL/TLS and STARTTLS); i.e., blindly accept all certificates. This is
generally a bad security policy which is susceptible to MITM attacks.
2. If STARTTLS is selected but the server doesn't claim to support
STARTTLS, then proceed without using encryption. This, too, is a bad
security policy which is susceptible to MITM attacks.
Since the time that K-9 Mail was forked, a couple things have changed:
> K-9 Mail has implemented the ability for users to review and permanently
accept individual certificates that would otherwise fail authentication.
With this ability, there is no need for a user to subject themselves to
the ongoing risks of feature 1. above. Hence, this commit removes feature
1.
> The AOSP email client has changed its behavior and no longer permits a
security downgrade to an unencrypted connection if the server doesn't
claim to support STARTTLS (i.e., they eliminated feature 2. above). K-9
Mail should do the same. It's unlikely that a server is going to provide
STARTTLS on an intermittent basis, so providing a contingency for such
unusual behavior is an unnecessary risk. Hence, this commit removes that
feature as well.
Effect on existing users:
If the old connection security setting was "SSL/TLS (if available)" (which
now gets remapped to "SSL/TLS"), and the server does not provide a
certificate that can be authenticated, then a "Certificate error for
<account name>" notification is generated telling the user to check their
server settings. Tapping the notification takes the user to the relevant
server settings, where the user can tap "Next" to review the certificate
and choose to permanently accept it. This process would occur during the
first syncing of folders after application upgrade or (in the case of
SMTP) during the first attempt to send a message.
If the connection security setting was "STARTTLS (if available)" (which
now gets remapped to "STARTTLS"), and the server does not provide a
certificate that can be authenticated, then the same process as above
would occur.
If the old connection security setting was "STARTTLS (if available)", and
the server doesn't claim to support STARTTLS, then the user would get a
certificate error notification which would lead them to the server's
settings. There they would need to choose a different connection security
-- most likely "NONE". If they didn't change anything but instead just
tapped "Next", the server settings would be checked again and a dialog
would pop up saying, "Cannot connect to server. (STARTTLS connection
security not available)". (The implementation of notifications when
STARTTLS is not available is not actually included here -- it's in the
commit that follows.)
Regarding the changes to providers.xml: in cases where the scheme ended
with "+ssl", the schemes were simply updated by appending "+". In cases
where the scheme ended with "+tls", a check of the server was made to
assure that STARTTLS was available before appending "+" to the scheme.
Domains paran.com and nate.com failed the check and were removed because
no current information could be found. Domains me.com and mac.com also
failed and were updated based on http://support.apple.com/kb/ht4864.
2014-02-26 16:50:21 -05:00
|
|
|
} else if (scheme.startsWith("pop3+tls")) {
|
2011-06-06 18:08:43 -04:00
|
|
|
connectionSecurity = ConnectionSecurity.STARTTLS_REQUIRED;
|
2015-03-08 07:05:53 -04:00
|
|
|
port = Type.POP3.defaultPort;
|
Eliminate the 'if available' connection security options
These options originated in the AOSP email client from which K-9 Mail was
forked. They provide an odd combination of 2 features:
1. Don't bother to authenticate the server's certificate (applies to both
SSL/TLS and STARTTLS); i.e., blindly accept all certificates. This is
generally a bad security policy which is susceptible to MITM attacks.
2. If STARTTLS is selected but the server doesn't claim to support
STARTTLS, then proceed without using encryption. This, too, is a bad
security policy which is susceptible to MITM attacks.
Since the time that K-9 Mail was forked, a couple things have changed:
> K-9 Mail has implemented the ability for users to review and permanently
accept individual certificates that would otherwise fail authentication.
With this ability, there is no need for a user to subject themselves to
the ongoing risks of feature 1. above. Hence, this commit removes feature
1.
> The AOSP email client has changed its behavior and no longer permits a
security downgrade to an unencrypted connection if the server doesn't
claim to support STARTTLS (i.e., they eliminated feature 2. above). K-9
Mail should do the same. It's unlikely that a server is going to provide
STARTTLS on an intermittent basis, so providing a contingency for such
unusual behavior is an unnecessary risk. Hence, this commit removes that
feature as well.
Effect on existing users:
If the old connection security setting was "SSL/TLS (if available)" (which
now gets remapped to "SSL/TLS"), and the server does not provide a
certificate that can be authenticated, then a "Certificate error for
<account name>" notification is generated telling the user to check their
server settings. Tapping the notification takes the user to the relevant
server settings, where the user can tap "Next" to review the certificate
and choose to permanently accept it. This process would occur during the
first syncing of folders after application upgrade or (in the case of
SMTP) during the first attempt to send a message.
If the connection security setting was "STARTTLS (if available)" (which
now gets remapped to "STARTTLS"), and the server does not provide a
certificate that can be authenticated, then the same process as above
would occur.
If the old connection security setting was "STARTTLS (if available)", and
the server doesn't claim to support STARTTLS, then the user would get a
certificate error notification which would lead them to the server's
settings. There they would need to choose a different connection security
-- most likely "NONE". If they didn't change anything but instead just
tapped "Next", the server settings would be checked again and a dialog
would pop up saying, "Cannot connect to server. (STARTTLS connection
security not available)". (The implementation of notifications when
STARTTLS is not available is not actually included here -- it's in the
commit that follows.)
Regarding the changes to providers.xml: in cases where the scheme ended
with "+ssl", the schemes were simply updated by appending "+". In cases
where the scheme ended with "+tls", a check of the server was made to
assure that STARTTLS was available before appending "+" to the scheme.
Domains paran.com and nate.com failed the check and were removed because
no current information could be found. Domains me.com and mac.com also
failed and were updated based on http://support.apple.com/kb/ht4864.
2014-02-26 16:50:21 -05:00
|
|
|
} else if (scheme.startsWith("pop3+ssl")) {
|
2011-06-06 18:08:43 -04:00
|
|
|
connectionSecurity = ConnectionSecurity.SSL_TLS_REQUIRED;
|
2015-03-08 07:05:53 -04:00
|
|
|
port = Type.POP3.defaultTlsPort;
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2011-06-06 18:08:43 -04:00
|
|
|
throw new IllegalArgumentException("Unsupported protocol (" + scheme + ")");
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
2011-06-06 18:08:43 -04:00
|
|
|
host = pop3Uri.getHost();
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2011-06-06 18:08:43 -04:00
|
|
|
if (pop3Uri.getPort() != -1) {
|
|
|
|
port = pop3Uri.getPort();
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
2014-02-13 17:18:16 -05:00
|
|
|
AuthType authType = AuthType.PLAIN;
|
2011-06-06 18:08:43 -04:00
|
|
|
if (pop3Uri.getUserInfo() != null) {
|
2014-09-28 06:59:11 -04:00
|
|
|
int userIndex = 0, passwordIndex = 1;
|
|
|
|
String userinfo = pop3Uri.getUserInfo();
|
|
|
|
String[] userInfoParts = userinfo.split(":");
|
|
|
|
if (userInfoParts.length > 2 || userinfo.endsWith(":") ) {
|
|
|
|
// If 'userinfo' ends with ":" the password is empty. This can only happen
|
|
|
|
// after an account was imported (so authType and username are present).
|
|
|
|
userIndex++;
|
|
|
|
passwordIndex++;
|
|
|
|
authType = AuthType.valueOf(userInfoParts[0]);
|
|
|
|
}
|
2014-12-14 10:54:27 -05:00
|
|
|
username = decodeUtf8(userInfoParts[userIndex]);
|
2014-09-28 06:59:11 -04:00
|
|
|
if (userInfoParts.length > passwordIndex) {
|
|
|
|
if (authType == AuthType.EXTERNAL) {
|
2014-12-14 10:54:27 -05:00
|
|
|
clientCertificateAlias = decodeUtf8(userInfoParts[passwordIndex]);
|
2014-09-28 06:59:11 -04:00
|
|
|
} else {
|
2014-12-14 10:54:27 -05:00
|
|
|
password = decodeUtf8(userInfoParts[passwordIndex]);
|
2010-02-01 21:06:29 -05:00
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
2011-06-06 18:08:43 -04:00
|
|
|
|
2015-02-22 16:30:26 -05:00
|
|
|
return new ServerSettings(ServerSettings.Type.POP3, host, port, connectionSecurity, authType, username,
|
2014-05-25 16:45:14 -04:00
|
|
|
password, clientCertificateAlias);
|
2011-06-06 18:08:43 -04:00
|
|
|
}
|
|
|
|
|
2011-06-08 23:50:43 -04:00
|
|
|
/**
|
|
|
|
* Creates a Pop3Store URI with the supplied settings.
|
|
|
|
*
|
|
|
|
* @param server
|
|
|
|
* The {@link ServerSettings} object that holds the server settings.
|
|
|
|
*
|
|
|
|
* @return A Pop3Store URI that holds the same information as the {@code server} parameter.
|
|
|
|
*
|
2014-12-19 03:54:17 -05:00
|
|
|
* @see StoreConfig#getStoreUri()
|
2011-06-08 23:50:43 -04:00
|
|
|
* @see Pop3Store#decodeUri(String)
|
|
|
|
*/
|
|
|
|
public static String createUri(ServerSettings server) {
|
2014-12-14 10:54:27 -05:00
|
|
|
String userEnc = encodeUtf8(server.username);
|
2014-09-28 06:59:11 -04:00
|
|
|
String passwordEnc = (server.password != null) ?
|
2014-12-14 10:54:27 -05:00
|
|
|
encodeUtf8(server.password) : "";
|
2014-09-28 06:59:11 -04:00
|
|
|
String clientCertificateAliasEnc = (server.clientCertificateAlias != null) ?
|
2014-12-14 10:54:27 -05:00
|
|
|
encodeUtf8(server.clientCertificateAlias) : "";
|
2011-06-08 23:50:43 -04:00
|
|
|
|
|
|
|
String scheme;
|
|
|
|
switch (server.connectionSecurity) {
|
|
|
|
case SSL_TLS_REQUIRED:
|
|
|
|
scheme = "pop3+ssl+";
|
|
|
|
break;
|
|
|
|
case STARTTLS_REQUIRED:
|
|
|
|
scheme = "pop3+tls+";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case NONE:
|
|
|
|
scheme = "pop3";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-05-25 16:45:14 -04:00
|
|
|
AuthType authType = server.authenticationType;
|
|
|
|
String userInfo;
|
2014-08-18 18:12:39 -04:00
|
|
|
if (AuthType.EXTERNAL == authType) {
|
2014-05-25 16:45:14 -04:00
|
|
|
userInfo = authType.name() + ":" + userEnc + ":" + clientCertificateAliasEnc;
|
|
|
|
} else {
|
|
|
|
userInfo = authType.name() + ":" + userEnc + ":" + passwordEnc;
|
|
|
|
}
|
|
|
|
|
2011-06-08 23:50:43 -04:00
|
|
|
try {
|
|
|
|
return new URI(scheme, userInfo, server.host, server.port, null, null,
|
|
|
|
null).toString();
|
|
|
|
} catch (URISyntaxException e) {
|
|
|
|
throw new IllegalArgumentException("Can't create Pop3Store URI", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-06 18:08:43 -04:00
|
|
|
|
|
|
|
private String mHost;
|
|
|
|
private int mPort;
|
|
|
|
private String mUsername;
|
|
|
|
private String mPassword;
|
2014-05-25 16:45:14 -04:00
|
|
|
private String mClientCertificateAlias;
|
2011-10-16 23:59:36 -04:00
|
|
|
private AuthType mAuthType;
|
2014-02-13 19:43:24 -05:00
|
|
|
private ConnectionSecurity mConnectionSecurity;
|
2014-10-04 06:45:45 -04:00
|
|
|
private Map<String, Folder> mFolders = new HashMap<String, Folder>();
|
2011-06-06 18:08:43 -04:00
|
|
|
private Pop3Capabilities mCapabilities;
|
|
|
|
|
2011-10-14 14:33:25 -04:00
|
|
|
/**
|
|
|
|
* This value is {@code true} if the server supports the CAPA command but doesn't advertise
|
|
|
|
* support for the TOP command OR if the server doesn't support the CAPA command and we
|
|
|
|
* already unsuccessfully tried to use the TOP command.
|
|
|
|
*/
|
|
|
|
private boolean mTopNotSupported;
|
|
|
|
|
2011-06-06 18:08:43 -04:00
|
|
|
|
2014-12-17 11:42:22 -05:00
|
|
|
public Pop3Store(StoreConfig storeConfig, TrustedSocketFactory socketFactory) throws MessagingException {
|
|
|
|
super(storeConfig, socketFactory);
|
2011-06-06 18:08:43 -04:00
|
|
|
|
2011-06-07 10:09:15 -04:00
|
|
|
ServerSettings settings;
|
2011-06-06 18:08:43 -04:00
|
|
|
try {
|
2014-12-11 22:23:32 -05:00
|
|
|
settings = decodeUri(storeConfig.getStoreUri());
|
2011-06-06 18:08:43 -04:00
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
throw new MessagingException("Error while decoding store URI", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
mHost = settings.host;
|
|
|
|
mPort = settings.port;
|
|
|
|
|
2014-02-13 19:43:24 -05:00
|
|
|
mConnectionSecurity = settings.connectionSecurity;
|
2011-06-06 18:08:43 -04:00
|
|
|
|
|
|
|
mUsername = settings.username;
|
|
|
|
mPassword = settings.password;
|
2014-05-25 16:45:14 -04:00
|
|
|
mClientCertificateAlias = settings.clientCertificateAlias;
|
2014-02-13 17:18:16 -05:00
|
|
|
mAuthType = settings.authenticationType;
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public Folder getFolder(String name) {
|
2008-11-01 17:32:06 -04:00
|
|
|
Folder folder = mFolders.get(name);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (folder == null) {
|
2008-11-01 17:32:06 -04:00
|
|
|
folder = new Pop3Folder(name);
|
|
|
|
mFolders.put(folder.getName(), folder);
|
|
|
|
}
|
|
|
|
return folder;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public List <? extends Folder > getPersonalNamespaces(boolean forceListAll) throws MessagingException {
|
2010-04-21 22:20:35 -04:00
|
|
|
List<Folder> folders = new LinkedList<Folder>();
|
2014-12-11 22:23:32 -05:00
|
|
|
folders.add(getFolder(mStoreConfig.getInboxFolderName()));
|
2010-04-21 22:20:35 -04:00
|
|
|
return folders;
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void checkSettings() throws MessagingException {
|
2014-12-11 22:23:32 -05:00
|
|
|
Pop3Folder folder = new Pop3Folder(mStoreConfig.getInboxFolderName());
|
2013-07-30 16:36:47 -04:00
|
|
|
folder.open(Folder.OPEN_MODE_RW);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (!mCapabilities.uidl) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* Run an additional test to see if UIDL is supported on the server. If it's not we
|
|
|
|
* can't service this account.
|
|
|
|
*/
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2009-04-10 22:11:17 -04:00
|
|
|
/*
|
|
|
|
* If the server doesn't support UIDL it will return a - response, which causes
|
|
|
|
* executeSimpleCommand to throw a MessagingException, exiting this method.
|
|
|
|
*/
|
2011-07-17 08:13:04 -04:00
|
|
|
folder.executeSimpleCommand(UIDL_COMMAND);
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
Implementation of complete IMAP two-phase "delete/expunge" behavior.
On each IMAP account, the expunge behavior can be set to expunge
messages in a folder as soon as a move or delete is performed on the
folder ("immediately"), each time the folder is polled, or only when
executed manually.
In the Message List, there is now an Expunge action in the option
menu.
In the Folder List, there is now an Expunge action in the context
menu (long-press on the folder).
For IMAP accounts, it is also possible to disable the copying of deleted messages to the
Trash folder, by setting the Trash folder to -NONE-.
Fixes Issue 536.
Separately, in WebDAV accounts, the user can now choose the
server-side equivalents of the special folders, just like for IMAP.
2009-12-20 18:13:49 -05:00
|
|
|
folder.close();
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
2013-03-13 01:34:14 -04:00
|
|
|
@Override
|
|
|
|
public boolean isSeenFlagSupported() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-12-11 22:23:32 -05:00
|
|
|
class Pop3Folder extends Folder<Pop3Message> {
|
2008-11-01 17:32:06 -04:00
|
|
|
private Socket mSocket;
|
|
|
|
private InputStream mIn;
|
|
|
|
private OutputStream mOut;
|
2014-10-04 06:45:45 -04:00
|
|
|
private Map<String, Pop3Message> mUidToMsgMap = new HashMap<String, Pop3Message>();
|
2015-01-05 17:24:24 -05:00
|
|
|
@SuppressLint("UseSparseArrays")
|
2014-10-04 06:45:45 -04:00
|
|
|
private Map<Integer, Pop3Message> mMsgNumToMsgMap = new HashMap<Integer, Pop3Message>();
|
|
|
|
private Map<String, Integer> mUidToMsgNumMap = new HashMap<String, Integer>();
|
2008-11-01 17:32:06 -04:00
|
|
|
private String mName;
|
|
|
|
private int mMessageCount;
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public Pop3Folder(String name) {
|
2014-12-11 22:23:32 -05:00
|
|
|
super();
|
2008-11-01 17:32:06 -04:00
|
|
|
this.mName = name;
|
2011-04-05 05:28:04 -04:00
|
|
|
|
2014-12-11 22:23:32 -05:00
|
|
|
if (mName.equalsIgnoreCase(mStoreConfig.getInboxFolderName())) {
|
|
|
|
mName = mStoreConfig.getInboxFolderName();
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2013-07-30 16:36:47 -04:00
|
|
|
public synchronized void open(int mode) throws MessagingException {
|
2011-02-06 17:09:48 -05:00
|
|
|
if (isOpen()) {
|
2008-11-01 17:32:06 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-12-11 22:23:32 -05:00
|
|
|
if (!mName.equalsIgnoreCase(mStoreConfig.getInboxFolderName())) {
|
2008-11-01 17:32:06 -04:00
|
|
|
throw new MessagingException("Folder does not exist");
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2008-11-01 17:32:06 -04:00
|
|
|
SocketAddress socketAddress = new InetSocketAddress(mHost, mPort);
|
Eliminate the 'if available' connection security options
These options originated in the AOSP email client from which K-9 Mail was
forked. They provide an odd combination of 2 features:
1. Don't bother to authenticate the server's certificate (applies to both
SSL/TLS and STARTTLS); i.e., blindly accept all certificates. This is
generally a bad security policy which is susceptible to MITM attacks.
2. If STARTTLS is selected but the server doesn't claim to support
STARTTLS, then proceed without using encryption. This, too, is a bad
security policy which is susceptible to MITM attacks.
Since the time that K-9 Mail was forked, a couple things have changed:
> K-9 Mail has implemented the ability for users to review and permanently
accept individual certificates that would otherwise fail authentication.
With this ability, there is no need for a user to subject themselves to
the ongoing risks of feature 1. above. Hence, this commit removes feature
1.
> The AOSP email client has changed its behavior and no longer permits a
security downgrade to an unencrypted connection if the server doesn't
claim to support STARTTLS (i.e., they eliminated feature 2. above). K-9
Mail should do the same. It's unlikely that a server is going to provide
STARTTLS on an intermittent basis, so providing a contingency for such
unusual behavior is an unnecessary risk. Hence, this commit removes that
feature as well.
Effect on existing users:
If the old connection security setting was "SSL/TLS (if available)" (which
now gets remapped to "SSL/TLS"), and the server does not provide a
certificate that can be authenticated, then a "Certificate error for
<account name>" notification is generated telling the user to check their
server settings. Tapping the notification takes the user to the relevant
server settings, where the user can tap "Next" to review the certificate
and choose to permanently accept it. This process would occur during the
first syncing of folders after application upgrade or (in the case of
SMTP) during the first attempt to send a message.
If the connection security setting was "STARTTLS (if available)" (which
now gets remapped to "STARTTLS"), and the server does not provide a
certificate that can be authenticated, then the same process as above
would occur.
If the old connection security setting was "STARTTLS (if available)", and
the server doesn't claim to support STARTTLS, then the user would get a
certificate error notification which would lead them to the server's
settings. There they would need to choose a different connection security
-- most likely "NONE". If they didn't change anything but instead just
tapped "Next", the server settings would be checked again and a dialog
would pop up saying, "Cannot connect to server. (STARTTLS connection
security not available)". (The implementation of notifications when
STARTTLS is not available is not actually included here -- it's in the
commit that follows.)
Regarding the changes to providers.xml: in cases where the scheme ended
with "+ssl", the schemes were simply updated by appending "+". In cases
where the scheme ended with "+tls", a check of the server was made to
assure that STARTTLS was available before appending "+" to the scheme.
Domains paran.com and nate.com failed the check and were removed because
no current information could be found. Domains me.com and mac.com also
failed and were updated based on http://support.apple.com/kb/ht4864.
2014-02-26 16:50:21 -05:00
|
|
|
if (mConnectionSecurity == ConnectionSecurity.SSL_TLS_REQUIRED) {
|
2014-12-17 11:42:22 -05:00
|
|
|
mSocket = mTrustedSocketFactory.createSocket(null, mHost, mPort, mClientCertificateAlias);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2008-11-01 17:32:06 -04:00
|
|
|
mSocket = new Socket();
|
|
|
|
}
|
|
|
|
|
2011-01-23 22:26:57 -05:00
|
|
|
mSocket.connect(socketAddress, SOCKET_CONNECT_TIMEOUT);
|
|
|
|
mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
|
|
|
|
mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
|
|
|
|
|
2014-12-11 22:23:32 -05:00
|
|
|
mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (!isOpen()) {
|
2009-11-24 19:40:29 -05:00
|
|
|
throw new MessagingException("Unable to connect socket");
|
2009-04-15 09:05:29 -04:00
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
String serverGreeting = executeSimpleCommand(null);
|
2008-11-01 17:32:06 -04:00
|
|
|
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
mCapabilities = getCapabilities();
|
Eliminate the 'if available' connection security options
These options originated in the AOSP email client from which K-9 Mail was
forked. They provide an odd combination of 2 features:
1. Don't bother to authenticate the server's certificate (applies to both
SSL/TLS and STARTTLS); i.e., blindly accept all certificates. This is
generally a bad security policy which is susceptible to MITM attacks.
2. If STARTTLS is selected but the server doesn't claim to support
STARTTLS, then proceed without using encryption. This, too, is a bad
security policy which is susceptible to MITM attacks.
Since the time that K-9 Mail was forked, a couple things have changed:
> K-9 Mail has implemented the ability for users to review and permanently
accept individual certificates that would otherwise fail authentication.
With this ability, there is no need for a user to subject themselves to
the ongoing risks of feature 1. above. Hence, this commit removes feature
1.
> The AOSP email client has changed its behavior and no longer permits a
security downgrade to an unencrypted connection if the server doesn't
claim to support STARTTLS (i.e., they eliminated feature 2. above). K-9
Mail should do the same. It's unlikely that a server is going to provide
STARTTLS on an intermittent basis, so providing a contingency for such
unusual behavior is an unnecessary risk. Hence, this commit removes that
feature as well.
Effect on existing users:
If the old connection security setting was "SSL/TLS (if available)" (which
now gets remapped to "SSL/TLS"), and the server does not provide a
certificate that can be authenticated, then a "Certificate error for
<account name>" notification is generated telling the user to check their
server settings. Tapping the notification takes the user to the relevant
server settings, where the user can tap "Next" to review the certificate
and choose to permanently accept it. This process would occur during the
first syncing of folders after application upgrade or (in the case of
SMTP) during the first attempt to send a message.
If the connection security setting was "STARTTLS (if available)" (which
now gets remapped to "STARTTLS"), and the server does not provide a
certificate that can be authenticated, then the same process as above
would occur.
If the old connection security setting was "STARTTLS (if available)", and
the server doesn't claim to support STARTTLS, then the user would get a
certificate error notification which would lead them to the server's
settings. There they would need to choose a different connection security
-- most likely "NONE". If they didn't change anything but instead just
tapped "Next", the server settings would be checked again and a dialog
would pop up saying, "Cannot connect to server. (STARTTLS connection
security not available)". (The implementation of notifications when
STARTTLS is not available is not actually included here -- it's in the
commit that follows.)
Regarding the changes to providers.xml: in cases where the scheme ended
with "+ssl", the schemes were simply updated by appending "+". In cases
where the scheme ended with "+tls", a check of the server was made to
assure that STARTTLS was available before appending "+" to the scheme.
Domains paran.com and nate.com failed the check and were removed because
no current information could be found. Domains me.com and mac.com also
failed and were updated based on http://support.apple.com/kb/ht4864.
2014-02-26 16:50:21 -05:00
|
|
|
if (mConnectionSecurity == ConnectionSecurity.STARTTLS_REQUIRED) {
|
2010-07-29 20:58:22 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (mCapabilities.stls) {
|
2013-12-17 13:44:25 -05:00
|
|
|
executeSimpleCommand(STLS_COMMAND);
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2014-12-17 11:42:22 -05:00
|
|
|
mSocket = mTrustedSocketFactory.createSocket(
|
2014-12-17 10:12:55 -05:00
|
|
|
mSocket,
|
|
|
|
mHost,
|
|
|
|
mPort,
|
2014-05-25 16:45:14 -04:00
|
|
|
mClientCertificateAlias);
|
2014-12-11 22:23:32 -05:00
|
|
|
mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
|
2008-11-01 17:32:06 -04:00
|
|
|
mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
|
|
|
|
mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (!isOpen()) {
|
2009-11-24 19:40:29 -05:00
|
|
|
throw new MessagingException("Unable to connect socket");
|
2009-04-15 09:05:29 -04:00
|
|
|
}
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
mCapabilities = getCapabilities();
|
Eliminate the 'if available' connection security options
These options originated in the AOSP email client from which K-9 Mail was
forked. They provide an odd combination of 2 features:
1. Don't bother to authenticate the server's certificate (applies to both
SSL/TLS and STARTTLS); i.e., blindly accept all certificates. This is
generally a bad security policy which is susceptible to MITM attacks.
2. If STARTTLS is selected but the server doesn't claim to support
STARTTLS, then proceed without using encryption. This, too, is a bad
security policy which is susceptible to MITM attacks.
Since the time that K-9 Mail was forked, a couple things have changed:
> K-9 Mail has implemented the ability for users to review and permanently
accept individual certificates that would otherwise fail authentication.
With this ability, there is no need for a user to subject themselves to
the ongoing risks of feature 1. above. Hence, this commit removes feature
1.
> The AOSP email client has changed its behavior and no longer permits a
security downgrade to an unencrypted connection if the server doesn't
claim to support STARTTLS (i.e., they eliminated feature 2. above). K-9
Mail should do the same. It's unlikely that a server is going to provide
STARTTLS on an intermittent basis, so providing a contingency for such
unusual behavior is an unnecessary risk. Hence, this commit removes that
feature as well.
Effect on existing users:
If the old connection security setting was "SSL/TLS (if available)" (which
now gets remapped to "SSL/TLS"), and the server does not provide a
certificate that can be authenticated, then a "Certificate error for
<account name>" notification is generated telling the user to check their
server settings. Tapping the notification takes the user to the relevant
server settings, where the user can tap "Next" to review the certificate
and choose to permanently accept it. This process would occur during the
first syncing of folders after application upgrade or (in the case of
SMTP) during the first attempt to send a message.
If the connection security setting was "STARTTLS (if available)" (which
now gets remapped to "STARTTLS"), and the server does not provide a
certificate that can be authenticated, then the same process as above
would occur.
If the old connection security setting was "STARTTLS (if available)", and
the server doesn't claim to support STARTTLS, then the user would get a
certificate error notification which would lead them to the server's
settings. There they would need to choose a different connection security
-- most likely "NONE". If they didn't change anything but instead just
tapped "Next", the server settings would be checked again and a dialog
would pop up saying, "Cannot connect to server. (STARTTLS connection
security not available)". (The implementation of notifications when
STARTTLS is not available is not actually included here -- it's in the
commit that follows.)
Regarding the changes to providers.xml: in cases where the scheme ended
with "+ssl", the schemes were simply updated by appending "+". In cases
where the scheme ended with "+tls", a check of the server was made to
assure that STARTTLS was available before appending "+" to the scheme.
Domains paran.com and nate.com failed the check and were removed because
no current information could be found. Domains me.com and mac.com also
failed and were updated based on http://support.apple.com/kb/ht4864.
2014-02-26 16:50:21 -05:00
|
|
|
} else {
|
2014-02-28 12:47:43 -05:00
|
|
|
/*
|
|
|
|
* This exception triggers a "Certificate error"
|
|
|
|
* notification that takes the user to the incoming
|
|
|
|
* server settings for review. This might be needed if
|
|
|
|
* the account was configured with an obsolete
|
|
|
|
* "STARTTLS (if available)" setting.
|
|
|
|
*/
|
|
|
|
throw new CertificateValidationException(
|
2014-08-07 13:54:14 -04:00
|
|
|
"STARTTLS connection security not available");
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
switch (mAuthType) {
|
|
|
|
case PLAIN:
|
|
|
|
if (mCapabilities.authPlain) {
|
|
|
|
authPlain();
|
|
|
|
} else {
|
|
|
|
login();
|
2011-04-06 11:42:37 -04:00
|
|
|
}
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CRAM_MD5:
|
|
|
|
if (mCapabilities.cramMD5) {
|
|
|
|
authCramMD5();
|
|
|
|
} else {
|
|
|
|
authAPOP(serverGreeting);
|
2011-04-06 11:42:37 -04:00
|
|
|
}
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
break;
|
2010-07-29 20:58:22 -04:00
|
|
|
|
2014-05-25 16:45:14 -04:00
|
|
|
case EXTERNAL:
|
|
|
|
if (mCapabilities.external) {
|
2014-08-07 13:54:14 -04:00
|
|
|
authExternal();
|
|
|
|
} else {
|
|
|
|
// Provide notification to user of a problem authenticating using client certificates
|
2014-12-17 09:28:48 -05:00
|
|
|
throw new CertificateValidationException(MissingCapability);
|
2014-08-07 13:54:14 -04:00
|
|
|
}
|
2014-05-25 16:45:14 -04:00
|
|
|
break;
|
|
|
|
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
default:
|
|
|
|
throw new MessagingException(
|
|
|
|
"Unhandled authentication method found in the server settings (bug).");
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (SSLException e) {
|
2013-01-17 09:24:22 -05:00
|
|
|
throw new CertificateValidationException(e.getMessage(), e);
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (GeneralSecurityException gse) {
|
2008-11-01 17:32:06 -04:00
|
|
|
throw new MessagingException(
|
2009-11-24 19:40:29 -05:00
|
|
|
"Unable to open connection to POP server due to security error.", gse);
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (IOException ioe) {
|
2008-11-01 17:32:06 -04:00
|
|
|
throw new MessagingException("Unable to open connection to POP server.", ioe);
|
|
|
|
}
|
|
|
|
|
2011-07-17 08:13:04 -04:00
|
|
|
String response = executeSimpleCommand(STAT_COMMAND);
|
2009-04-10 22:11:17 -04:00
|
|
|
String[] parts = response.split(" ");
|
|
|
|
mMessageCount = Integer.parseInt(parts[1]);
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2008-11-01 17:32:06 -04:00
|
|
|
mUidToMsgMap.clear();
|
|
|
|
mMsgNumToMsgMap.clear();
|
|
|
|
mUidToMsgNumMap.clear();
|
|
|
|
}
|
|
|
|
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
private void login() throws MessagingException {
|
|
|
|
executeSimpleCommand(USER_COMMAND + " " + mUsername);
|
|
|
|
try {
|
|
|
|
executeSimpleCommand(PASS_COMMAND + " " + mPassword, true);
|
|
|
|
} catch (Pop3ErrorResponse e) {
|
|
|
|
throw new AuthenticationFailedException(
|
|
|
|
"POP3 login authentication failed: " + e.getMessage(), e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void authPlain() throws MessagingException {
|
|
|
|
executeSimpleCommand("AUTH PLAIN");
|
|
|
|
try {
|
|
|
|
byte[] encodedBytes = Base64.encodeBase64(("\000" + mUsername
|
|
|
|
+ "\000" + mPassword).getBytes());
|
|
|
|
executeSimpleCommand(new String(encodedBytes), true);
|
|
|
|
} catch (Pop3ErrorResponse e) {
|
|
|
|
throw new AuthenticationFailedException(
|
|
|
|
"POP3 SASL auth PLAIN authentication failed: "
|
|
|
|
+ e.getMessage(), e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void authAPOP(String serverGreeting) throws MessagingException {
|
|
|
|
// regex based on RFC 2449 (3.) "Greeting"
|
|
|
|
String timestamp = serverGreeting.replaceFirst(
|
|
|
|
"^\\+OK *(?:\\[[^\\]]+\\])?[^<]*(<[^>]*>)?[^<]*$", "$1");
|
|
|
|
if ("".equals(timestamp)) {
|
|
|
|
throw new MessagingException(
|
|
|
|
"APOP authentication is not supported");
|
|
|
|
}
|
|
|
|
MessageDigest md;
|
|
|
|
try {
|
|
|
|
md = MessageDigest.getInstance("MD5");
|
|
|
|
} catch (NoSuchAlgorithmException e) {
|
|
|
|
throw new MessagingException(
|
|
|
|
"MD5 failure during POP3 auth APOP", e);
|
|
|
|
}
|
|
|
|
byte[] digest = md.digest((timestamp + mPassword).getBytes());
|
|
|
|
String hexDigest = new String(Hex.encodeHex(digest));
|
|
|
|
try {
|
|
|
|
executeSimpleCommand("APOP " + mUsername + " " + hexDigest, true);
|
|
|
|
} catch (Pop3ErrorResponse e) {
|
|
|
|
throw new AuthenticationFailedException(
|
|
|
|
"POP3 APOP authentication failed: " + e.getMessage(), e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void authCramMD5() throws MessagingException {
|
|
|
|
String b64Nonce = executeSimpleCommand("AUTH CRAM-MD5").replace("+ ", "");
|
|
|
|
|
|
|
|
String b64CRAM = Authentication.computeCramMd5(mUsername, mPassword, b64Nonce);
|
|
|
|
try {
|
|
|
|
executeSimpleCommand(b64CRAM, true);
|
|
|
|
} catch (Pop3ErrorResponse e) {
|
|
|
|
throw new AuthenticationFailedException(
|
|
|
|
"POP3 CRAM-MD5 authentication failed: "
|
|
|
|
+ e.getMessage(), e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-07 13:54:14 -04:00
|
|
|
private void authExternal() throws MessagingException {
|
|
|
|
try {
|
|
|
|
executeSimpleCommand(
|
|
|
|
String.format("AUTH EXTERNAL %s",
|
2014-12-12 10:02:59 -05:00
|
|
|
Base64.encode(mUsername)), false);
|
2014-08-07 13:54:14 -04:00
|
|
|
} catch (Pop3ErrorResponse e) {
|
|
|
|
/*
|
|
|
|
* Provide notification to the user of a problem authenticating
|
|
|
|
* using client certificates. We don't use an
|
|
|
|
* AuthenticationFailedException because that would trigger a
|
|
|
|
* "Username or password incorrect" notification in
|
|
|
|
* AccountSetupCheckSettings.
|
|
|
|
*/
|
|
|
|
throw new CertificateValidationException(
|
|
|
|
"POP3 client certificate authentication failed: " + e.getMessage(), e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-16 08:20:10 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean isOpen() {
|
2009-11-24 19:40:29 -05:00
|
|
|
return (mIn != null && mOut != null && mSocket != null
|
|
|
|
&& mSocket.isConnected() && !mSocket.isClosed());
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2013-07-30 16:36:47 -04:00
|
|
|
public int getMode() {
|
|
|
|
return Folder.OPEN_MODE_RW;
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void close() {
|
|
|
|
try {
|
2011-05-14 17:30:47 -04:00
|
|
|
if (isOpen()) {
|
2011-07-17 08:13:04 -04:00
|
|
|
executeSimpleCommand(QUIT_COMMAND);
|
2011-05-14 17:30:47 -04:00
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (Exception e) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* QUIT may fail if the connection is already closed. We don't care. It's just
|
|
|
|
* being friendly.
|
|
|
|
*/
|
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2008-11-06 01:55:29 -05:00
|
|
|
closeIO();
|
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private void closeIO() {
|
|
|
|
try {
|
2008-11-01 17:32:06 -04:00
|
|
|
mIn.close();
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (Exception e) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* May fail if the connection is already closed.
|
|
|
|
*/
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2008-11-01 17:32:06 -04:00
|
|
|
mOut.close();
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (Exception e) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* May fail if the connection is already closed.
|
|
|
|
*/
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2008-11-01 17:32:06 -04:00
|
|
|
mSocket.close();
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (Exception e) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* May fail if the connection is already closed.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
mIn = null;
|
|
|
|
mOut = null;
|
|
|
|
mSocket = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public String getName() {
|
2008-11-01 17:32:06 -04:00
|
|
|
return mName;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean create(FolderType type) throws MessagingException {
|
2008-11-01 17:32:06 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean exists() throws MessagingException {
|
2014-12-11 22:23:32 -05:00
|
|
|
return mName.equalsIgnoreCase(mStoreConfig.getInboxFolderName());
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int getMessageCount() {
|
2008-11-01 17:32:06 -04:00
|
|
|
return mMessageCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int getUnreadMessageCount() throws MessagingException {
|
2008-11-01 17:32:06 -04:00
|
|
|
return -1;
|
|
|
|
}
|
2010-04-16 10:33:54 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int getFlaggedMessageCount() throws MessagingException {
|
2010-04-16 10:33:54 -04:00
|
|
|
return -1;
|
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
|
|
|
|
@Override
|
2014-12-11 22:23:32 -05:00
|
|
|
public Pop3Message getMessage(String uid) throws MessagingException {
|
2008-11-01 17:32:06 -04:00
|
|
|
Pop3Message message = mUidToMsgMap.get(uid);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (message == null) {
|
2008-11-01 17:32:06 -04:00
|
|
|
message = new Pop3Message(uid, this);
|
|
|
|
}
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-12-19 03:54:17 -05:00
|
|
|
public List<Pop3Message> getMessages(int start, int end, Date earliestDate, MessageRetrievalListener<Pop3Message> listener)
|
2011-02-06 17:09:48 -05:00
|
|
|
throws MessagingException {
|
|
|
|
if (start < 1 || end < 1 || end < start) {
|
2014-03-03 10:40:23 -05:00
|
|
|
throw new MessagingException(String.format(Locale.US, "Invalid message set %d %d",
|
2009-11-24 19:40:29 -05:00
|
|
|
start, end));
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2008-11-01 17:32:06 -04:00
|
|
|
indexMsgNums(start, end);
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (IOException ioe) {
|
2008-11-01 17:32:06 -04:00
|
|
|
throw new MessagingException("getMessages", ioe);
|
|
|
|
}
|
2014-12-19 03:54:17 -05:00
|
|
|
List<Pop3Message> messages = new ArrayList<Pop3Message>();
|
2008-11-01 17:32:06 -04:00
|
|
|
int i = 0;
|
2011-02-06 17:09:48 -05:00
|
|
|
for (int msgNum = start; msgNum <= end; msgNum++) {
|
2008-11-01 17:32:06 -04:00
|
|
|
Pop3Message message = mMsgNumToMsgMap.get(msgNum);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (message == null) {
|
2010-09-02 19:59:20 -04:00
|
|
|
/*
|
|
|
|
* There could be gaps in the message numbers or malformed
|
|
|
|
* responses which lead to "gaps" in mMsgNumToMsgMap.
|
|
|
|
*
|
|
|
|
* See issue 2252
|
|
|
|
*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (listener != null) {
|
2008-11-01 17:32:06 -04:00
|
|
|
listener.messageStarted(message.getUid(), i++, (end - start) + 1);
|
|
|
|
}
|
|
|
|
messages.add(message);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (listener != null) {
|
2008-11-01 17:32:06 -04:00
|
|
|
listener.messageFinished(message, i++, (end - start) + 1);
|
|
|
|
}
|
|
|
|
}
|
2014-10-04 05:37:30 -04:00
|
|
|
return messages;
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ensures that the given message set (from start to end inclusive)
|
|
|
|
* has been queried so that uids are available in the local cache.
|
|
|
|
* @param start
|
|
|
|
* @param end
|
|
|
|
* @throws MessagingException
|
|
|
|
* @throws IOException
|
|
|
|
*/
|
|
|
|
private void indexMsgNums(int start, int end)
|
2011-02-06 17:09:48 -05:00
|
|
|
throws MessagingException, IOException {
|
2008-11-01 17:32:06 -04:00
|
|
|
int unindexedMessageCount = 0;
|
2011-02-06 17:09:48 -05:00
|
|
|
for (int msgNum = start; msgNum <= end; msgNum++) {
|
|
|
|
if (mMsgNumToMsgMap.get(msgNum) == null) {
|
2008-11-01 17:32:06 -04:00
|
|
|
unindexedMessageCount++;
|
|
|
|
}
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (unindexedMessageCount == 0) {
|
2008-11-01 17:32:06 -04:00
|
|
|
return;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (unindexedMessageCount < 50 && mMessageCount > 5000) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* In extreme cases we'll do a UIDL command per message instead of a bulk
|
|
|
|
* download.
|
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
for (int msgNum = start; msgNum <= end; msgNum++) {
|
2008-11-01 17:32:06 -04:00
|
|
|
Pop3Message message = mMsgNumToMsgMap.get(msgNum);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (message == null) {
|
2011-07-17 08:13:04 -04:00
|
|
|
String response = executeSimpleCommand(UIDL_COMMAND + " " + msgNum);
|
2013-06-29 09:28:27 -04:00
|
|
|
// response = "+OK msgNum msgUid"
|
|
|
|
String[] uidParts = response.split(" +");
|
|
|
|
if (uidParts.length < 3 || !"+OK".equals(uidParts[0])) {
|
2014-12-16 06:51:52 -05:00
|
|
|
Log.e(LOG_TAG, "ERR response: " + response);
|
2013-06-29 09:28:27 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
String msgUid = uidParts[2];
|
2008-11-01 17:32:06 -04:00
|
|
|
message = new Pop3Message(msgUid, this);
|
|
|
|
indexMessage(msgNum, message);
|
|
|
|
}
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2011-07-17 08:13:04 -04:00
|
|
|
String response = executeSimpleCommand(UIDL_COMMAND);
|
2011-02-06 17:09:48 -05:00
|
|
|
while ((response = readLine()) != null) {
|
|
|
|
if (response.equals(".")) {
|
2008-11-01 17:32:06 -04:00
|
|
|
break;
|
|
|
|
}
|
2011-07-17 08:37:21 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Yet another work-around for buggy server software:
|
2011-09-02 13:23:45 -04:00
|
|
|
* split the response into message number and unique identifier, no matter how many spaces it has
|
2011-07-17 08:37:21 -04:00
|
|
|
*
|
|
|
|
* Example for a malformed response:
|
|
|
|
* 1 2011071307115510400ae3e9e00bmu9
|
|
|
|
*
|
|
|
|
* Note the three spaces between message number and unique identifier.
|
|
|
|
* See issue 3546
|
|
|
|
*/
|
|
|
|
|
2011-09-02 13:23:45 -04:00
|
|
|
String[] uidParts = response.split(" +");
|
2011-02-06 17:09:48 -05:00
|
|
|
if ((uidParts.length >= 3) && "+OK".equals(uidParts[0])) {
|
2010-03-25 09:42:48 -04:00
|
|
|
/*
|
|
|
|
* At least one server software places a "+OK" in
|
|
|
|
* front of every line in the unique-id listing.
|
2010-04-29 00:59:14 -04:00
|
|
|
*
|
2010-03-25 09:42:48 -04:00
|
|
|
* Fix up the array if we detected this behavior.
|
|
|
|
* See Issue 1237
|
2010-04-29 00:59:14 -04:00
|
|
|
*/
|
2010-03-25 09:42:48 -04:00
|
|
|
uidParts[0] = uidParts[1];
|
|
|
|
uidParts[1] = uidParts[2];
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (uidParts.length >= 2) {
|
2010-03-17 23:43:39 -04:00
|
|
|
Integer msgNum = Integer.valueOf(uidParts[0]);
|
|
|
|
String msgUid = uidParts[1];
|
2011-02-06 17:09:48 -05:00
|
|
|
if (msgNum >= start && msgNum <= end) {
|
2010-03-17 23:43:39 -04:00
|
|
|
Pop3Message message = mMsgNumToMsgMap.get(msgNum);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (message == null) {
|
2010-03-17 23:43:39 -04:00
|
|
|
message = new Pop3Message(msgUid, this);
|
|
|
|
indexMessage(msgNum, message);
|
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-04 06:45:45 -04:00
|
|
|
private void indexUids(List<String> uids)
|
2011-02-06 17:09:48 -05:00
|
|
|
throws MessagingException, IOException {
|
2014-02-15 17:48:35 -05:00
|
|
|
Set<String> unindexedUids = new HashSet<String>();
|
2011-02-06 17:09:48 -05:00
|
|
|
for (String uid : uids) {
|
|
|
|
if (mUidToMsgMap.get(uid) == null) {
|
2014-12-16 06:51:52 -05:00
|
|
|
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
|
|
|
|
Log.d(LOG_TAG, "Need to index UID " + uid);
|
2009-11-24 19:40:29 -05:00
|
|
|
}
|
|
|
|
unindexedUids.add(uid);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
2011-10-06 12:28:14 -04:00
|
|
|
if (unindexedUids.isEmpty()) {
|
2008-11-01 17:32:06 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If we are missing uids in the cache the only sure way to
|
|
|
|
* get them is to do a full UIDL list. A possible optimization
|
|
|
|
* would be trying UIDL for the latest X messages and praying.
|
|
|
|
*/
|
2011-07-17 08:13:04 -04:00
|
|
|
String response = executeSimpleCommand(UIDL_COMMAND);
|
2011-02-06 17:09:48 -05:00
|
|
|
while ((response = readLine()) != null) {
|
|
|
|
if (response.equals(".")) {
|
2009-11-24 19:40:29 -05:00
|
|
|
break;
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
2013-06-26 10:57:55 -04:00
|
|
|
String[] uidParts = response.split(" +");
|
2009-04-10 22:11:17 -04:00
|
|
|
|
2010-12-01 13:14:12 -05:00
|
|
|
// Ignore messages without a unique-id
|
2011-02-06 17:09:48 -05:00
|
|
|
if (uidParts.length >= 2) {
|
2010-12-24 13:55:05 -05:00
|
|
|
Integer msgNum = Integer.valueOf(uidParts[0]);
|
|
|
|
String msgUid = uidParts[1];
|
2011-02-06 17:09:48 -05:00
|
|
|
if (unindexedUids.contains(msgUid)) {
|
2014-12-16 06:51:52 -05:00
|
|
|
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
|
|
|
|
Log.d(LOG_TAG, "Got msgNum " + msgNum + " for UID " + msgUid);
|
2010-12-24 13:55:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Pop3Message message = mUidToMsgMap.get(msgUid);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (message == null) {
|
2010-12-24 13:55:05 -05:00
|
|
|
message = new Pop3Message(msgUid, this);
|
|
|
|
}
|
|
|
|
indexMessage(msgNum, message);
|
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private void indexMessage(int msgNum, Pop3Message message) {
|
2014-12-16 06:51:52 -05:00
|
|
|
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
|
|
|
|
Log.d(LOG_TAG, "Adding index for UID " + message.getUid() + " to msgNum " + msgNum);
|
2009-11-24 19:40:29 -05:00
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
mMsgNumToMsgMap.put(msgNum, message);
|
|
|
|
mUidToMsgMap.put(message.getUid(), message);
|
|
|
|
mUidToMsgNumMap.put(message.getUid(), msgNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-12-19 04:01:34 -05:00
|
|
|
public List<Pop3Message> getMessages(MessageRetrievalListener listener) throws MessagingException {
|
Complete merge of DAmail functionality into K9mail. Following
features are added to K9mail:
1) Show unread message count on each folder
2) Sum unread count of all shown folders in an account to the account display
3) Periodically check selected folders for new mail, not just Inbox
4) Don't refresh folder when opened (unless folder is empty)
5) Show date and time of last sync for each folder
6) Fix timer for automatic periodic sync (use wakelock to assure completion)
7) Optimize local folder queries (speeds up account and folder lists)
8) Show Loading... message in status bar indicating which folder is being synced
9) Eliminate redundant sync of new messages (performance enhancement)
10) Improve notification text for multiple accounts
11) Do not automatically sync folders more often than the account-specific period
12) Use user-configured date and time formats
13) Select which folders are shown, using configurable Classes
14) Select which folders are synced, using configurable Classes
15) Added context (long press) menu to folders, to provide for Refresh
and Folder Settings
16) Status light flashes purple when there are unread messages
17) Folder list more quickly eliminates display of deleted and out-of-Class folders.
18) Delete works
19) Mark all messages as read (in the folder context menu)
20) Notifications only for new unread messages
21) One minute synchronization frequency
22) Deleting an unread message decrements unread counter
23) Notifications work for POP3 accounts
24) Message deletes work for POP3 accounts
25) Explicit errors show in folder list
26) Stack traces saved to folder K9mail-errors
27) Clear pending actions (danger, for emergencies only!)
28) Delete policy in Account settings
29) DNS cache in InetAddress disabled
30) Trapped some crash-causing error conditions
31) Eliminate duplicate copies to Sent folder
32) Prevent crashes due to message listener concurrency
33) Empty Trash
34) Nuclear "Mark all messages as read" (marks all messages as read in
server-side folder, irrespective of which messages have been downloaded)
35) Forward (alternate) to allow forwarding email through other programs
36) Accept text/plain Intents to allow other programs to send email through K9mail
37) Displays Outbox sending status
38) Manual retry of outbox sending when "Refresh"ing Outbox
39) Folder error status is persisted
40) Ability to log to arbitrary file
Fixes K9 issues 11, 23, 24, 65, 69, 71, 79, 81, 82, 83, 87, 101, 104,
107, 120, 148, 154
2008-12-30 22:49:09 -05:00
|
|
|
throw new UnsupportedOperationException("Pop3: No getMessages");
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-12-19 04:01:34 -05:00
|
|
|
public List<Pop3Message> getMessages(String[] uids, MessageRetrievalListener listener)
|
2011-02-06 17:09:48 -05:00
|
|
|
throws MessagingException {
|
Complete merge of DAmail functionality into K9mail. Following
features are added to K9mail:
1) Show unread message count on each folder
2) Sum unread count of all shown folders in an account to the account display
3) Periodically check selected folders for new mail, not just Inbox
4) Don't refresh folder when opened (unless folder is empty)
5) Show date and time of last sync for each folder
6) Fix timer for automatic periodic sync (use wakelock to assure completion)
7) Optimize local folder queries (speeds up account and folder lists)
8) Show Loading... message in status bar indicating which folder is being synced
9) Eliminate redundant sync of new messages (performance enhancement)
10) Improve notification text for multiple accounts
11) Do not automatically sync folders more often than the account-specific period
12) Use user-configured date and time formats
13) Select which folders are shown, using configurable Classes
14) Select which folders are synced, using configurable Classes
15) Added context (long press) menu to folders, to provide for Refresh
and Folder Settings
16) Status light flashes purple when there are unread messages
17) Folder list more quickly eliminates display of deleted and out-of-Class folders.
18) Delete works
19) Mark all messages as read (in the folder context menu)
20) Notifications only for new unread messages
21) One minute synchronization frequency
22) Deleting an unread message decrements unread counter
23) Notifications work for POP3 accounts
24) Message deletes work for POP3 accounts
25) Explicit errors show in folder list
26) Stack traces saved to folder K9mail-errors
27) Clear pending actions (danger, for emergencies only!)
28) Delete policy in Account settings
29) DNS cache in InetAddress disabled
30) Trapped some crash-causing error conditions
31) Eliminate duplicate copies to Sent folder
32) Prevent crashes due to message listener concurrency
33) Empty Trash
34) Nuclear "Mark all messages as read" (marks all messages as read in
server-side folder, irrespective of which messages have been downloaded)
35) Forward (alternate) to allow forwarding email through other programs
36) Accept text/plain Intents to allow other programs to send email through K9mail
37) Displays Outbox sending status
38) Manual retry of outbox sending when "Refresh"ing Outbox
39) Folder error status is persisted
40) Ability to log to arbitrary file
Fixes K9 issues 11, 23, 24, 65, 69, 71, 79, 81, 82, 83, 87, 101, 104,
107, 120, 148, 154
2008-12-30 22:49:09 -05:00
|
|
|
throw new UnsupportedOperationException("Pop3: No getMessages by uids");
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetch the items contained in the FetchProfile into the given set of
|
|
|
|
* Messages in as efficient a manner as possible.
|
|
|
|
* @param messages
|
|
|
|
* @param fp
|
|
|
|
* @throws MessagingException
|
|
|
|
*/
|
2010-04-16 08:20:10 -04:00
|
|
|
@Override
|
2014-12-19 03:54:17 -05:00
|
|
|
public void fetch(List<Pop3Message> messages, FetchProfile fp, MessageRetrievalListener<Pop3Message> listener)
|
2011-02-06 17:09:48 -05:00
|
|
|
throws MessagingException {
|
2014-10-05 04:40:57 -04:00
|
|
|
if (messages == null || messages.isEmpty()) {
|
2008-11-01 17:32:06 -04:00
|
|
|
return;
|
|
|
|
}
|
2014-10-04 06:45:45 -04:00
|
|
|
List<String> uids = new ArrayList<String>();
|
2011-02-06 17:09:48 -05:00
|
|
|
for (Message message : messages) {
|
2008-11-01 17:32:06 -04:00
|
|
|
uids.add(message.getUid());
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2008-11-01 17:32:06 -04:00
|
|
|
indexUids(uids);
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (IOException ioe) {
|
2008-11-01 17:32:06 -04:00
|
|
|
throw new MessagingException("fetch", ioe);
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
|
|
|
if (fp.contains(FetchProfile.Item.ENVELOPE)) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* We pass the listener only if there are other things to do in the
|
|
|
|
* FetchProfile. Since fetchEnvelop works in bulk and eveything else
|
|
|
|
* works one at a time if we let fetchEnvelope send events the
|
|
|
|
* event would get sent twice.
|
|
|
|
*/
|
|
|
|
fetchEnvelope(messages, fp.size() == 1 ? listener : null);
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (IOException ioe) {
|
2008-11-01 17:32:06 -04:00
|
|
|
throw new MessagingException("fetch", ioe);
|
|
|
|
}
|
2014-10-04 05:37:30 -04:00
|
|
|
for (int i = 0, count = messages.size(); i < count; i++) {
|
2014-12-19 03:54:17 -05:00
|
|
|
Pop3Message pop3Message = messages.get(i);
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
|
|
|
if (listener != null && !fp.contains(FetchProfile.Item.ENVELOPE)) {
|
2008-11-01 17:32:06 -04:00
|
|
|
listener.messageStarted(pop3Message.getUid(), i, count);
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (fp.contains(FetchProfile.Item.BODY)) {
|
2008-11-01 17:32:06 -04:00
|
|
|
fetchBody(pop3Message, -1);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else if (fp.contains(FetchProfile.Item.BODY_SANE)) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* To convert the suggested download size we take the size
|
|
|
|
* divided by the maximum line size (76).
|
|
|
|
*/
|
2014-12-11 22:23:32 -05:00
|
|
|
if (mStoreConfig.getMaximumAutoDownloadMessageSize() > 0) {
|
2011-07-02 15:29:49 -04:00
|
|
|
fetchBody(pop3Message,
|
2014-12-11 22:23:32 -05:00
|
|
|
(mStoreConfig.getMaximumAutoDownloadMessageSize() / 76));
|
2011-07-02 15:29:49 -04:00
|
|
|
} else {
|
|
|
|
fetchBody(pop3Message, -1);
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} else if (fp.contains(FetchProfile.Item.STRUCTURE)) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* If the user is requesting STRUCTURE we are required to set the body
|
|
|
|
* to null since we do not support the function.
|
|
|
|
*/
|
|
|
|
pop3Message.setBody(null);
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (listener != null && !(fp.contains(FetchProfile.Item.ENVELOPE) && fp.size() == 1)) {
|
2014-12-11 22:23:32 -05:00
|
|
|
listener.messageFinished(pop3Message, i, count);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (IOException ioe) {
|
2008-11-01 17:32:06 -04:00
|
|
|
throw new MessagingException("Unable to fetch message", ioe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-19 03:54:17 -05:00
|
|
|
private void fetchEnvelope(List<Pop3Message> messages,
|
|
|
|
MessageRetrievalListener<Pop3Message> listener) throws IOException, MessagingException {
|
2008-11-01 17:32:06 -04:00
|
|
|
int unsizedMessages = 0;
|
2011-02-06 17:09:48 -05:00
|
|
|
for (Message message : messages) {
|
|
|
|
if (message.getSize() == -1) {
|
2008-11-01 17:32:06 -04:00
|
|
|
unsizedMessages++;
|
|
|
|
}
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (unsizedMessages == 0) {
|
2008-11-01 17:32:06 -04:00
|
|
|
return;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (unsizedMessages < 50 && mMessageCount > 5000) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* In extreme cases we'll do a command per message instead of a bulk request
|
|
|
|
* to hopefully save some time and bandwidth.
|
|
|
|
*/
|
2014-10-04 05:37:30 -04:00
|
|
|
for (int i = 0, count = messages.size(); i < count; i++) {
|
2014-12-19 03:54:17 -05:00
|
|
|
Pop3Message message = messages.get(i);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (listener != null) {
|
2014-12-19 03:54:17 -05:00
|
|
|
listener.messageStarted(message.getUid(), i, count);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
2014-03-03 10:40:23 -05:00
|
|
|
String response = executeSimpleCommand(String.format(Locale.US, LIST_COMMAND + " %d",
|
2014-12-19 03:54:17 -05:00
|
|
|
mUidToMsgNumMap.get(message.getUid())));
|
2008-11-01 17:32:06 -04:00
|
|
|
String[] listParts = response.split(" ");
|
2010-04-16 08:20:10 -04:00
|
|
|
//int msgNum = Integer.parseInt(listParts[1]);
|
2008-11-01 17:32:06 -04:00
|
|
|
int msgSize = Integer.parseInt(listParts[2]);
|
2014-12-19 03:54:17 -05:00
|
|
|
message.setSize(msgSize);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (listener != null) {
|
2014-12-19 03:54:17 -05:00
|
|
|
listener.messageFinished(message, i, count);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2014-02-15 17:48:35 -05:00
|
|
|
Set<String> msgUidIndex = new HashSet<String>();
|
2011-02-06 17:09:48 -05:00
|
|
|
for (Message message : messages) {
|
2008-11-01 17:32:06 -04:00
|
|
|
msgUidIndex.add(message.getUid());
|
|
|
|
}
|
2014-10-04 05:37:30 -04:00
|
|
|
int i = 0, count = messages.size();
|
2011-07-17 08:13:04 -04:00
|
|
|
String response = executeSimpleCommand(LIST_COMMAND);
|
2011-02-06 17:09:48 -05:00
|
|
|
while ((response = readLine()) != null) {
|
|
|
|
if (response.equals(".")) {
|
2008-11-01 17:32:06 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
String[] listParts = response.split(" ");
|
|
|
|
int msgNum = Integer.parseInt(listParts[0]);
|
|
|
|
int msgSize = Integer.parseInt(listParts[1]);
|
|
|
|
Pop3Message pop3Message = mMsgNumToMsgMap.get(msgNum);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (pop3Message != null && msgUidIndex.contains(pop3Message.getUid())) {
|
|
|
|
if (listener != null) {
|
2008-11-01 17:32:06 -04:00
|
|
|
listener.messageStarted(pop3Message.getUid(), i, count);
|
|
|
|
}
|
|
|
|
pop3Message.setSize(msgSize);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (listener != null) {
|
2008-11-01 17:32:06 -04:00
|
|
|
listener.messageFinished(pop3Message, i, count);
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-05-14 15:40:21 -04:00
|
|
|
* Fetches the body of the given message, limiting the downloaded data to the specified
|
|
|
|
* number of lines if possible.
|
|
|
|
*
|
|
|
|
* If lines is -1 the entire message is fetched. This is implemented with RETR for
|
|
|
|
* lines = -1 or TOP for any other value. If the server does not support TOP, RETR is used
|
|
|
|
* instead.
|
2008-11-01 17:32:06 -04:00
|
|
|
*/
|
|
|
|
private void fetchBody(Pop3Message message, int lines)
|
2011-02-06 17:09:48 -05:00
|
|
|
throws IOException, MessagingException {
|
2008-11-01 17:32:06 -04:00
|
|
|
String response = null;
|
2011-05-14 15:40:21 -04:00
|
|
|
|
|
|
|
// Try hard to use the TOP command if we're not asked to download the whole message.
|
|
|
|
if (lines != -1 && (!mTopNotSupported || mCapabilities.top)) {
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2014-12-16 06:51:52 -05:00
|
|
|
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3 && !mCapabilities.top) {
|
|
|
|
Log.d(LOG_TAG, "This server doesn't support the CAPA command. " +
|
2011-06-01 16:03:56 -04:00
|
|
|
"Checking to see if the TOP command is supported nevertheless.");
|
2009-05-10 01:47:26 -04:00
|
|
|
}
|
2011-05-14 15:40:21 -04:00
|
|
|
|
2014-03-03 10:40:23 -05:00
|
|
|
response = executeSimpleCommand(String.format(Locale.US, TOP_COMMAND + " %d %d",
|
2011-06-01 16:03:56 -04:00
|
|
|
mUidToMsgNumMap.get(message.getUid()), lines));
|
2011-05-14 15:40:21 -04:00
|
|
|
|
|
|
|
// TOP command is supported. Remember this for the next time.
|
|
|
|
mCapabilities.top = true;
|
|
|
|
} catch (Pop3ErrorResponse e) {
|
|
|
|
if (mCapabilities.top) {
|
|
|
|
// The TOP command should be supported but something went wrong.
|
|
|
|
throw e;
|
|
|
|
} else {
|
2014-12-16 06:51:52 -05:00
|
|
|
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
|
|
|
|
Log.d(LOG_TAG, "The server really doesn't support the TOP " +
|
2011-06-01 16:03:56 -04:00
|
|
|
"command. Using RETR instead.");
|
2011-05-14 15:40:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Don't try to use the TOP command again.
|
|
|
|
mTopNotSupported = true;
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-14 15:40:21 -04:00
|
|
|
|
|
|
|
if (response == null) {
|
2014-03-03 10:40:23 -05:00
|
|
|
executeSimpleCommand(String.format(Locale.US, RETR_COMMAND + " %d",
|
2011-11-03 01:02:41 -04:00
|
|
|
mUidToMsgNumMap.get(message.getUid())));
|
2011-05-14 15:40:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
message.parse(new Pop3ResponseInputStream(mIn));
|
|
|
|
|
|
|
|
// TODO: if we've received fewer lines than requested we also have the complete message.
|
|
|
|
if (lines == -1 || !mCapabilities.top) {
|
|
|
|
message.setFlag(Flag.X_DOWNLOADED_FULL, true);
|
|
|
|
}
|
|
|
|
} catch (MessagingException me) {
|
|
|
|
/*
|
|
|
|
* If we're only downloading headers it's possible
|
|
|
|
* we'll get a broken MIME message which we're not
|
|
|
|
* real worried about. If we've downloaded the body
|
|
|
|
* and can't parse it we need to let the user know.
|
|
|
|
*/
|
|
|
|
if (lines == -1) {
|
|
|
|
throw me;
|
|
|
|
}
|
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
2010-04-16 08:20:10 -04:00
|
|
|
@Override
|
2014-10-04 05:37:30 -04:00
|
|
|
public Map<String, String> appendMessages(List<? extends Message> messages) throws MessagingException {
|
2011-06-28 07:20:48 -04:00
|
|
|
return null;
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
2010-04-16 08:20:10 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void delete(boolean recurse) throws MessagingException {
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
2009-12-06 19:56:06 -05:00
|
|
|
|
2010-04-16 08:20:10 -04:00
|
|
|
@Override
|
2014-10-04 05:37:30 -04:00
|
|
|
public void delete(List<? extends Message> msgs, String trashFolderName) throws MessagingException {
|
|
|
|
setFlags(msgs, Collections.singleton(Flag.DELETED), true);
|
2009-11-29 13:18:52 -05:00
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
Complete merge of DAmail functionality into K9mail. Following
features are added to K9mail:
1) Show unread message count on each folder
2) Sum unread count of all shown folders in an account to the account display
3) Periodically check selected folders for new mail, not just Inbox
4) Don't refresh folder when opened (unless folder is empty)
5) Show date and time of last sync for each folder
6) Fix timer for automatic periodic sync (use wakelock to assure completion)
7) Optimize local folder queries (speeds up account and folder lists)
8) Show Loading... message in status bar indicating which folder is being synced
9) Eliminate redundant sync of new messages (performance enhancement)
10) Improve notification text for multiple accounts
11) Do not automatically sync folders more often than the account-specific period
12) Use user-configured date and time formats
13) Select which folders are shown, using configurable Classes
14) Select which folders are synced, using configurable Classes
15) Added context (long press) menu to folders, to provide for Refresh
and Folder Settings
16) Status light flashes purple when there are unread messages
17) Folder list more quickly eliminates display of deleted and out-of-Class folders.
18) Delete works
19) Mark all messages as read (in the folder context menu)
20) Notifications only for new unread messages
21) One minute synchronization frequency
22) Deleting an unread message decrements unread counter
23) Notifications work for POP3 accounts
24) Message deletes work for POP3 accounts
25) Explicit errors show in folder list
26) Stack traces saved to folder K9mail-errors
27) Clear pending actions (danger, for emergencies only!)
28) Delete policy in Account settings
29) DNS cache in InetAddress disabled
30) Trapped some crash-causing error conditions
31) Eliminate duplicate copies to Sent folder
32) Prevent crashes due to message listener concurrency
33) Empty Trash
34) Nuclear "Mark all messages as read" (marks all messages as read in
server-side folder, irrespective of which messages have been downloaded)
35) Forward (alternate) to allow forwarding email through other programs
36) Accept text/plain Intents to allow other programs to send email through K9mail
37) Displays Outbox sending status
38) Manual retry of outbox sending when "Refresh"ing Outbox
39) Folder error status is persisted
40) Ability to log to arbitrary file
Fixes K9 issues 11, 23, 24, 65, 69, 71, 79, 81, 82, 83, 87, 101, 104,
107, 120, 148, 154
2008-12-30 22:49:09 -05:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public String getUidFromMessageId(Message message) throws MessagingException {
|
2009-11-24 19:40:29 -05:00
|
|
|
return null;
|
Complete merge of DAmail functionality into K9mail. Following
features are added to K9mail:
1) Show unread message count on each folder
2) Sum unread count of all shown folders in an account to the account display
3) Periodically check selected folders for new mail, not just Inbox
4) Don't refresh folder when opened (unless folder is empty)
5) Show date and time of last sync for each folder
6) Fix timer for automatic periodic sync (use wakelock to assure completion)
7) Optimize local folder queries (speeds up account and folder lists)
8) Show Loading... message in status bar indicating which folder is being synced
9) Eliminate redundant sync of new messages (performance enhancement)
10) Improve notification text for multiple accounts
11) Do not automatically sync folders more often than the account-specific period
12) Use user-configured date and time formats
13) Select which folders are shown, using configurable Classes
14) Select which folders are synced, using configurable Classes
15) Added context (long press) menu to folders, to provide for Refresh
and Folder Settings
16) Status light flashes purple when there are unread messages
17) Folder list more quickly eliminates display of deleted and out-of-Class folders.
18) Delete works
19) Mark all messages as read (in the folder context menu)
20) Notifications only for new unread messages
21) One minute synchronization frequency
22) Deleting an unread message decrements unread counter
23) Notifications work for POP3 accounts
24) Message deletes work for POP3 accounts
25) Explicit errors show in folder list
26) Stack traces saved to folder K9mail-errors
27) Clear pending actions (danger, for emergencies only!)
28) Delete policy in Account settings
29) DNS cache in InetAddress disabled
30) Trapped some crash-causing error conditions
31) Eliminate duplicate copies to Sent folder
32) Prevent crashes due to message listener concurrency
33) Empty Trash
34) Nuclear "Mark all messages as read" (marks all messages as read in
server-side folder, irrespective of which messages have been downloaded)
35) Forward (alternate) to allow forwarding email through other programs
36) Accept text/plain Intents to allow other programs to send email through K9mail
37) Displays Outbox sending status
38) Manual retry of outbox sending when "Refresh"ing Outbox
39) Folder error status is persisted
40) Ability to log to arbitrary file
Fixes K9 issues 11, 23, 24, 65, 69, 71, 79, 81, 82, 83, 87, 101, 104,
107, 120, 148, 154
2008-12-30 22:49:09 -05:00
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
Complete merge of DAmail functionality into K9mail. Following
features are added to K9mail:
1) Show unread message count on each folder
2) Sum unread count of all shown folders in an account to the account display
3) Periodically check selected folders for new mail, not just Inbox
4) Don't refresh folder when opened (unless folder is empty)
5) Show date and time of last sync for each folder
6) Fix timer for automatic periodic sync (use wakelock to assure completion)
7) Optimize local folder queries (speeds up account and folder lists)
8) Show Loading... message in status bar indicating which folder is being synced
9) Eliminate redundant sync of new messages (performance enhancement)
10) Improve notification text for multiple accounts
11) Do not automatically sync folders more often than the account-specific period
12) Use user-configured date and time formats
13) Select which folders are shown, using configurable Classes
14) Select which folders are synced, using configurable Classes
15) Added context (long press) menu to folders, to provide for Refresh
and Folder Settings
16) Status light flashes purple when there are unread messages
17) Folder list more quickly eliminates display of deleted and out-of-Class folders.
18) Delete works
19) Mark all messages as read (in the folder context menu)
20) Notifications only for new unread messages
21) One minute synchronization frequency
22) Deleting an unread message decrements unread counter
23) Notifications work for POP3 accounts
24) Message deletes work for POP3 accounts
25) Explicit errors show in folder list
26) Stack traces saved to folder K9mail-errors
27) Clear pending actions (danger, for emergencies only!)
28) Delete policy in Account settings
29) DNS cache in InetAddress disabled
30) Trapped some crash-causing error conditions
31) Eliminate duplicate copies to Sent folder
32) Prevent crashes due to message listener concurrency
33) Empty Trash
34) Nuclear "Mark all messages as read" (marks all messages as read in
server-side folder, irrespective of which messages have been downloaded)
35) Forward (alternate) to allow forwarding email through other programs
36) Accept text/plain Intents to allow other programs to send email through K9mail
37) Displays Outbox sending status
38) Manual retry of outbox sending when "Refresh"ing Outbox
39) Folder error status is persisted
40) Ability to log to arbitrary file
Fixes K9 issues 11, 23, 24, 65, 69, 71, 79, 81, 82, 83, 87, 101, 104,
107, 120, 148, 154
2008-12-30 22:49:09 -05:00
|
|
|
@Override
|
2014-10-05 07:40:35 -04:00
|
|
|
public void setFlags(final Set<Flag> flags, boolean value) throws MessagingException {
|
|
|
|
throw new UnsupportedOperationException("POP3: No setFlags(Set<Flag>,boolean)");
|
Complete merge of DAmail functionality into K9mail. Following
features are added to K9mail:
1) Show unread message count on each folder
2) Sum unread count of all shown folders in an account to the account display
3) Periodically check selected folders for new mail, not just Inbox
4) Don't refresh folder when opened (unless folder is empty)
5) Show date and time of last sync for each folder
6) Fix timer for automatic periodic sync (use wakelock to assure completion)
7) Optimize local folder queries (speeds up account and folder lists)
8) Show Loading... message in status bar indicating which folder is being synced
9) Eliminate redundant sync of new messages (performance enhancement)
10) Improve notification text for multiple accounts
11) Do not automatically sync folders more often than the account-specific period
12) Use user-configured date and time formats
13) Select which folders are shown, using configurable Classes
14) Select which folders are synced, using configurable Classes
15) Added context (long press) menu to folders, to provide for Refresh
and Folder Settings
16) Status light flashes purple when there are unread messages
17) Folder list more quickly eliminates display of deleted and out-of-Class folders.
18) Delete works
19) Mark all messages as read (in the folder context menu)
20) Notifications only for new unread messages
21) One minute synchronization frequency
22) Deleting an unread message decrements unread counter
23) Notifications work for POP3 accounts
24) Message deletes work for POP3 accounts
25) Explicit errors show in folder list
26) Stack traces saved to folder K9mail-errors
27) Clear pending actions (danger, for emergencies only!)
28) Delete policy in Account settings
29) DNS cache in InetAddress disabled
30) Trapped some crash-causing error conditions
31) Eliminate duplicate copies to Sent folder
32) Prevent crashes due to message listener concurrency
33) Empty Trash
34) Nuclear "Mark all messages as read" (marks all messages as read in
server-side folder, irrespective of which messages have been downloaded)
35) Forward (alternate) to allow forwarding email through other programs
36) Accept text/plain Intents to allow other programs to send email through K9mail
37) Displays Outbox sending status
38) Manual retry of outbox sending when "Refresh"ing Outbox
39) Folder error status is persisted
40) Ability to log to arbitrary file
Fixes K9 issues 11, 23, 24, 65, 69, 71, 79, 81, 82, 83, 87, 101, 104,
107, 120, 148, 154
2008-12-30 22:49:09 -05:00
|
|
|
}
|
|
|
|
|
2010-04-16 08:20:10 -04:00
|
|
|
@Override
|
2014-10-05 07:40:35 -04:00
|
|
|
public void setFlags(List<? extends Message> messages, final Set<Flag> flags, boolean value)
|
2011-02-06 17:09:48 -05:00
|
|
|
throws MessagingException {
|
2014-10-04 05:37:30 -04:00
|
|
|
if (!value || !flags.contains(Flag.DELETED)) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* The only flagging we support is setting the Deleted flag.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
2014-10-04 06:45:45 -04:00
|
|
|
List<String> uids = new ArrayList<String>();
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
|
|
|
for (Message message : messages) {
|
2009-11-24 19:40:29 -05:00
|
|
|
uids.add(message.getUid());
|
|
|
|
}
|
|
|
|
|
|
|
|
indexUids(uids);
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (IOException ioe) {
|
2009-11-24 19:40:29 -05:00
|
|
|
throw new MessagingException("Could not get message number for uid " + uids, ioe);
|
Complete merge of DAmail functionality into K9mail. Following
features are added to K9mail:
1) Show unread message count on each folder
2) Sum unread count of all shown folders in an account to the account display
3) Periodically check selected folders for new mail, not just Inbox
4) Don't refresh folder when opened (unless folder is empty)
5) Show date and time of last sync for each folder
6) Fix timer for automatic periodic sync (use wakelock to assure completion)
7) Optimize local folder queries (speeds up account and folder lists)
8) Show Loading... message in status bar indicating which folder is being synced
9) Eliminate redundant sync of new messages (performance enhancement)
10) Improve notification text for multiple accounts
11) Do not automatically sync folders more often than the account-specific period
12) Use user-configured date and time formats
13) Select which folders are shown, using configurable Classes
14) Select which folders are synced, using configurable Classes
15) Added context (long press) menu to folders, to provide for Refresh
and Folder Settings
16) Status light flashes purple when there are unread messages
17) Folder list more quickly eliminates display of deleted and out-of-Class folders.
18) Delete works
19) Mark all messages as read (in the folder context menu)
20) Notifications only for new unread messages
21) One minute synchronization frequency
22) Deleting an unread message decrements unread counter
23) Notifications work for POP3 accounts
24) Message deletes work for POP3 accounts
25) Explicit errors show in folder list
26) Stack traces saved to folder K9mail-errors
27) Clear pending actions (danger, for emergencies only!)
28) Delete policy in Account settings
29) DNS cache in InetAddress disabled
30) Trapped some crash-causing error conditions
31) Eliminate duplicate copies to Sent folder
32) Prevent crashes due to message listener concurrency
33) Empty Trash
34) Nuclear "Mark all messages as read" (marks all messages as read in
server-side folder, irrespective of which messages have been downloaded)
35) Forward (alternate) to allow forwarding email through other programs
36) Accept text/plain Intents to allow other programs to send email through K9mail
37) Displays Outbox sending status
38) Manual retry of outbox sending when "Refresh"ing Outbox
39) Folder error status is persisted
40) Ability to log to arbitrary file
Fixes K9 issues 11, 23, 24, 65, 69, 71, 79, 81, 82, 83, 87, 101, 104,
107, 120, 148, 154
2008-12-30 22:49:09 -05:00
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
for (Message message : messages) {
|
2009-11-24 19:40:29 -05:00
|
|
|
|
|
|
|
Integer msgNum = mUidToMsgNumMap.get(message.getUid());
|
2011-02-06 17:09:48 -05:00
|
|
|
if (msgNum == null) {
|
2009-11-24 19:40:29 -05:00
|
|
|
MessagingException me = new MessagingException("Could not delete message " + message.getUid()
|
|
|
|
+ " because no msgNum found; permanent error");
|
|
|
|
me.setPermanentFailure(true);
|
|
|
|
throw me;
|
|
|
|
}
|
2011-07-17 08:13:04 -04:00
|
|
|
executeSimpleCommand(String.format(DELE_COMMAND + " %s", msgNum));
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private String readLine() throws IOException {
|
2011-09-30 02:18:00 -04:00
|
|
|
StringBuilder sb = new StringBuilder();
|
2008-11-01 17:32:06 -04:00
|
|
|
int d = mIn.read();
|
2011-02-06 17:09:48 -05:00
|
|
|
if (d == -1) {
|
2008-11-01 17:32:06 -04:00
|
|
|
throw new IOException("End of stream reached while trying to read line.");
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
do {
|
|
|
|
if (((char)d) == '\r') {
|
2008-11-01 17:32:06 -04:00
|
|
|
continue;
|
2011-02-06 17:09:48 -05:00
|
|
|
} else if (((char)d) == '\n') {
|
2008-11-01 17:32:06 -04:00
|
|
|
break;
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2008-11-01 17:32:06 -04:00
|
|
|
sb.append((char)d);
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} while ((d = mIn.read()) != -1);
|
2008-11-01 17:32:06 -04:00
|
|
|
String ret = sb.toString();
|
2014-12-16 06:51:52 -05:00
|
|
|
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
|
|
|
|
Log.d(LOG_TAG, "<<< " + ret);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private void writeLine(String s) throws IOException {
|
2008-11-01 17:32:06 -04:00
|
|
|
mOut.write(s.getBytes());
|
|
|
|
mOut.write('\r');
|
|
|
|
mOut.write('\n');
|
|
|
|
mOut.flush();
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private Pop3Capabilities getCapabilities() throws IOException {
|
2008-11-01 17:32:06 -04:00
|
|
|
Pop3Capabilities capabilities = new Pop3Capabilities();
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
try {
|
|
|
|
/*
|
|
|
|
* Try sending an AUTH command with no arguments.
|
|
|
|
*
|
|
|
|
* The server may respond with a list of supported SASL
|
|
|
|
* authentication mechanisms.
|
|
|
|
*
|
|
|
|
* Ref.: http://tools.ietf.org/html/draft-myers-sasl-pop3-05
|
|
|
|
*
|
|
|
|
* While this never became a standard, there are servers that
|
|
|
|
* support it, and Thunderbird includes this check.
|
|
|
|
*/
|
|
|
|
String response = executeSimpleCommand(AUTH_COMMAND);
|
|
|
|
while ((response = readLine()) != null) {
|
|
|
|
if (response.equals(".")) {
|
|
|
|
break;
|
|
|
|
}
|
2014-03-03 10:08:07 -05:00
|
|
|
response = response.toUpperCase(Locale.US);
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
if (response.equals(AUTH_PLAIN_CAPABILITY)) {
|
|
|
|
capabilities.authPlain = true;
|
|
|
|
} else if (response.equals(AUTH_CRAM_MD5_CAPABILITY)) {
|
|
|
|
capabilities.cramMD5 = true;
|
2014-05-25 16:45:14 -04:00
|
|
|
} else if (response.equals(AUTH_EXTERNAL_CAPABILITY)) {
|
|
|
|
capabilities.external = true;
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
// Assume AUTH command with no arguments is not supported.
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2011-07-17 08:13:04 -04:00
|
|
|
String response = executeSimpleCommand(CAPA_COMMAND);
|
2011-02-06 17:09:48 -05:00
|
|
|
while ((response = readLine()) != null) {
|
|
|
|
if (response.equals(".")) {
|
2008-11-01 17:32:06 -04:00
|
|
|
break;
|
|
|
|
}
|
2014-03-03 10:08:07 -05:00
|
|
|
response = response.toUpperCase(Locale.US);
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
if (response.equals(STLS_CAPABILITY)) {
|
2008-11-01 17:32:06 -04:00
|
|
|
capabilities.stls = true;
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
} else if (response.equals(UIDL_CAPABILITY)) {
|
2008-11-01 17:32:06 -04:00
|
|
|
capabilities.uidl = true;
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
} else if (response.equals(TOP_CAPABILITY)) {
|
2008-11-01 17:32:06 -04:00
|
|
|
capabilities.top = true;
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
} else if (response.startsWith(SASL_CAPABILITY)) {
|
|
|
|
List<String> saslAuthMechanisms = Arrays.asList(response.split(" "));
|
|
|
|
if (saslAuthMechanisms.contains(AUTH_PLAIN_CAPABILITY)) {
|
|
|
|
capabilities.authPlain = true;
|
|
|
|
}
|
|
|
|
if (saslAuthMechanisms.contains(AUTH_CRAM_MD5_CAPABILITY)) {
|
|
|
|
capabilities.cramMD5 = true;
|
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
2011-05-14 15:40:21 -04:00
|
|
|
|
|
|
|
if (!capabilities.top) {
|
|
|
|
/*
|
|
|
|
* If the CAPA command is supported but it doesn't advertise support for the
|
|
|
|
* TOP command, we won't check for it manually.
|
|
|
|
*/
|
|
|
|
mTopNotSupported = true;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (MessagingException me) {
|
2008-11-01 17:32:06 -04:00
|
|
|
/*
|
|
|
|
* The server may not support the CAPA command, so we just eat this Exception
|
|
|
|
* and allow the empty capabilities object to be returned.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
return capabilities;
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private String executeSimpleCommand(String command) throws MessagingException {
|
2010-07-29 20:53:46 -04:00
|
|
|
return executeSimpleCommand(command, false);
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private String executeSimpleCommand(String command, boolean sensitive) throws MessagingException {
|
|
|
|
try {
|
2013-07-30 16:36:47 -04:00
|
|
|
open(Folder.OPEN_MODE_RW);
|
2010-07-29 20:53:46 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
if (command != null) {
|
2014-12-16 06:51:52 -05:00
|
|
|
if (K9MailLib.isDebug() && DEBUG_PROTOCOL_POP3) {
|
|
|
|
if (sensitive && !K9MailLib.isDebugSensitive()) {
|
|
|
|
Log.d(LOG_TAG, ">>> "
|
2010-07-29 20:53:46 -04:00
|
|
|
+ "[Command Hidden, Enable Sensitive Debug Logging To Show]");
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2014-12-16 06:51:52 -05:00
|
|
|
Log.d(LOG_TAG, ">>> " + command);
|
2010-07-29 20:53:46 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-06 01:55:29 -05:00
|
|
|
writeLine(command);
|
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2008-11-06 01:55:29 -05:00
|
|
|
String response = readLine();
|
2014-03-08 18:41:43 -05:00
|
|
|
if (response.length() == 0 || response.charAt(0) != '+') {
|
2011-05-14 15:40:21 -04:00
|
|
|
throw new Pop3ErrorResponse(response);
|
2008-11-06 01:55:29 -05:00
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2008-11-06 01:55:29 -05:00
|
|
|
return response;
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (MessagingException me) {
|
2009-11-24 19:40:29 -05:00
|
|
|
throw me;
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (Exception e) {
|
2008-11-06 01:55:29 -05:00
|
|
|
closeIO();
|
2009-04-10 22:11:17 -04:00
|
|
|
throw new MessagingException("Unable to execute POP3 command", e);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-14 17:19:24 -04:00
|
|
|
@Override
|
|
|
|
public boolean isFlagSupported(Flag flag) {
|
|
|
|
return (flag == Flag.DELETED);
|
|
|
|
}
|
|
|
|
|
2008-12-14 01:18:24 -05:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean supportsFetchingFlags() {
|
2008-12-14 01:18:24 -05:00
|
|
|
return false;
|
2011-01-23 22:27:26 -05:00
|
|
|
}
|
2008-12-14 01:18:24 -05:00
|
|
|
|
2008-11-01 17:32:06 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean equals(Object o) {
|
|
|
|
if (o instanceof Pop3Folder) {
|
2008-11-01 17:32:06 -04:00
|
|
|
return ((Pop3Folder) o).mName.equals(mName);
|
|
|
|
}
|
|
|
|
return super.equals(o);
|
|
|
|
}
|
2010-04-29 00:59:14 -04:00
|
|
|
|
2010-04-16 08:20:10 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int hashCode() {
|
2010-04-16 08:20:10 -04:00
|
|
|
return mName.hashCode();
|
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
2008-12-14 01:18:24 -05:00
|
|
|
}//Pop3Folder
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
static class Pop3Message extends MimeMessage {
|
|
|
|
public Pop3Message(String uid, Pop3Folder folder) {
|
2008-11-01 17:32:06 -04:00
|
|
|
mUid = uid;
|
|
|
|
mFolder = folder;
|
|
|
|
mSize = -1;
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void setSize(int size) {
|
2008-11-01 17:32:06 -04:00
|
|
|
mSize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void setFlag(Flag flag, boolean set) throws MessagingException {
|
2008-11-01 17:32:06 -04:00
|
|
|
super.setFlag(flag, set);
|
2014-10-05 07:40:35 -04:00
|
|
|
mFolder.setFlags(Collections.singletonList(this), Collections.singleton(flag), set);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
2009-11-24 19:40:29 -05:00
|
|
|
|
Complete merge of DAmail functionality into K9mail. Following
features are added to K9mail:
1) Show unread message count on each folder
2) Sum unread count of all shown folders in an account to the account display
3) Periodically check selected folders for new mail, not just Inbox
4) Don't refresh folder when opened (unless folder is empty)
5) Show date and time of last sync for each folder
6) Fix timer for automatic periodic sync (use wakelock to assure completion)
7) Optimize local folder queries (speeds up account and folder lists)
8) Show Loading... message in status bar indicating which folder is being synced
9) Eliminate redundant sync of new messages (performance enhancement)
10) Improve notification text for multiple accounts
11) Do not automatically sync folders more often than the account-specific period
12) Use user-configured date and time formats
13) Select which folders are shown, using configurable Classes
14) Select which folders are synced, using configurable Classes
15) Added context (long press) menu to folders, to provide for Refresh
and Folder Settings
16) Status light flashes purple when there are unread messages
17) Folder list more quickly eliminates display of deleted and out-of-Class folders.
18) Delete works
19) Mark all messages as read (in the folder context menu)
20) Notifications only for new unread messages
21) One minute synchronization frequency
22) Deleting an unread message decrements unread counter
23) Notifications work for POP3 accounts
24) Message deletes work for POP3 accounts
25) Explicit errors show in folder list
26) Stack traces saved to folder K9mail-errors
27) Clear pending actions (danger, for emergencies only!)
28) Delete policy in Account settings
29) DNS cache in InetAddress disabled
30) Trapped some crash-causing error conditions
31) Eliminate duplicate copies to Sent folder
32) Prevent crashes due to message listener concurrency
33) Empty Trash
34) Nuclear "Mark all messages as read" (marks all messages as read in
server-side folder, irrespective of which messages have been downloaded)
35) Forward (alternate) to allow forwarding email through other programs
36) Accept text/plain Intents to allow other programs to send email through K9mail
37) Displays Outbox sending status
38) Manual retry of outbox sending when "Refresh"ing Outbox
39) Folder error status is persisted
40) Ability to log to arbitrary file
Fixes K9 issues 11, 23, 24, 65, 69, 71, 79, 81, 82, 83, 87, 101, 104,
107, 120, 148, 154
2008-12-30 22:49:09 -05:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void delete(String trashFolderName) throws MessagingException {
|
2009-11-24 19:40:29 -05:00
|
|
|
// try
|
|
|
|
// {
|
|
|
|
// Poor POP3 users, we can't copy the message to the Trash folder, but they still want a delete
|
|
|
|
setFlag(Flag.DELETED, true);
|
|
|
|
// }
|
|
|
|
// catch (MessagingException me)
|
|
|
|
// {
|
2014-12-16 06:51:52 -05:00
|
|
|
// Log.w(LOG_TAG, "Could not delete non-existent message", me);
|
2009-11-24 19:40:29 -05:00
|
|
|
// }
|
Complete merge of DAmail functionality into K9mail. Following
features are added to K9mail:
1) Show unread message count on each folder
2) Sum unread count of all shown folders in an account to the account display
3) Periodically check selected folders for new mail, not just Inbox
4) Don't refresh folder when opened (unless folder is empty)
5) Show date and time of last sync for each folder
6) Fix timer for automatic periodic sync (use wakelock to assure completion)
7) Optimize local folder queries (speeds up account and folder lists)
8) Show Loading... message in status bar indicating which folder is being synced
9) Eliminate redundant sync of new messages (performance enhancement)
10) Improve notification text for multiple accounts
11) Do not automatically sync folders more often than the account-specific period
12) Use user-configured date and time formats
13) Select which folders are shown, using configurable Classes
14) Select which folders are synced, using configurable Classes
15) Added context (long press) menu to folders, to provide for Refresh
and Folder Settings
16) Status light flashes purple when there are unread messages
17) Folder list more quickly eliminates display of deleted and out-of-Class folders.
18) Delete works
19) Mark all messages as read (in the folder context menu)
20) Notifications only for new unread messages
21) One minute synchronization frequency
22) Deleting an unread message decrements unread counter
23) Notifications work for POP3 accounts
24) Message deletes work for POP3 accounts
25) Explicit errors show in folder list
26) Stack traces saved to folder K9mail-errors
27) Clear pending actions (danger, for emergencies only!)
28) Delete policy in Account settings
29) DNS cache in InetAddress disabled
30) Trapped some crash-causing error conditions
31) Eliminate duplicate copies to Sent folder
32) Prevent crashes due to message listener concurrency
33) Empty Trash
34) Nuclear "Mark all messages as read" (marks all messages as read in
server-side folder, irrespective of which messages have been downloaded)
35) Forward (alternate) to allow forwarding email through other programs
36) Accept text/plain Intents to allow other programs to send email through K9mail
37) Displays Outbox sending status
38) Manual retry of outbox sending when "Refresh"ing Outbox
39) Folder error status is persisted
40) Ability to log to arbitrary file
Fixes K9 issues 11, 23, 24, 65, 69, 71, 79, 81, 82, 83, 87, 101, 104,
107, 120, 148, 154
2008-12-30 22:49:09 -05:00
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
static class Pop3Capabilities {
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
public boolean cramMD5;
|
|
|
|
public boolean authPlain;
|
2008-11-01 17:32:06 -04:00
|
|
|
public boolean stls;
|
|
|
|
public boolean top;
|
|
|
|
public boolean uidl;
|
2014-05-25 16:45:14 -04:00
|
|
|
public boolean external;
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2010-04-16 08:20:10 -04:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public String toString() {
|
2014-05-25 16:45:14 -04:00
|
|
|
return String.format("CRAM-MD5 %b, PLAIN %b, STLS %b, TOP %b, UIDL %b, EXTERNAL %b",
|
POP3 authentication improvements
Changes:
Extract code and create login() and authCramMD5() methods.
Implement the SASL PLAIN authentication mechanism. Its primary benefit is
the explicit support for UTF-8. If the user has configured "PLAIN"
authentication, then SASL PLAIN will be used, if available, otherwise
login() will be used.
Implement POP3 APOP authentication (issue 3218). If the user has
configured "CRAM_MD5" authentication (a future commit will change this
user option to a localized string "Encrypted password"), then SASL
CRAM-MD5 will be used, if available, otherwise the availability of POP3
APOP will be checked and used (per RFC 2449, there is no APOP
"capability").
Extend getCapabilities() to check for available authentication methods by
sending the "AUTH" command with no arguments
(http://tools.ietf.org/html/draft-myers-sasl-pop3-05). This never became
a standard, but there are servers that support it, and Thunderbird
includes this check.
The SASL PLAIN and CRAM-MD5 authentication methods are not attempted
unless the server professes to have the appropriate capability.
(Previously, CRAM-MD5 was tried regardless of capability.) No check is
made for the USER capability prior to use of that method. All this is the
same behavior as in Thunderbird.
Eliminate the testing for capabilities in cases where the test results are
never used (PIPELINING, USER).
Change when getCapabilities() is called. It is called once upon
connection. If STARTTLS is negotiated (POP3 STLS), then
getCapabilities() is called again after the connection is encrypted (and
the server is authenticated), but before user authentication is attempted.
2014-02-22 17:51:18 -05:00
|
|
|
cramMD5,
|
|
|
|
authPlain,
|
2009-11-24 19:40:29 -05:00
|
|
|
stls,
|
|
|
|
top,
|
2014-05-25 16:45:14 -04:00
|
|
|
uidl,
|
|
|
|
external);
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
static class Pop3ResponseInputStream extends InputStream {
|
2014-09-22 15:52:59 -04:00
|
|
|
private InputStream mIn;
|
|
|
|
private boolean mStartOfLine = true;
|
|
|
|
private boolean mFinished;
|
2008-11-01 17:32:06 -04:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public Pop3ResponseInputStream(InputStream in) {
|
2008-11-01 17:32:06 -04:00
|
|
|
mIn = in;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public int read() throws IOException {
|
|
|
|
if (mFinished) {
|
2008-11-01 17:32:06 -04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
int d = mIn.read();
|
2011-02-06 17:09:48 -05:00
|
|
|
if (mStartOfLine && d == '.') {
|
2008-11-01 17:32:06 -04:00
|
|
|
d = mIn.read();
|
2011-02-06 17:09:48 -05:00
|
|
|
if (d == '\r') {
|
2008-11-01 17:32:06 -04:00
|
|
|
mFinished = true;
|
|
|
|
mIn.read();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mStartOfLine = (d == '\n');
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
2011-05-14 15:40:21 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Exception that is thrown if the server returns an error response.
|
|
|
|
*/
|
|
|
|
static class Pop3ErrorResponse extends MessagingException {
|
2013-02-04 05:18:49 -05:00
|
|
|
private static final long serialVersionUID = 3672087845857867174L;
|
|
|
|
|
2011-05-14 15:40:21 -04:00
|
|
|
public Pop3ErrorResponse(String message) {
|
|
|
|
super(message, true);
|
|
|
|
}
|
|
|
|
}
|
2008-11-01 17:32:06 -04:00
|
|
|
}
|