Exchange服务器不接受javax.mail API提供的用户名/密码

我有一个可爱的小Java客户端发送签名的电子邮件。 我们有一台Exchange服务器,需要用户名/密码validation才能发送邮件。

当我连接到Exchange服务器时,我收到此错误:

avax.mail.AuthenticationFailedException: failed to connect at javax.mail.Service.connect(Service.java:322) at javax.mail.Service.connect(Service.java:172) 

当我连接到其他服务器(Unix服务器)时,我没有问题。

以下是完整的调试跟踪。 我无法弄明白。

 DEBUG: JavaMail version 1.4.2 DEBUG: successfully loaded resource: /META-INF/javamail.default.providers DEBUG: Tables of loaded providers DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SM} DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc], } DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc] DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "SERVER", port 25, isSSL false 220 SERVER ESMTP (deca81216f2ecf4fd6fedb030e3dcfd0) DEBUG SMTP: connected to host "SERVER", port: 25 EHLO CLIENT 250-SERVER Hello CLIENT [192.1.1.1], pleased to meet you 250-STARTTLS 250-PIPELINING 250-SIZE 100000000 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN PLAIN 250-8BITMIME 250 HELP DEBUG SMTP: Found extension "STARTTLS", arg "" DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SIZE", arg "100000000" DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN" DEBUG SMTP: Found extension "AUTH=LOGIN", arg "PLAIN" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "HELP", arg "" STARTTLS 220 Ready to start TLS EHLO CLIENT 250-SERVER Hello CLIENT [192.1.1.1], pleased to meet you 250-PIPELINING 250-SIZE 100000000 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN PLAIN 250-8BITMIME 250 HELP DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SIZE", arg "100000000" DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN" DEBUG SMTP: Found extension "AUTH=LOGIN", arg "PLAIN" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "HELP", arg "" DEBUG SMTP: Attempt to authenticate DEBUG SMTP: check mechanisms: LOGIN PLAIN DIGEST-MD5 AUTH LOGIN 334 VXNlcn5hbWU6 RVJOXHNsK2FyZmlu 334 UGFzc3dvcmQ6 UVdFUnF3ZXIxMjM0IUAjJA== 535 Error: authentication failed DEBUG SMTP: useEhlo true, useAuth true DEBUG SMTP: trying to connect to host "SERVER", port 25, isSSL false 220 SERVER ESMTP (deca81216f2ecf4fd6fedb030e3dcfd0) DEBUG SMTP: connected to host "SERVER", port: 25 EHLO CLIENT 250-SERVER Hello CLIENT [192.1.1.1], pleased to meet you 250-STARTTLS 250-PIPELINING 250-SIZE 100000000 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN PLAIN 250-8BITMIME 250 HELP DEBUG SMTP: Found extension "STARTTLS", arg "" DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SIZE", arg "100000000" DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN" DEBUG SMTP: Found extension "AUTH=LOGIN", arg "PLAIN" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "HELP", arg "" STARTTLS 220 Ready to start TLS EHLO CLIENT 250-SERVER Hello CLIENT [192.1.1.1], pleased to meet you 250-PIPELINING 250-SIZE 100000000 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN PLAIN 250-8BITMIME 250 HELP DEBUG SMTP: Found extension "PIPELINING", arg "" DEBUG SMTP: Found extension "SIZE", arg "100000000" DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN" DEBUG SMTP: Found extension "AUTH=LOGIN", arg "PLAIN" DEBUG SMTP: Found extension "8BITMIME", arg "" DEBUG SMTP: Found extension "HELP", arg "" DEBUG SMTP: Attempt to authenticate DEBUG SMTP: check mechanisms: LOGIN PLAIN DIGEST-MD5 AUTH LOGIN 334 VXNlcm5hbWU6 RVJOXHNsZ2FyZmlu 334 UGFzc3dvcmQ6 UVdFUnF3ZXIxMjM0IUAjJA== 535 Error: authentication failed Error sending mail: failed to connect javax.mail.AuthenticationFailedException: failed to connect at javax.mail.Service.connect(Service.java:322) at javax.mail.Service.connect(Service.java:172) at SignMessage.sendSigned(SignMessage.java:248) at SignMessage.main(SignMessage.java:340 

显然,Java Mail API无法正确建立MS Exchange SSL连接。 它依赖于使用SSLSocketFactory ,但是,如果我没记错的话,MS Exchange需要一些混合的方法。

无论如何,我在我的一个项目中有这段代码:

 import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.*; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; public class ExchangeSSLSocketFactory extends SSLSocketFactory { private SSLSocketFactory sslSocketFactory; private SocketFactory socketFactory; public ExchangeSSLSocketFactory() { try { socketFactory = SocketFactory.getDefault(); SSLContext context = SSLContext.getInstance("TLS"); context.init(null, new TrustManager[] { new EmptyTrustManager() }, null); sslSocketFactory = (SSLSocketFactory)context.getSocketFactory(); } catch (Exception e) { throw new RuntimeException(e); } } private final class EmptyTrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] cert, String authType) throws CertificateException {} public void checkServerTrusted(X509Certificate[] cert, String authType) throws CertificateException {} public X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; } } public static SocketFactory getDefault() { return new ExchangeSSLSocketFactory(); } @Override public Socket createSocket(Socket socket, String s, int i, boolean flag) throws IOException { return sslSocketFactory.createSocket(socket, s, i, flag); } @Override public Socket createSocket(InetAddress inaddr, int i, InetAddress inaddr1, int j) throws IOException { return socketFactory.createSocket(inaddr, i, inaddr1, j); } @Override public Socket createSocket(InetAddress inaddr, int i) throws IOException { return socketFactory.createSocket(inaddr, i); } @Override public Socket createSocket(String s, int i, InetAddress inaddr, int j) throws IOException { return socketFactory.createSocket(s, i, inaddr, j); } @Override public Socket createSocket(String s, int i) throws IOException { return socketFactory.createSocket(s, i); } @Override public Socket createSocket() throws IOException { return socketFactory.createSocket(); } @Override public String[] getDefaultCipherSuites() { return sslSocketFactory.getSupportedCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return sslSocketFactory.getSupportedCipherSuites(); } } 

您可以通过设置以下属性来告诉Java Mail API使用此套接字工厂:

  • ssl.SocketFactory.provider
  • mail.smtp.socketFactory.class

ExchangeSSLSocketFactory完整类名

从您的调试输出,您似乎已经拥有:

  • mail.smtp.starttls.enable设置为true

有了这一切,问题就应该解决了。

我有同样的问题。 现在它正常工作。 我禁用了防病毒软件(McAfee)并更正了用户名(我不必要地提供了域名,而不是必需的)。

尝试显式禁用普通登录:

 properties.setProperty("mail." + protocol + ".auth.plain.disable", "true"); 

要么

 props.put("mail.smtp.auth.plain.disable", true); 

显然,在某些版本的交换中存在一个错误,它会宣传对普通身份validation的支持,而事实上总是会失败。