mirror of https://github.com/M66B/FairEmail.git
Updated Javamail to version 1.6.5
This commit is contained in:
parent
d25834cd27
commit
786fde2ca4
|
@ -242,7 +242,7 @@ dependencies {
|
|||
def exif_version = "1.3.0-alpha01"
|
||||
def biometric_version = "1.0.1"
|
||||
def billingclient_version = "2.1.0"
|
||||
def javamail_version = "1.6.5-SNAPSHOT"
|
||||
def javamail_version = "1.6.5"
|
||||
def jsoup_version = "1.12.1"
|
||||
def dnsjava_version = "2.1.9"
|
||||
def openpgp_version = "12.0"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0, which is available at
|
||||
|
@ -16,7 +16,9 @@
|
|||
|
||||
package com.sun.mail.pop3;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.logging.Level;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
|
@ -280,11 +282,16 @@ public class POP3Store extends Store {
|
|||
|
||||
supportsUidl = capabilities == null || capabilities.containsKey("UIDL");
|
||||
|
||||
String msg = null;
|
||||
if ((msg = p.login(user, passwd)) != null) {
|
||||
throw cleanupAndThrow(p, new EOFException(msg));
|
||||
try {
|
||||
if (!authenticate(p, user, passwd))
|
||||
throw cleanupAndThrow(p, new EOFException("login failed"));
|
||||
} catch (EOFException ex) {
|
||||
throw cleanupAndThrow(p, ex);
|
||||
} catch (Exception ex) {
|
||||
throw cleanupAndThrow(p, new EOFException(ex.getMessage()));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If a Folder closes the port, and then a Folder
|
||||
* is opened, the Store won't have a port. In that
|
||||
|
@ -322,6 +329,117 @@ public class POP3Store extends Store {
|
|||
return ife;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate to the server.
|
||||
*
|
||||
* XXX - This extensible authentication mechanism scheme was adapted
|
||||
* from the SMTPTransport class. The work was done at the last
|
||||
* minute for the 1.6.5 release and so is not as clean as it
|
||||
* could be. There's great confusion over boolean success/failure
|
||||
* return codes vs exceptions. This should all be cleaned up at
|
||||
* some point, and more testing should be done, but I'm leaving
|
||||
* it in this "I believe it works" state for now. I've tested
|
||||
* it with LOGIN, PLAIN, and XOAUTH2 mechanisms, the latter being
|
||||
* the primary motivation for the work right now.
|
||||
*
|
||||
* @param p the Protocol object to use
|
||||
* @param user the user to authenticate as
|
||||
* @param passwd the password for the user
|
||||
* @return true if authentication succeeds
|
||||
* @exception MessagingException if authentication fails
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
private boolean authenticate(Protocol p, String user, String passwd)
|
||||
throws MessagingException {
|
||||
// setting mail.pop3.auth.mechanisms controls which mechanisms will
|
||||
// be used, and in what order they'll be considered. only the first
|
||||
// match is used.
|
||||
String mechs = session.getProperty("mail." + name + ".auth.mechanisms");
|
||||
boolean usingDefaultMechs = false;
|
||||
if (mechs == null) {
|
||||
mechs = p.getDefaultMechanisms();
|
||||
usingDefaultMechs = true;
|
||||
}
|
||||
|
||||
String authzid =
|
||||
session.getProperty("mail." + name + ".sasl.authorizationid");
|
||||
if (authzid == null)
|
||||
authzid = user;
|
||||
/*
|
||||
* XXX - maybe someday
|
||||
*
|
||||
if (enableSASL) {
|
||||
logger.fine("Authenticate with SASL");
|
||||
try {
|
||||
if (sasllogin(getSASLMechanisms(), getSASLRealm(), authzid,
|
||||
user, passwd)) {
|
||||
return true; // success
|
||||
} else {
|
||||
logger.fine("SASL authentication failed");
|
||||
return false;
|
||||
}
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
logger.log(Level.FINE, "SASL support failed", ex);
|
||||
// if the SASL support fails, fall back to non-SASL
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("Attempt to authenticate using mechanisms: " + mechs);
|
||||
|
||||
/*
|
||||
* Loop through the list of mechanisms supplied by the user
|
||||
* (or defaulted) and try each in turn. If the server supports
|
||||
* the mechanism and we have an authenticator for the mechanism,
|
||||
* and it hasn't been disabled, use it.
|
||||
*/
|
||||
StringTokenizer st = new StringTokenizer(mechs);
|
||||
while (st.hasMoreTokens()) {
|
||||
String m = st.nextToken();
|
||||
m = m.toUpperCase(Locale.ENGLISH);
|
||||
if (!p.supportsMechanism(m)) {
|
||||
logger.log(Level.FINE, "no authenticator for mechanism {0}", m);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!p.supportsAuthentication(m)) {
|
||||
logger.log(Level.FINE, "mechanism {0} not supported by server",
|
||||
m);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If using the default mechanisms, check if this one is disabled.
|
||||
*/
|
||||
if (usingDefaultMechs) {
|
||||
String dprop = "mail." + name + ".auth." +
|
||||
m.toLowerCase(Locale.ENGLISH) + ".disable";
|
||||
boolean disabled = PropUtil.getBooleanProperty(
|
||||
session.getProperties(),
|
||||
dprop, !p.isMechanismEnabled(m));
|
||||
if (disabled) {
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("mechanism " + m +
|
||||
" disabled by property: " + dprop);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// only the first supported and enabled mechanism is used
|
||||
logger.log(Level.FINE, "Using mechanism {0}", m);
|
||||
String msg =
|
||||
p.authenticate(m, host, authzid, user, passwd);
|
||||
if (msg != null)
|
||||
throw new AuthenticationFailedException(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if no authentication mechanism found, fail
|
||||
throw new AuthenticationFailedException(
|
||||
"No authentication mechanisms supported by both server and client");
|
||||
}
|
||||
|
||||
private static boolean isRecoverable(Throwable t) {
|
||||
return (t instanceof Exception) || (t instanceof LinkageError);
|
||||
}
|
||||
|
|
|
@ -21,8 +21,13 @@ import java.net.*;
|
|||
import java.io.*;
|
||||
import java.security.*;
|
||||
import java.util.logging.Level;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
import com.sun.mail.auth.Ntlm;
|
||||
import com.sun.mail.util.ASCIIUtility;
|
||||
import com.sun.mail.util.BASE64DecoderStream;
|
||||
import com.sun.mail.util.BASE64EncoderStream;
|
||||
import com.sun.mail.util.PropUtil;
|
||||
import com.sun.mail.util.MailLogger;
|
||||
import com.sun.mail.util.SocketFetcher;
|
||||
|
@ -33,6 +38,7 @@ import com.sun.mail.util.SharedByteArrayOutputStream;
|
|||
|
||||
class Response {
|
||||
boolean ok = false; // true if "+OK"
|
||||
boolean cont = false; // true if "+ " continuation line
|
||||
String data = null; // rest of line after "+OK" or "-ERR"
|
||||
InputStream bytes = null; // all the bytes from a multi-line response
|
||||
}
|
||||
|
@ -61,6 +67,9 @@ class Protocol {
|
|||
private boolean pipelining;
|
||||
private boolean noauthdebug = true; // hide auth info in debug output
|
||||
private boolean traceSuspended; // temporarily suspend tracing
|
||||
private Map<String, Authenticator> authenticators = new HashMap<>();
|
||||
private String defaultAuthenticationMechanisms; // set in constructor
|
||||
private String localHostName;
|
||||
|
||||
private static final int POP3_PORT = 110; // standard POP3 port
|
||||
private static final String CRLF = "\r\n";
|
||||
|
@ -117,6 +126,21 @@ class Protocol {
|
|||
PropUtil.getBooleanProperty(props, prefix + ".pipelining", false);
|
||||
if (pipelining)
|
||||
logger.config("PIPELINING enabled");
|
||||
|
||||
// created here, because they're inner classes that reference "this"
|
||||
Authenticator[] a = new Authenticator[] {
|
||||
new LoginAuthenticator(),
|
||||
new PlainAuthenticator(),
|
||||
//new DigestMD5Authenticator(),
|
||||
new NtlmAuthenticator(),
|
||||
new OAuth2Authenticator()
|
||||
};
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
authenticators.put(a[i].getMechanism(), a[i]);
|
||||
sb.append(a[i].getMechanism()).append(' ');
|
||||
}
|
||||
defaultAuthenticationMechanisms = sb.toString();
|
||||
}
|
||||
|
||||
private static IOException cleanupAndThrow(Socket socket, IOException ife) {
|
||||
|
@ -236,6 +260,84 @@ class Protocol {
|
|||
return capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this Protocol object support the named authentication mechanism?
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
boolean supportsMechanism(String mech) {
|
||||
return authenticators.containsKey(mech.toUpperCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the whitespace separated string list of default authentication
|
||||
* mechanisms.
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
String getDefaultMechanisms() {
|
||||
return defaultAuthenticationMechanisms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the named authentication mechanism enabled?
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
boolean isMechanismEnabled(String mech) {
|
||||
Authenticator a = authenticators.get(mech.toUpperCase(Locale.ENGLISH));
|
||||
return a != null && a.enabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate to the server using the named authentication mechanism
|
||||
* and the supplied credentials.
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
synchronized String authenticate(String mech,
|
||||
String host, String authzid,
|
||||
String user, String passwd) {
|
||||
Authenticator a = authenticators.get(mech.toUpperCase(Locale.ENGLISH));
|
||||
if (a == null)
|
||||
return "No such authentication mechanism: " + mech;
|
||||
try {
|
||||
if (!a.authenticate(host, authzid, user, passwd))
|
||||
return "login failed";
|
||||
return null;
|
||||
} catch (IOException ex) {
|
||||
return ex.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the server we're connected to support the specified
|
||||
* authentication mechanism? Uses the information
|
||||
* returned by the server from the CAPA command.
|
||||
*
|
||||
* @param auth the authentication mechanism
|
||||
* @return true if the authentication mechanism is supported
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
synchronized boolean supportsAuthentication(String auth) {
|
||||
assert Thread.holdsLock(this);
|
||||
if (auth.equals("LOGIN"))
|
||||
return true;
|
||||
if (capabilities == null)
|
||||
return false;
|
||||
String a = capabilities.get("SASL");
|
||||
if (a == null)
|
||||
return false;
|
||||
StringTokenizer st = new StringTokenizer(a);
|
||||
while (st.hasMoreTokens()) {
|
||||
String tok = st.nextToken();
|
||||
if (tok.equalsIgnoreCase(auth))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Login to the server, using the USER and PASS commands.
|
||||
*/
|
||||
|
@ -317,6 +419,318 @@ class Protocol {
|
|||
return toHex(digest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base class for POP3 authentication mechanism implementations.
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
private abstract class Authenticator {
|
||||
protected Response resp; // the response, used by subclasses
|
||||
private final String mech; // the mechanism name, set in the constructor
|
||||
private final boolean enabled; // is this mechanism enabled by default?
|
||||
|
||||
Authenticator(String mech) {
|
||||
this(mech, true);
|
||||
}
|
||||
|
||||
Authenticator(String mech, boolean enabled) {
|
||||
this.mech = mech.toUpperCase(Locale.ENGLISH);
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
String getMechanism() {
|
||||
return mech;
|
||||
}
|
||||
|
||||
boolean enabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the authentication handshake by issuing the AUTH command.
|
||||
* Delegate to the doAuth method to do the mechanism-specific
|
||||
* part of the handshake.
|
||||
*/
|
||||
boolean authenticate(String host, String authzid,
|
||||
String user, String passwd) throws IOException {
|
||||
Throwable thrown = null;
|
||||
try {
|
||||
// use "initial response" capability, if supported
|
||||
String ir = getInitialResponse(host, authzid, user, passwd);
|
||||
if (noauthdebug && isTracing()) {
|
||||
logger.fine("AUTH " + mech + " command trace suppressed");
|
||||
suspendTracing();
|
||||
}
|
||||
if (ir != null)
|
||||
resp = simpleCommand("AUTH " + mech + " " +
|
||||
(ir.length() == 0 ? "=" : ir));
|
||||
else
|
||||
resp = simpleCommand("AUTH " + mech);
|
||||
|
||||
if (resp.cont)
|
||||
doAuth(host, authzid, user, passwd);
|
||||
} catch (IOException ex) { // should never happen, ignore
|
||||
logger.log(Level.FINE, "AUTH " + mech + " failed", ex);
|
||||
} catch (Throwable t) { // crypto can't be initialized?
|
||||
logger.log(Level.FINE, "AUTH " + mech + " failed", t);
|
||||
thrown = t;
|
||||
} finally {
|
||||
if (noauthdebug && isTracing())
|
||||
logger.fine("AUTH " + mech + " " +
|
||||
(resp.ok ? "succeeded" : "failed"));
|
||||
resumeTracing();
|
||||
if (!resp.ok) {
|
||||
close();
|
||||
if (thrown != null) {
|
||||
if (thrown instanceof Error)
|
||||
throw (Error)thrown;
|
||||
if (thrown instanceof Exception) {
|
||||
EOFException ex = new EOFException(
|
||||
resp.data != null ?
|
||||
resp.data : "authentication failed");
|
||||
ex.initCause(thrown);
|
||||
throw ex;
|
||||
}
|
||||
assert false : "unknown Throwable"; // can't happen
|
||||
}
|
||||
throw new EOFException(resp.data != null ?
|
||||
resp.data : "authentication failed");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the initial response to use in the AUTH command,
|
||||
* or null if not supported. Subclasses that support the
|
||||
* initial response capability will override this method.
|
||||
*/
|
||||
String getInitialResponse(String host, String authzid, String user,
|
||||
String passwd) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract void doAuth(String host, String authzid, String user,
|
||||
String passwd) throws IOException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the authentication handshake for LOGIN authentication.
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
private class LoginAuthenticator extends Authenticator {
|
||||
LoginAuthenticator() {
|
||||
super("LOGIN");
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean authenticate(String host, String authzid,
|
||||
String user, String passwd) throws IOException {
|
||||
String msg = null;
|
||||
if ((msg = login(user, passwd)) != null) {
|
||||
throw new EOFException(msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void doAuth(String host, String authzid, String user, String passwd)
|
||||
throws IOException {
|
||||
// should never get here
|
||||
throw new EOFException("LOGIN asked for more");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the authentication handshake for PLAIN authentication.
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
private class PlainAuthenticator extends Authenticator {
|
||||
PlainAuthenticator() {
|
||||
super("PLAIN");
|
||||
}
|
||||
|
||||
@Override
|
||||
String getInitialResponse(String host, String authzid, String user,
|
||||
String passwd) throws IOException {
|
||||
// return "authzid<NUL>user<NUL>passwd"
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
OutputStream b64os =
|
||||
new BASE64EncoderStream(bos, Integer.MAX_VALUE);
|
||||
if (authzid != null)
|
||||
b64os.write(authzid.getBytes(StandardCharsets.UTF_8));
|
||||
b64os.write(0);
|
||||
b64os.write(user.getBytes(StandardCharsets.UTF_8));
|
||||
b64os.write(0);
|
||||
b64os.write(passwd.getBytes(StandardCharsets.UTF_8));
|
||||
b64os.flush(); // complete the encoding
|
||||
|
||||
return ASCIIUtility.toString(bos.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
void doAuth(String host, String authzid, String user, String passwd)
|
||||
throws IOException {
|
||||
// should never get here
|
||||
throw new EOFException("PLAIN asked for more");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the authentication handshake for DIGEST-MD5 authentication.
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
/*
|
||||
* XXX - Need to move DigestMD5 class to com.sun.mail.auth
|
||||
*
|
||||
private class DigestMD5Authenticator extends Authenticator {
|
||||
private DigestMD5 md5support; // only create if needed
|
||||
|
||||
DigestMD5Authenticator() {
|
||||
super("DIGEST-MD5");
|
||||
}
|
||||
|
||||
private synchronized DigestMD5 getMD5() {
|
||||
if (md5support == null)
|
||||
md5support = new DigestMD5(logger);
|
||||
return md5support;
|
||||
}
|
||||
|
||||
@Override
|
||||
void doAuth(Protocol p, String host, String authzid,
|
||||
String user, String passwd)
|
||||
throws IOException {
|
||||
DigestMD5 md5 = getMD5();
|
||||
assert md5 != null;
|
||||
|
||||
byte[] b = md5.authClient(host, user, passwd, getSASLRealm(),
|
||||
resp.data);
|
||||
resp = p.simpleCommand(b);
|
||||
if (resp.cont) { // client authenticated by server
|
||||
if (!md5.authServer(resp.data)) {
|
||||
// server NOT authenticated by client !!!
|
||||
resp.ok = false;
|
||||
} else {
|
||||
// send null response
|
||||
resp = simpleCommand(new byte[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Perform the authentication handshake for NTLM authentication.
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
private class NtlmAuthenticator extends Authenticator {
|
||||
private Ntlm ntlm;
|
||||
|
||||
NtlmAuthenticator() {
|
||||
super("NTLM");
|
||||
}
|
||||
|
||||
@Override
|
||||
String getInitialResponse(String host, String authzid, String user,
|
||||
String passwd) throws IOException {
|
||||
ntlm = new Ntlm(props.getProperty(prefix + ".auth.ntlm.domain"),
|
||||
getLocalHost(), user, passwd, logger);
|
||||
|
||||
int flags = PropUtil.getIntProperty(
|
||||
props, prefix + ".auth.ntlm.flags", 0);
|
||||
boolean v2 = PropUtil.getBooleanProperty(
|
||||
props, prefix + ".auth.ntlm.v2", true);
|
||||
|
||||
String type1 = ntlm.generateType1Msg(flags, v2);
|
||||
return type1;
|
||||
}
|
||||
|
||||
@Override
|
||||
void doAuth(String host, String authzid, String user, String passwd)
|
||||
throws IOException {
|
||||
assert ntlm != null;
|
||||
String type3 = ntlm.generateType3Msg(
|
||||
resp.data.substring(4).trim());
|
||||
|
||||
resp = simpleCommand(type3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the authentication handshake for XOAUTH2 authentication.
|
||||
*
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
private class OAuth2Authenticator extends Authenticator {
|
||||
|
||||
OAuth2Authenticator() {
|
||||
super("XOAUTH2", false); // disabled by default
|
||||
}
|
||||
|
||||
@Override
|
||||
String getInitialResponse(String host, String authzid, String user,
|
||||
String passwd) throws IOException {
|
||||
String resp = "user=" + user + "\001auth=Bearer " +
|
||||
passwd + "\001\001";
|
||||
byte[] b = BASE64EncoderStream.encode(
|
||||
resp.getBytes(StandardCharsets.UTF_8));
|
||||
return ASCIIUtility.toString(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
void doAuth(String host, String authzid, String user, String passwd)
|
||||
throws IOException {
|
||||
// OAuth2 failure returns a JSON error code,
|
||||
// which looks like a "please continue" to the authenticate()
|
||||
// code, so we turn that into a clean failure here.
|
||||
String err = "";
|
||||
if (resp.data != null) {
|
||||
byte[] b = resp.data.getBytes(StandardCharsets.UTF_8);
|
||||
b = BASE64DecoderStream.decode(b);
|
||||
err = new String(b, StandardCharsets.UTF_8);
|
||||
}
|
||||
throw new EOFException("OAUTH2 authentication failed: " + err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the local host.
|
||||
*
|
||||
* @return the local host name
|
||||
* @since Jakarta Mail 1.6.5
|
||||
*/
|
||||
private synchronized String getLocalHost() {
|
||||
// get our hostname and cache it for future use
|
||||
try {
|
||||
if (localHostName == null || localHostName.length() == 0) {
|
||||
InetAddress localHost = InetAddress.getLocalHost();
|
||||
localHostName = localHost.getCanonicalHostName();
|
||||
// if we can't get our name, use local address literal
|
||||
if (localHostName == null)
|
||||
// XXX - not correct for IPv6
|
||||
localHostName = "[" + localHost.getHostAddress() + "]";
|
||||
}
|
||||
} catch (UnknownHostException uhex) {
|
||||
}
|
||||
|
||||
// last chance, try to get our address from our socket
|
||||
if (localHostName == null || localHostName.length() <= 0) {
|
||||
if (socket != null && socket.isBound()) {
|
||||
InetAddress localHost = socket.getLocalAddress();
|
||||
localHostName = localHost.getCanonicalHostName();
|
||||
// if we can't get our name, use local address literal
|
||||
if (localHostName == null)
|
||||
// XXX - not correct for IPv6
|
||||
localHostName = "[" + localHost.getHostAddress() + "]";
|
||||
}
|
||||
}
|
||||
return localHostName;
|
||||
}
|
||||
|
||||
private static char[] digits = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
|
||||
|
@ -758,7 +1172,10 @@ class Protocol {
|
|||
Response r = new Response();
|
||||
if (line.startsWith("+OK"))
|
||||
r.ok = true;
|
||||
else if (line.startsWith("-ERR"))
|
||||
else if (line.startsWith("+ ")) {
|
||||
r.ok = true;
|
||||
r.cont = true;
|
||||
} else if (line.startsWith("-ERR"))
|
||||
r.ok = false;
|
||||
else
|
||||
throw new IOException("Unexpected response: " + line);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<!--
|
||||
|
||||
Copyright (c) 1997, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program and the accompanying materials are made available under the
|
||||
terms of the Eclipse Public License v. 2.0, which is available at
|
||||
|
@ -297,6 +297,99 @@ Defaults to false.
|
|||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.mechanisms">mail.pop3.auth.mechanisms</A></TD>
|
||||
<TD>String</TD>
|
||||
<TD>
|
||||
If set, lists the authentication mechanisms to consider, and the order
|
||||
in which to consider them. Only mechanisms supported by the server and
|
||||
supported by the current implementation will be used.
|
||||
The default is <code>"LOGIN PLAIN DIGEST-MD5 NTLM"</code>, which includes all
|
||||
the authentication mechanisms supported by the current implementation
|
||||
except XOAUTH2.
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.login.disable">mail.pop3.auth.login.disable</A></TD>
|
||||
<TD>boolean</TD>
|
||||
<TD>If true, prevents use of the <code>USER</code> and <code>PASS</code>
|
||||
commands.
|
||||
Default is false.</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.plain.disable">mail.pop3.auth.plain.disable</A></TD>
|
||||
<TD>boolean</TD>
|
||||
<TD>If true, prevents use of the <code>AUTH PLAIN</code> command.
|
||||
Default is false.</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.digest-md5.disable">mail.pop3.auth.digest-md5.disable</A></TD>
|
||||
<TD>boolean</TD>
|
||||
<TD>If true, prevents use of the <code>AUTH DIGEST-MD5</code> command.
|
||||
Default is false.</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.ntlm.disable">mail.pop3.auth.ntlm.disable</A></TD>
|
||||
<TD>boolean</TD>
|
||||
<TD>If true, prevents use of the <code>AUTH NTLM</code> command.
|
||||
Default is false.</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.ntlm.domain">mail.pop3.auth.ntlm.domain</A></TD>
|
||||
<TD>String</TD>
|
||||
<TD>
|
||||
The NTLM authentication domain.
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.ntlm.flags">mail.pop3.auth.ntlm.flags</A></TD>
|
||||
<TD>int</TD>
|
||||
<TD>
|
||||
NTLM protocol-specific flags.
|
||||
See <A HREF="http://curl.haxx.se/rfc/ntlm.html#theNtlmFlags" TARGET="_top">
|
||||
http://curl.haxx.se/rfc/ntlm.html#theNtlmFlags</A> for details.
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<!--
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.ntlm.unicode">mail.pop3.auth.ntlm.unicode</A></TD>
|
||||
<TD>boolean</TD>
|
||||
<TD>
|
||||
Set this to "true" if the username or password may use
|
||||
Unicode UTF-8 encoded characters. Default is "true".
|
||||
Currently has no effect.
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.ntlm.lmcompat">mail.pop3.auth.ntlm.lmcompat</A></TD>
|
||||
<TD>int</TD>
|
||||
<TD>
|
||||
Sets the LM compatibility level, as described here:
|
||||
<A HREF="http://curl.haxx.se/rfc/ntlm.html#ntlmVersion2" TARGET="_top">
|
||||
http://curl.haxx.se/rfc/ntlm.html#ntlmVersion2</A>
|
||||
Defaults to "3". Currently not used.
|
||||
</TD>
|
||||
</TR>
|
||||
-->
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.auth.xoauth2.disable">mail.pop3.auth.xoauth2.disable</A></TD>
|
||||
<TD>boolean</TD>
|
||||
<TD>If true, prevents use of the <code>AUTHENTICATE XOAUTH2</code> command.
|
||||
Because the OAuth 2.0 protocol requires a special access token instead of
|
||||
a password, this mechanism is disabled by default. Enable it by explicitly
|
||||
setting this property to "false" or by setting the "mail.pop3.auth.mechanisms"
|
||||
property to "XOAUTH2".</TD>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><A ID="mail.pop3.socketFactory">mail.pop3.socketFactory</A></TD>
|
||||
<TD>SocketFactory</TD>
|
||||
|
|
|
@ -22,5 +22,5 @@ package javax.mail;
|
|||
* at build time.
|
||||
*/
|
||||
class Version {
|
||||
public static final String version = "1.6.5-SNAPSHOT";
|
||||
public static final String version = "1.6.5";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue