2011年9月8日 星期四

使用 Java 寄信:JavaMail 範例 (2012-10-12 修正)

自己寫的寄信程式的範例~
測試過公司、以前學校的郵件伺服器(未加密),以及 Gmail、Yeah、QQ 的 SSL 連線,還有 Gmail 的 TLS 連線。
其中 TLS 連線可以參考 [1] 的討論,原本我以為 TLS 是加密連線
不過似乎 TLS 其實是明文,因此需要加密內文的 SSL 在設定屬性時要用 "smtps",但 TLS 要用 "smtp"。

public class MailSend {
  private boolean authFlag = true;
  private int typeOfConnection = 0; // 0: none, 1: TLS, 2: SSL
  
  public boolean sendMail(String sender, String receiver, String ccList , String smtpHost, int port,
      String username, String passwd, String Subject) {
    InternetAddress[] address = null;
    // mail body
    StringBuilder messageText = new StringBuilder();
    messageText.append("<html><body>");
    messageText.append("content");
    messageText.append("</body></html>");
    //System.out.println(messageText.toString());
    
    boolean sessionDebug = false;
    try {
      // encoding
      System.setProperty("mail.mime.charset", "utf8");
      
      // properties
      java.util.Properties props = null;
      switch (typeOfConnection) {
      case 1: // TLS
        props = getPropertyInTls(smtpHost, port);
        break;
      case 2: // SSL
        props = getPropertyInSsl(smtpHost, port);
        break;
      default:
        props = getPropertyInNormalConnection(smtpHost, port);
        break;
      }
      
      // construct a mail session
      javax.mail.Session mailSession = javax.mail.Session.getDefaultInstance(props, null);
      mailSession.setDebug(sessionDebug);
      Message msg = new MimeMessage(mailSession);
      // mail sender
      msg.setFrom(new InternetAddress(sender));
      // mail recievers
      address = InternetAddress.parse(receiver, false);
      msg.setRecipients(Message.RecipientType.TO, address);
      // mail cc
      msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccList));
      // mail's subject
      msg.setSubject(Subject);
      // mail's sending time
      msg.setSentDate(new Date());
      MimeBodyPart mbp = new MimeBodyPart();
      // mail's charset
      mbp.setContent(messageText.toString(), "text/html; charset=utf8");
      Multipart mp = new MimeMultipart();
      mp.addBodyPart(mbp);
      msg.setContent(mp);
      
      if (this.authFlag) {
        Transport transport = null;
        if(this.authFlag == 0) transport = mailSession.getTransport("smtp");
        else transport = mailSession.getTransport("smtps");
        transport.connect(smtpHost, username, passwd);
        transport.sendMessage(msg, msg.getAllRecipients());
        transport.close();
      } else {
        Transport.send(msg);
      }
      return true;
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    }
  }
  
  public boolean setTypeOfConnection (String type) {
    type = type.toLowerCase();
    if(type.compareTo("tls") == 0) {
      this.typeOfConnection = 1;
      return true;
    }
    else if(type.compareTo("ssl") == 0) {
      this.typeOfConnection = 2;
      return true;
    }
    else if(type.compareTo("none") == 0) {
      this.typeOfConnection = 0;
      return true;
    }
    return false;
  }
  
  private java.util.Properties getPropertyInNormalConnection (String smtpHost, int port) {
    java.util.Properties props = new java.util.Properties();
    
    props.put("mail.host", smtpHost);
    props.put("mail.transport.protocol", "smtp");
    props.put("mail.smtp.port", port);
    props.put("mail.smtp.auth", String.valueOf(this.authFlag));
    
    return props;
  }
  
  private java.util.Properties getPropertyInTls (String smtpHost, int port) {
    java.util.Properties props = new java.util.Properties();
    
    props.put("mail.host", smtpHost);
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable","true");
    props.put("mail.smtp.port", port);
    
    return props;
  }
  
  private java.util.Properties getPropertyInSsl (String smtpHost, int port) {
    java.util.Properties props = new java.util.Properties();
    
    props.put("mail.host", smtpHost);
    props.put("mail.smtps.auth", "true");
    props.put("mail.smtps.port", port);
    props.put("mail.smtps.socketFactory.port", port);
    props.put("mail.smtps.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    props.put("mail.smtps.socketFactory.fallback", "true");
    props.put("mail.smtps.ssl.enable", "true");
    
    return props;
  }
}
Properties 參數可以參考:com.sun.mail.smtp
補充:
要用 SSL/TLS 加密時可能需要加上
props.setProperty("mail.smtp.ssl.trust", "*");
這段是 certification 一律通過不檢查(信任範圍設為 *),需要檢查憑證時就依照自己的環境狀況去設定。

參考資料:
1、Using JavaMail with TLS

沒有留言: