我想让我的 android 应用程序使用我的邮件服务器发送邮件,我的服务器使用端口 25,所以我的应用程序需要在没有 ssl 的情况下发送邮件。我已经尝试过这里大多数类似问题中提到的方法,但都没有奏效,因此我提出了一个新问题。以下是我读过的一些链接:
使用带有 smtp 但没有 SSL 的 JavaMail API 在 android 中
发送电子邮件 使用 TSL
Java Mail 通过 SMTP 发送电子邮件:在没有 SSL Javamail 的端口 25 上发送电子邮件时出现
SSLHandshakeException:javax.net.ssl.SSLHandshakeException:sun。
使用带有 TLS 的 JavaMail 从 VPS 发送邮件时出现 security.validator.ValidatorException
http://java.sun.com/products/javamail/javamail-1.4.2/SSLNOTES142.txt
下面是我的邮件发送类:
public class MailSender extends Authenticator {
private String user;
private String password;
private String [] to;
private String from;
private String port;
private String sport;
private String host;
private String subject;
private String body;
private boolean auth;
private boolean debuggable;
private Multipart multi;
public MailSender(){
host = "me.myserver.com";
port = "25";
sport = "25";
user = "";
password = "";
from = "";
subject = "";
body = "";
debuggable = true;
auth = true;
multi = new MimeMultipart();
// There is something wrong with MailCap, javamail can not find a handler for the multipart/mixed part, so this bit needs to be added.
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);
}
public MailSender(String user, String password){
this();
this.user = user;
this.password = password;
}
public boolean send() throws Exception {
Properties props = setProperties();
try{
Session session = Session.getInstance(props, this);
session.setDebug(true);
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
InternetAddress[] addressTo = new InternetAddress[to.length];
for(int i=0; i<to.length; i++){
addressTo[i] = new InternetAddress(to[i]);
}
msg.setRecipients(MimeMessage.RecipientType.TO, addressTo);
msg.setSubject(subject);
msg.setSentDate(new Date());
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(body);
multi.addBodyPart(messageBodyPart);
msg.setContent(multi);
Transport transport = session.getTransport("smtps");
transport.connect(host, 25, user, password);
transport.sendMessage(msg, msg.getAllRecipients());
transport.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public void addAttachment(String filename) throws Exception {
BodyPart messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multi.addBodyPart(messageBodyPart);
}
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
private Properties setProperties() {
Properties props = new Properties();
props.put("mail.smtp.host", host);
if(debuggable) {
props.put("mail.debug", "true");
}
if(auth) {
props.put("mail.smtp.auth", "true");
}
//props.put("mail.smtp.ssl.enable", "false");
//props.put("mail.smtp.ssl.trust", "*");
props.put("mail.smtp.port", port);
props.put("mail.smtp.socketFactory.port", sport);
//props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
//props.put("mail.smtp.socketFactory.fallback", "true");
props.setProperty("mail.smtp.ssl.enable", "true");
props.setProperty("mail.smtp.ssl.socketFactory.class",
"DummySSLSocketFactory");
props.setProperty("mail.smtp.ssl.socketFactory.fallback", "false");
//props.put("mail.smtp.starttls.enable", "false");
return props;
}
public void setTo(String[] toAddress) {
this.to = toAddress;
}
public void setFrom(String fromAddress) {
this.from = fromAddress;
}
public void setSubject(String subject) {
this.subject = subject;
}
public void setBody(String body) {
this.body = body;
}
}
DummySSLSocketFactory.java:
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();
}
}
DummyTrustManager.java:
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];
}
}
日志中的错误消息:
08-15 16:08:59.338: W/System.err(16163): javax.mail.MessagingException: Could not connect to SMTP host: me.myserver.com, port: 25;
08-15 16:08:59.338: W/System.err(16163): nested exception is:
08-15 16:08:59.338: W/System.err(16163): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5bfaf480: Failure in SSL library, usually a protocol error
08-15 16:08:59.338: W/System.err(16163): error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:766 0x580b87de:0x00000000)
08-15 16:08:59.338: W/System.err(16163): at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1391)
08-15 16:08:59.338: W/System.err(16163): at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:412)
08-15 16:08:59.346: W/System.err(16163): at javax.mail.Service.connect(Service.java:288)
08-15 16:08:59.346: W/System.err(16163): at Android.sender.MailSender.send(MailSender.java:100)
08-15 16:08:59.346: W/System.err(16163): at Android.sender.Sender$SendMail.doInBackground(Sender.java:73)
08-15 16:08:59.346: W/System.err(16163): at Android.sender.Sender$SendMail.doInBackground(Sender.java:1)
08-15 16:08:59.354: W/System.err(16163): at android.os.AsyncTask$2.call(AsyncTask.java:287)
08-15 16:08:59.354: W/System.err(16163): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
08-15 16:08:59.354: W/System.err(16163): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
08-15 16:08:59.354: W/System.err(16163): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
08-15 16:08:59.354: W/System.err(16163): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
08-15 16:08:59.354: W/System.err(16163): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
08-15 16:08:59.354: W/System.err(16163): at java.lang.Thread.run(Thread.java:856)
08-15 16:08:59.354: W/System.err(16163): Caused by: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5bfaf480: Failure in SSL library, usually a protocol error
08-15 16:08:59.354: W/System.err(16163): error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:766 0x580b87de:0x00000000)
08-15 16:08:59.362: W/System.err(16163): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:436)
08-15 16:08:59.362: W/System.err(16163): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.<init>(OpenSSLSocketImpl.java:647)
08-15 16:08:59.362: W/System.err(16163): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:618)
08-15 16:08:59.362: W/System.err(16163): at com.sun.mail.smtp.SMTPTransport.initStreams(SMTPTransport.java:1449)
08-15 16:08:59.362: W/System.err(16163): at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1366)
08-15 16:08:59.362: W/System.err(16163): ... 12 more
08-15 16:08:59.362: W/System.err(16163): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5bfaf480: Failure in SSL library, usually a protocol error
08-15 16:08:59.362: W/System.err(16163): error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:766 0x580b87de:0x00000000)
08-15 16:08:59.362: W/System.err(16163): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
08-15 16:08:59.362: W/System.err(16163): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:395)
08-15 16:08:59.362: W/System.err(16163): ... 16 more
这里我改了“Transport transport = session.getTransport("smtps");” 到“Transport transport = session.getTransport("smtps");”,并且错误日志中的消息已更改。
08-15 17:18:13.986: W/System.err(21399): javax.mail.MessagingException: Could not convert socket to TLS;
08-15 17:18:13.986: W/System.err(21399): nested exception is:
08-15 17:18:13.986: W/System.err(21399): javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
08-15 17:18:13.986: W/System.err(21399): at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1339)
08-15 17:18:13.986: W/System.err(21399): at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:420)
08-15 17:18:13.986: W/System.err(21399): at javax.mail.Service.connect(Service.java:288)
08-15 17:18:13.986: W/System.err(21399): at Android.sender.MailSender.send(MailSender.java:100)
08-15 17:18:13.986: W/System.err(21399): at Android.sender.Sender$SendMail.doInBackground(Sender.java:73)
08-15 17:18:13.986: W/System.err(21399): at Android.sender.Sender$SendMail.doInBackground(Sender.java:1)
08-15 17:18:13.986: W/System.err(21399): at android.os.AsyncTask$2.call(AsyncTask.java:287)
08-15 17:18:13.986: W/System.err(21399): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
08-15 17:18:13.986: W/System.err(21399): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
08-15 17:18:13.986: W/System.err(21399): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
08-15 17:18:13.986: W/System.err(21399): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
08-15 17:18:13.986: W/System.err(21399): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
08-15 17:18:13.986: W/System.err(21399): at java.lang.Thread.run(Thread.java:856)
08-15 17:18:13.986: W/System.err(21399): Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
08-15 17:18:13.986: W/System.err(21399): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:398)
08-15 17:18:13.986: W/System.err(21399): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.<init>(OpenSSLSocketImpl.java:647)
08-15 17:18:13.986: W/System.err(21399): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:618)
08-15 17:18:13.986: W/System.err(21399): at com.sun.mail.smtp.SMTPTransport.initStreams(SMTPTransport.java:1449)
08-15 17:18:13.986: W/System.err(21399): at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1336)
08-15 17:18:13.986: W/System.err(21399): ... 12 more
08-15 17:18:13.986: W/System.err(21399): Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
08-15 17:18:13.986: W/System.err(21399): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:192)
08-15 17:18:13.994: W/System.err(21399): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:163)
08-15 17:18:13.994: W/System.err(21399): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:597)
08-15 17:18:13.994: W/System.err(21399): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
08-15 17:18:13.994: W/System.err(21399): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:395)
08-15 17:18:13.994: W/System.err(21399): ... 16 more
08-15 17:18:13.994: W/System.err(21399): Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
08-15 17:18:13.994: W/System.err(21399): ... 21 more