使用JavaMail API的SSLException

问题描述:

我使用Java Mail API开发应用程序来发送邮件。如果我使用由yahoo或gmail托管的邮件服务器,我可以成功发送邮件。但是,当我尝试使用自己的邮件服务器时,我无法发送邮件,导致失败的可能原因是什么?当我在我的设备中执行我的应用程序时,它显示“电子邮件未发送”,因此不会发生异常。请问如何更改我的程序,以便我可以成功地将我的应用程序连接到我的smtp服务器,或者如何获取更多信息以显示,因此我可以理解连接失败的原因。使用JavaMail API的SSLException

这里是我的程序: Sender.java

public class Sender extends Activity { 

    Button Send; 
    TextView text; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_sender); 

     Send = (Button) findViewById(R.id.mail); 
     text = (TextView) findViewById(R.id.textView1); 

     StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() 
     .permitAll().build(); 
     StrictMode.setThreadPolicy(policy); 

     Send.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // TODO Auto-generated method stub 
       new SendMail().execute(); 
      } 
     }); 

    } 

    private class SendMail extends AsyncTask<String, Void, Integer> 
    { 
     ProgressDialog pd = null; 
     String error = null; 
     Integer result; 

     @Override 
     protected void onPreExecute() { 
      // TODO Auto-generated method stub 
      super.onPreExecute(); 
      pd = new ProgressDialog(Sender.this); 
      pd.setTitle("Sending Mail"); 
      pd.setMessage("Please wait..."); 
      pd.setCancelable(false); 
      pd.show(); 
     } 

     @Override 
     protected Integer doInBackground(String... params) { 
      // TODO Auto-generated method stub 

      MailSender sender = new MailSender("[email protected]", "password"); 

      sender.setTo(new String[]{"[email protected]", "[email protected]"}); 
      sender.setFrom("[email protected]"); 
      sender.setSubject("Test mail"); 
      sender.setBody("This is the mail body"); 
      try { 
       if(sender.send()) { 
        System.out.println("Message sent"); 
        return 1; 
       } else { 
        return 2; 
       } 
      } catch (Exception e) {  
      error = e.getMessage(); 
      Log.e("SendMail", e.getMessage(), e);  
      } 
      return 3; 
     } 

     protected void onPostExecute(Integer result) { 
      pd.dismiss(); 
      if(error!=null) { 
       text.setText(error); 
      } 
      if(result==1) { 
       Toast.makeText(Sender.this, 
        "Email was sent successfully.", Toast.LENGTH_LONG) 
        .show(); 
      } else if(result==2) { 
       Toast.makeText(Sender.this, 
        "Email was not sent.", Toast.LENGTH_LONG).show(); 
      } else if(result==3) { 
       Toast.makeText(Sender.this, 
        "There was a problem sending the email.", 
        Toast.LENGTH_LONG).show(); 
      } 
     } 
    } 
} 

MailSender.java在错误日志

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 = "web.mysmtp.com"; 
     port = "25"; 
     sport = "25"; 

     user = ""; 
     password = ""; 
     from = ""; 
     subject = ""; 
     body = ""; 

     debuggable = false; 
     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.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", "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; 
    } 
} 

错误消息:

08-15 11:21:37.284: W/System.err(2553):  javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5c075548: Failure in SSL library, usually a protocol error 
08-15 11:21:37.291: W/System.err(2553): Caused by: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5c075548: Failure in SSL library, usually a protocol error 
08-15 11:21:37.299: W/System.err(2553): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x5c075548: Failure in SSL library, usually a protocol error 

您正在连接到端口25并使用SSL。端口25是非SSL(纯文本)端口。假设您的服务器已设置为SSL,请使用不需要您指定端口号的连接方法,并让JavaMail使用默认端口。

+0

所以我需要做的是删除端口的规格,所以要隐藏以下三行? props.put(“mail.smtp.port”,port); props.put(“mail.smtp.socketFactory.port”,sport); props.put(“mail.smtp.socketFactory.class”,“javax.net.SocketFactory”); – Conrad 2012-08-15 04:13:36

+1

是的,您根本不需要套接字工厂属性,并且由于您调用此方法而忽略端口属性:transport.connect(host,25,user,password);将其替换为transport.connect(主机,用户,密码); – 2012-08-15 17:46:27

+0

谢谢。它解决了我的问题。 – Autobots 2013-05-02 12:06:16

您的SMTP服务器的SSL配置将是我要检查的第一件事。如果你的课程使用外部服务,那么它就是你的服务器的安全配置。

+0

所以你的意思是我应该将javax.net.ssl.SSLSocketFactory更改为javax.net.SocketFactory这一行“props.put(”mail.smtp.socketFactory.class“,”javax.net.ssl.SSLSocketFactory“) ;“?我还需要做什么更改,因为在我更改之后,我仍然无法发送邮件。 – Conrad 2012-08-15 04:05:44

由于您未在服务器端创建签名证书,您可能会遇到此错误。如果您确实设置了SSL验证,那么您要么没有正确执行此操作,要么您连接到证书尚未添加到信任库的服务器。

这篇文章(How Can I Access an SSL Connection Through Android?)有一个代码示例的答案,说明如何初始化密钥库和信任库。

Java邮件API导致很多问题,here是我的各种pop3/smtp连接的工作示例,我最近用几个不同的邮件服务器进行了测试。