2011-03-14 82 views
1

我想在android上获取我的Exchange电子邮件,并且为此我正在使用javamail api for android ...它在使用imap的gmail和yahoo上效果很好。 的问题是,我的Exchange服务器自签名证书因此Android不喜欢这个太多,我得到03-14 12:46:13.698: WARN/System.err(281): javax.mail.MessagingException: Not trusted server certificate;android javamail api imap over ssl

我看到这个例子:Sending Email in Android using JavaMail API without using the default/built-in app其中有人使通过SSL进行发送例子。我想我可以使用该JSSEProvider接受我的自签名证书,但我不知道如何使用它。

请帮帮我!

回答

7

我一直有同样的问题,并设法通过配置信任管理器来解决它,详见http://java.sun.com/products/javamail/javamail-1.4.2/SSLNOTES142.txt

我所做的就是创建自己的TrustManager:

package com.myapp; 
import javax.net.ssl.X509TrustManager; 
import java.security.cert.X509Certificate; 

/** 
* DummyTrustManager - NOT SECURE 
*/ 
public class DummyTrustManager implements X509TrustManager { 

    public void checkClientTrusted(X509Certificate[] cert, String authType) { 
    // everything is trusted 
    } 

    public void checkServerTrusted(X509Certificate[] cert, String authType) { 
    // everything is trusted 
    } 

    public X509Certificate[] getAcceptedIssuers() { 
    return new X509Certificate[0]; 
    } 
} 

,并使用这在我自己的SSLSocketFactory:,你需要指定

package com.myapp; 

import java.io.IOException; 
import java.net.InetAddress; 
import java.net.Socket; 

import javax.net.SocketFactory; 
import javax.net.ssl.*; 


/** 
* DummySSLSocketFactory 
*/ 
public class DummySSLSocketFactory extends SSLSocketFactory { 
    private SSLSocketFactory factory; 

    public DummySSLSocketFactory() { 
    try { 
     SSLContext sslcontext = SSLContext.getInstance("TLS"); 
     sslcontext.init(null, 
       new TrustManager[] { new DummyTrustManager()}, 
       null); 
     factory = (SSLSocketFactory)sslcontext.getSocketFactory(); 
    } catch(Exception ex) { 
     // ignore 
    } 
    } 

    public static SocketFactory getDefault() { 
    return new DummySSLSocketFactory(); 
    } 

    public Socket createSocket() throws IOException { 
    return factory.createSocket(); 
    } 

     public Socket createSocket(Socket socket, String s, int i, boolean flag) 
       throws IOException { 
    return factory.createSocket(socket, s, i, flag); 
    } 

    public Socket createSocket(InetAddress inaddr, int i, 
       InetAddress inaddr1, int j) throws IOException { 
    return factory.createSocket(inaddr, i, inaddr1, j); 
    } 

    public Socket createSocket(InetAddress inaddr, int i) 
       throws IOException { 
    return factory.createSocket(inaddr, i); 
    } 

    public Socket createSocket(String s, int i, InetAddress inaddr, int j) 
       throws IOException { 
    return factory.createSocket(s, i, inaddr, j); 
    } 

    public Socket createSocket(String s, int i) throws IOException { 
    return factory.createSocket(s, i); 
    } 

    public String[] getDefaultCipherSuites() { 
    return factory.getDefaultCipherSuites(); 
    } 

    public String[] getSupportedCipherSuites() { 
    return factory.getSupportedCipherSuites(); 
    } 
} 

为了得到这个JavaMail的,Android的工作在获得会话实例之前新的SSLSocketFactory:

Properties props = new Properties(); 
    props.setProperty("mail.imaps.socketFactory.class", "com.myapp.DummySSLSocketFactory"); 
    session = Session.getDefaultInstance(props); 

我们现在定义的TrustManager被使用而不是默认的,并且所有的证书都会被接受。

很明显,有一些安全问题会盲目地接受所有证书,我建议在TrustManager中进行一些检查,否则您可能会面临各种安全问题(如中间人攻击(man-in-the-middle attacks) )。另外,我只会在你真正需要的地方使用它:例如你说GMail和Ymail正在工作,所以在连接到这些机制时我不会使用这种机制。

我会在异常处理程序中捕获“证书不可信”异常,并提示用户在实际覆盖之前接受不受信任的证书(必须警告只对完全信任的服务器执行此操作)的TrustManager。

+1

它正在工作perfeclty!非常感谢! – Merve 2012-05-28 08:49:07

+1

千万不要这样做。它信任每个证书,您可以完全禁用SSL。攻击者在这里有一个非常容易的工作。绝对有可能只向信任存储添加一组定义的可信证书,并且可以询问用户是否要接受证书。 正如你对此提醒的那样,我已经收回了我的失望。 – 2014-03-14 17:23:29

1

我遇到了同样的问题,并以我认为更简洁更简洁的方式解决了这个问题。我用马克阿利森链接到同一个参考,但并不是覆盖的SSLSocketFactory和实现自己的TrustManager,我增加了以下内容:

MailSSLSocketFactory sf = new MailSSLSocketFactory(); 
sf.setTrustAllHosts(true); 
// or 
// sf.setTrustedHosts(new String[] { "my-server" }); 
props.put("mail.smtp.ssl.enable", "true"); 
// also use following for additional safety 
//props.put("mail.smtp.ssl.checkserveridentity", "true"); 
props.put("mail.smtp.ssl.socketFactory", sf); 

欲了解更多信息,请查看链接的“套接字工厂”一节中:http://java.sun.com/products/javamail/javamail-1.4.2/SSLNOTES142.txt

值得注意的是,我这样做的时候,我不得不使用“IMAP”店,而不是“IMAPS”:

Store store = session.getStore("imap"); 

这里是我的完整代码,它访问时,对我来说效果很好Exchange 2010服务器:

import javax.mail.*; 
import java.util.*; 
import com.sun.mail.util.MailSSLSocketFactory; 
. 
. 
. 

// Set the socket factory to trust all hosts 
MailSSLSocketFactory sf = new MailSSLSocketFactory(); 
sf.setTrustAllHosts(true); 

// create the properties for the Session 
Properties props = new Properties(); 
props.put("mail.imap.ssl.enable", "true"); 
props.put("mail.imap.ssl.socketFactory", sf); 

// Get session 
Session session = Session.getInstance(props, null); 
//session.setDebug(true); 

// Get the store 
Store store = session.getStore("imap"); 
System.out.println("Establishing connection with IMAP server."); 

store.connect("host", 993, "username", "password"); 
System.out.println("Connection established with IMAP server."); 

// List all folders (including subfolders) 
Folder[] allFolders = store.getDefaultFolder().list("*"); 

store.close();