Java發送郵件,所遇到的常見需求


明天要做關於發送郵件的接口,雖然我之前已用Java Mail做過許多關於郵件的發送。但同事說有點難點,雖我還不知難點在哪,還是要復習下。凡事預則立,不預則廢嘛~

所需的包:

Java Mail : 目前,可從如下地址下載:JavaMail API

Activation : 目前,可從如下地址下載:JavaBeans Activation Framework (JAF)

 

參考的好文章:

JavaMail發送和接收郵件

JavaMail:用Authenticator的子類進行身份驗證及策略模式

Java發送郵件(帶附件)

Java 基於JavaMail實現向QQ郵箱發送郵件

 

代碼托管於:https://github.com/nicchagil/multi-project的MailSender文件夾。

 

基於SMTP發送一個簡單的郵件

首先,需要一個認證器:

package No001_基於SMTP的文本郵件;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

public class SimpleAuthenticator extends Authenticator {
    
    private String username;
    private String password;
    
    public SimpleAuthenticator(String username, String password) {
        super();
        this.username = username;
        this.password = password;
    }

    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(username, password);
    }

}
View Code

 

 

然后,書寫簡單的發送郵件程序:

package No001_基於SMTP的文本郵件;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SMTPSimpleMail {

    public static void main(String[] args) throws AddressException, MessagingException {
        /* 必需的信息 */
        String SMTP_MAIL_HOST = "smtp.163.com"; // 此郵件服務器地址,自行去所屬郵件查詢
        String EMAIL_USERNAME = "example_email@163.com";
        String EMAIL_PASSWORD = "mypassword";
        String TO_EMAIL_ADDRESS = "example_email_too@qq.com";
        
        /* 服務器信息 */
        Properties props = new Properties();
        props.put("mail.smtp.host", SMTP_MAIL_HOST);
        props.put("mail.smtp.auth", "true");

        /* 創建Session */
        Session session = Session.getDefaultInstance(props, new SimpleAuthenticator(EMAIL_USERNAME, EMAIL_PASSWORD));

        /* 郵件信息 */
        MimeMessage message = new MimeMessage(session);
        message.setFrom(new InternetAddress(EMAIL_USERNAME));
        message.addRecipient(Message.RecipientType.TO, new InternetAddress(TO_EMAIL_ADDRESS));
        message.setSubject("how to use java mail to send email.(Title)(001)");
        message.setText("how to use java mail to send email.(Content)");

        // 發送
        Transport.send(message);
        System.out.println("不是特別倒霉,你可以去查收郵件了。");
    }

}
View Code

 

各種收件人、抄送人、秘密抄送人,怎么辦

認證器沿用,略。

 

其實就是設置、追加多個收件人、抄送人、秘密抄送人:

package No002_各種發件人收件人抄送人怎么辦;

import java.io.UnsupportedEncodingException;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SendMailWithMultiPeople {

    public static void main(String[] args) throws AddressException, MessagingException, UnsupportedEncodingException {
        /* 必需的信息 */
        String SMTP_MAIL_HOST = "smtp.163.com"; // 此郵件服務器地址,自行去所屬郵件查詢
        String EMAIL_USERNAME = "example@163.com";
        String EMAIL_PASSWORD = "mypassword";
        String TO_EMAIL_ADDRESS_1 = "example@163.com";
        String CC_EMAIL_ADDRESS_1 = "example@163.com";
        String BCC_EMAIL_ADDRESS_1 = "example@163.com";
        
        /* 服務器信息 */
        Properties props = new Properties();
        props.put("mail.smtp.host", SMTP_MAIL_HOST);
        props.put("mail.smtp.auth", "true");

        /* 創建Session */
        Session session = Session.getDefaultInstance(props, new SimpleAuthenticator(EMAIL_USERNAME, EMAIL_PASSWORD));

        /* 發件人 */
        Address[] senderArray = new Address[1];
        senderArray[0] = new InternetAddress("example@163.com", "Nick Huang");
        
        /* 郵件信息 */
        MimeMessage message = new MimeMessage(session);
        message.addFrom(senderArray);
        message.addRecipient(Message.RecipientType.TO, new InternetAddress(TO_EMAIL_ADDRESS_1));
        message.addRecipient(Message.RecipientType.TO, new InternetAddress(CC_EMAIL_ADDRESS_1));
        message.addRecipient(Message.RecipientType.CC, new InternetAddress(CC_EMAIL_ADDRESS_1));
        message.addRecipient(Message.RecipientType.CC, new InternetAddress(TO_EMAIL_ADDRESS_1));
        message.addRecipient(Message.RecipientType.BCC, new InternetAddress(BCC_EMAIL_ADDRESS_1));
        message.setSubject("我是一封學習Java Mail的郵件");
        message.setText("我是一封學習Java Mail的郵件的內容,請郵件過濾器高抬貴手。");

        // 發送
        Transport.send(message);
        System.out.println("不是特別倒霉,你可以去查收郵件了。");
    }

}
View Code

 

 

發送附件怎么辦

認證器沿用,略。

 

發送附件demo:

package No003_發送附件怎么辦;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class SendMailWithAttachment {

    public static void main(String[] args) throws AddressException, MessagingException, UnsupportedEncodingException {
        /* 必需的信息 */
        String SMTP_MAIL_HOST = "smtp.163.com"; // 此郵件服務器地址,自行去所屬郵件查詢
        String EMAIL_USERNAME = "example@163.com";
        String EMAIL_PASSWORD = "password";
        String TO_EMAIL_ADDRESS_1 = "example@163.com";
        
        /* 服務器信息 */
        Properties props = new Properties();
        props.put("mail.smtp.host", SMTP_MAIL_HOST);
        props.put("mail.smtp.auth", "true");

        /* 創建Session */
        Session session = Session.getDefaultInstance(props, new SimpleAuthenticator(EMAIL_USERNAME, EMAIL_PASSWORD));

        /* 發件人 */
        Address[] senderArray = new Address[1];
        senderArray[0] = new InternetAddress(EMAIL_USERNAME);
        
        /* 郵件信息 */
        MimeMessage message = new MimeMessage(session);
        message.addFrom(senderArray);
        message.addRecipient(Message.RecipientType.TO, new InternetAddress(TO_EMAIL_ADDRESS_1));
        message.setSubject("我是一封學習Java Mail的郵件");
        
        BodyPart bodyPart = new MimeBodyPart();
        bodyPart.setText("這是一封學習Java Mail的郵件的內容,請郵件過濾器高抬貴手。");
        
        /* 附件 */
        BodyPart attachmentPart1 = new MimeBodyPart();
        DataSource source = new FileDataSource(new File("D:/文件壹.txt"));
        attachmentPart1.setDataHandler(new DataHandler(source));
        attachmentPart1.setFileName("=?GBK?B?" + new sun.misc.BASE64Encoder().encode("文件壹.txt".getBytes()) + "?=");
        
        BodyPart attachmentPart2 = new MimeBodyPart();
        source = new FileDataSource(new File("D:/文件貳.txt"));
        attachmentPart2.setDataHandler(new DataHandler(source));
        attachmentPart2.setFileName("=?GBK?B?" + new sun.misc.BASE64Encoder().encode("文件貳.txt".getBytes()) + "?=");
        
        Multipart multipart = new MimeMultipart();
        multipart.addBodyPart(bodyPart);
        multipart.addBodyPart(attachmentPart1);
        multipart.addBodyPart(attachmentPart2);
        message.setContent(multipart);

        // 發送
        Transport.send(message);
        System.out.println("不是特別倒霉,你可以去查收郵件了。");
    }

}
View Code

 

 

還有,發送HTML郵件

認證器沿用,略。

 

其實就是告訴收件客戶端用HTML解析渲染:

package No004_發送HTML郵件;

import java.io.UnsupportedEncodingException;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class HowToSendHTMLMail {

    public static void main(String[] args) throws AddressException, MessagingException, UnsupportedEncodingException {
        /* 必需的信息 */
        String SMTP_MAIL_HOST = "smtp.163.com"; // 此郵件服務器地址,自行去所屬郵件查詢
        String EMAIL_USERNAME = "example@163.com";
        String EMAIL_PASSWORD = "password";
        String TO_EMAIL_ADDRESS_1 = "example@163.com";
        
        /* 服務器信息 */
        Properties props = new Properties();
        props.put("mail.smtp.host", SMTP_MAIL_HOST);
        props.put("mail.smtp.auth", "true");

        /* 創建Session */
        Session session = Session.getDefaultInstance(props, new SimpleAuthenticator(EMAIL_USERNAME, EMAIL_PASSWORD));

        /* 發件人 */
        Address[] senderArray = new Address[1];
        senderArray[0] = new InternetAddress(EMAIL_USERNAME);
        
        /* 郵件信息 */
        MimeMessage message = new MimeMessage(session);
        message.addFrom(senderArray);
        message.addRecipient(Message.RecipientType.TO, new InternetAddress(TO_EMAIL_ADDRESS_1));
        message.setSubject("如何發送HTML的郵件");
        
        /* 正文 */
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent("<h1>loving you...</h2>", "text/html;charset=gb2312");
        
        /* 封裝郵件各部分信息 */
        Multipart multipart = new MimeMultipart();
        multipart.addBodyPart(bodyPart);
        message.setContent(multipart);

        // 發送
        Transport.send(message);
        System.out.println("不是特別倒霉,你可以去查收郵件了。");
    }

}
View Code

 

 要不,來個工具類?

認證器是一定的,沿用,略。

 

由於需要設置的屬性多且繁雜,用個自己人簡單易用的屬性命名,所以來一個配置類

package No005_來一個工具類;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class MailSenderConfig {
    private String SMTPMailHost; // 支持SMTP協議的郵件服務器地址

    /* 用於登錄郵件服務器 */
    private String username;
    private String password;

    private String subject; // 標題
    private String content; // 內容
    
    private String fromMail; // 顯示從此郵箱發出郵件
    private List<String> toMails; // 收件人
    private List<String> ccMails; // 抄送人
    private List<String> bccMails; // 秘密抄送人
    private List<File> attachments; // 附件
    
    public MailSenderConfig(String sMTPMailHost, String subject,
            String content, String fromMail) {
        super();
        SMTPMailHost = sMTPMailHost;
        this.subject = subject;
        this.content = content;
        this.fromMail = fromMail;
    }

    public String getSMTPMailHost() {
        return SMTPMailHost;
    }

    public void setSMTPMailHost(String sMTPMailHost) {
        SMTPMailHost = sMTPMailHost;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFromMail() {
        return fromMail;
    }

    public void setFromMail(String fromMail) {
        this.fromMail = fromMail;
    }

    public List<String> getToMails() {
        return toMails;
    }

    public void setToMails(List<String> toMails) {
        this.toMails = toMails;
    }

    public List<String> getCcMails() {
        return ccMails;
    }

    public void setCcMails(List<String> ccMails) {
        this.ccMails = ccMails;
    }

    public List<String> getBccMails() {
        return bccMails;
    }

    public void setBccMails(List<String> bccMails) {
        this.bccMails = bccMails;
    }

    public List<File> getAttachments() {
        return attachments;
    }

    public void setAttachments(List<File> attachments) {
        this.attachments = attachments;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
    
    public void addToMail (String mail) {
        if (this.toMails == null) {
            this.toMails = new ArrayList<String>();
        }
        this.toMails.add(mail);
    }
    
    public void addCcMail (String mail) {
        if (this.ccMails == null) {
            this.ccMails = new ArrayList<String>();
        }
        this.ccMails.add(mail);
    }
    
    public void addBccMail (String mail) {
        if (this.bccMails == null) {
            this.bccMails = new ArrayList<String>();
        }
        this.bccMails.add(mail);
    }
    
    public void addAttachment (File f) {
        if (this.attachments == null) {
            this.attachments = new ArrayList<File>();
        }
        this.attachments.add(f);
    }
    
}
View Code

 

 

最后,就是工具類的部分,主要負責幾個事情:按照Java Mail規則作些初始化動作、將自定義的屬性配置類翻譯並以Java Mail規則設置、發送郵件。

還有,需要提下的是,因為工具類所提供的代替設置的屬性有限,更多的情況可能不滿足需要,所以暴露出MimeMessage,在不滿足需求的情況開發者可自行加工配置,而其他部分仍可沿用工具類。

package No005_來一個工具類;

import java.io.File;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import No002_各種發件人收件人抄送人怎么辦.SimpleAuthenticator;

public class MailSender {
    
    private MailSenderConfig c;
    private MimeMessage message;
    
    public MailSender(MailSenderConfig config) throws Exception {
        super();
        this.c = config;
        this.setConfig();
    }
    
    /**
     * 初始化
     * @return
     */
    private Session initSession() {
        Properties props = new Properties();
        if (c.getSMTPMailHost() != null && c.getSMTPMailHost().length() > 0) {
            props.put("mail.smtp.host", c.getSMTPMailHost());
        }
        
        if (c.getUsername() != null && c.getUsername().length() > 0 && 
                c.getPassword() != null && c.getPassword().length() > 0) {
            props.put("mail.smtp.auth", "true");
            return Session.getDefaultInstance(props, new SimpleAuthenticator(c.getUsername(), c.getPassword()));
        } else {
            props.put("mail.smtp.auth", "false");
            return Session.getDefaultInstance(props);
        }
    }
    
    /**
     * 設置Java Mail屬性
     * @throws Exception
     */
    private void setConfig() throws Exception {
        this.configValid();
        
        Session s = this.initSession();
        message = new MimeMessage(s);
        
        /* 發件人 */
        Address[] fromMailArray = new Address[1];
        fromMailArray[0] = new InternetAddress(c.getFromMail());
        message.addFrom(fromMailArray);
        
        if (c.getToMails() != null && c.getToMails().size() > 0) {
            for (String mail : c.getToMails()) {
                message.addRecipient(Message.RecipientType.TO, new InternetAddress(mail));
            }
        }
        if (c.getCcMails() != null && c.getCcMails().size() > 0) {
            for (String mail : c.getCcMails()) {
                message.addRecipient(Message.RecipientType.CC, new InternetAddress(mail));
            }
        }
        if (c.getToMails() != null && c.getToMails().size() > 0) {
            for (String mail : c.getToMails()) {
                message.addRecipient(Message.RecipientType.BCC, new InternetAddress(mail));
            }
        }
        
        // 郵件標題
        message.setSubject(c.getSubject());
        
        /* 正文 */
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(c.getContent(), "text/html;charset=gb2312");
        
        /* 封裝郵件各部分信息 */
        Multipart multipart = new MimeMultipart();
        multipart.addBodyPart(bodyPart);
        message.setContent(multipart);
        
        BodyPart attachmentPart = null;
        DataSource ds = null;
        if (c.getAttachments() != null && c.getAttachments().size() > 0) {
            for (File f : c.getAttachments()) {
                attachmentPart = new MimeBodyPart();
                ds = new FileDataSource(f);
                attachmentPart.setDataHandler(new DataHandler(ds));
                attachmentPart.setFileName("=?GBK?B?" + new sun.misc.BASE64Encoder().encode(f.getName().getBytes()) + "?=");
                
                multipart.addBodyPart(attachmentPart);
            }
        }
        
        message.setContent(multipart);
    }
    
    /**
     * 配置校驗
     * @throws Exception
     */
    private void configValid() throws Exception {
        if (c == null) {
            throw new Exception("配置對象為空");
        }
        
        if (c.getSMTPMailHost() == null || c.getSMTPMailHost().length() == 0) {
            throw new Exception("SMTP服務器為空");
        }
        
        if (c.getFromMail() == null && c.getFromMail().length() == 0) {
            throw new Exception("發件人郵件為空");
        }
        
        if (c.getToMails() == null || c.getToMails().size() < 1) {
            throw new Exception("收件人郵件為空");
        }
        
        if (c.getSubject() == null || c.getSubject().length() == 0) {
            throw new Exception("郵件標題為空");
        }
        
        if (c.getContent() == null || c.getContent().length() == 0) {
            throw new Exception("郵件內容為空");
        }
    }
    
    /**
     * 發送郵件
     * @throws MessagingException
     */
    public void send() throws MessagingException {
        Transport.send(message);
    }
    
    /**
     * 設置MimeMessage,暴露此對象以便於開發者自行設置個性化的屬性
     * @return
     */
    public MimeMessage getMessage() {
        return message;
    }

    /**
     * 設置MimeMessage,暴露此對象以便於開發者自行設置個性化的屬性
     * @return
     */
    public void setMessage(MimeMessage message) {
        this.message = message;
    }

}
View Code

 

 

提供一個簡單的測試類

package No005_來一個工具類;

import java.io.File;

import javax.mail.internet.MimeMessage;

public class TestCall {

    public static void main(String[] args) throws Exception {
        /* 必需的信息 */
        String SMTP_MAIL_HOST = "smtp.163.com"; // 此郵件服務器地址,自行去所屬郵件查詢
        String EMAIL_USERNAME = "example@163.com";
        String EMAIL_PASSWORD = "password";
        String TO_EMAIL_ADDRESS_1 = "example@163.com";
        String TO_EMAIL_ADDRESS_2 = "example@163.com";
        
        /* 使用情況一,正常使用 */
        /*
        MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST, 
                "this is test mail for test java mail framework 3.", "this is content 3.", EMAIL_USERNAME);
        c.setUsername(EMAIL_USERNAME);
        c.setPassword(EMAIL_PASSWORD);
        c.addToMail(TO_EMAIL_ADDRESS_1);
        c.addToMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_1);
        c.addAttachment(new File("d:/1.txt"));
        
        MailSender ms = new MailSender(c);
        ms.send();
        System.out.println("sent...");
        */
        
        /* 使用情況二,在更多情況下,工具類所作的設置並不滿足需求,故將MimeMessage暴露並 */
        MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST, 
                "this is test mail for test java mail framework 4.", "this is content 4.", EMAIL_USERNAME);
        c.setUsername(EMAIL_USERNAME);
        c.setPassword(EMAIL_PASSWORD);
        c.addToMail(TO_EMAIL_ADDRESS_1);
        c.addToMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_1);
        c.addAttachment(new File("d:/1.txt"));
        
        MailSender ms = new MailSender(c);
        
        MimeMessage message = ms.getMessage();
        message.setContent("this is the replaced content by MimeMessage 4.", "text/html;charset=utf-8");
        ms.setMessage(message);
        
        ms.send();
        System.out.println("sent...");
    }

}
View Code

 

升級下工具類

在實際使用中,發現在批量發送郵件情況下,工具類的支持不好,比如發送100封郵件,按照上述工具類的邏輯,每發送一封郵件就建立一個連接,那么,100封不就100次了嗎?這樣嚴重浪費啊。

於是,針對此點作些升級:

 

認證器是一定的,沿用,略。

 

配置類

import java.util.ArrayList;
import java.util.List;

public class MailSenderConfig {
    
    private String SMTPMailHost; // 支持SMTP協議的郵件服務器地址

    /* 用於登錄郵件服務器 */
    private String username;
    private String password;

    private String subject; // 標題
    private String content; // 內容
    
    private String fromMail; // 顯示從此郵箱發出郵件
    private List<String> toMails; // 收件人
    private List<String> ccMails; // 抄送人
    private List<String> bccMails; // 秘密抄送人
    private List<Attachment> attachments; // 附件
    private String contentType = "text/html;charset=utf-8";
    
    /**
     * 構造器
     * @param sMTPMailHost    SMTP服務器
     * @param subject        標題
     * @param content        內容(默認以“text/html;charset=utf-8”形式發送)
     * @param fromMail        發送人地址
     */
    public MailSenderConfig(String sMTPMailHost, String subject,
            String content, String fromMail) {
        super();
        SMTPMailHost = sMTPMailHost;
        this.subject = subject;
        this.content = content;
        this.fromMail = fromMail;
    }
    
    /**
     * 構造器
     * @param sMTPMailHost    SMTP服務器
     * @param username        郵件服務器用戶名
     * @param password        郵件服務器密碼
     * @param subject        標題
     * @param content        內容(默認以“text/html;charset=utf-8”形式發送)
     * @param fromMail        發送人地址
     */
    public MailSenderConfig(String sMTPMailHost, String username,
            String password, String subject, String content, String fromMail) {
        super();
        SMTPMailHost = sMTPMailHost;
        this.username = username;
        this.password = password;
        this.subject = subject;
        this.content = content;
        this.fromMail = fromMail;
    }

    public void addToMail (String mail) {
        if (this.toMails == null) {
            this.toMails = new ArrayList<String>();
        }
        this.toMails.add(mail);
    }
    
    public void addCcMail (String mail) {
        if (this.ccMails == null) {
            this.ccMails = new ArrayList<String>();
        }
        this.ccMails.add(mail);
    }
    
    public void addBccMail (String mail) {
        if (this.bccMails == null) {
            this.bccMails = new ArrayList<String>();
        }
        this.bccMails.add(mail);
    }
    
    public void addAttachment (Attachment a) {
        if (this.attachments == null) {
            this.attachments = new ArrayList<Attachment>();
        }
        this.attachments.add(a);
    }
    
    /*
     * Getter and Setter
     */
    
    public String getSMTPMailHost() {
        return SMTPMailHost;
    }

    public void setSMTPMailHost(String sMTPMailHost) {
        SMTPMailHost = sMTPMailHost;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFromMail() {
        return fromMail;
    }

    public void setFromMail(String fromMail) {
        this.fromMail = fromMail;
    }

    public List<String> getToMails() {
        return toMails;
    }

    public void setToMails(List<String> toMails) {
        this.toMails = toMails;
    }

    public List<String> getCcMails() {
        return ccMails;
    }

    public void setCcMails(List<String> ccMails) {
        this.ccMails = ccMails;
    }

    public List<String> getBccMails() {
        return bccMails;
    }

    public void setBccMails(List<String> bccMails) {
        this.bccMails = bccMails;
    }

    public List<Attachment> getAttachments() {
        return attachments;
    }

    public void setAttachments(List<Attachment> attachments) {
        this.attachments = attachments;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
    
    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }
}
View Code

 

附件實體類

import java.io.File;

/**
 * 郵件附件實體類
 */
public class Attachment {

    private File file;
    private String filename;

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public String getFilename() {
        if (filename == null || filename.trim().length() == 0) {
            return file.getName();
        }
        
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public Attachment(File file, String filename) {
        super();
        this.file = file;
        this.filename = filename;
    }

    public Attachment(File file) {
        super();
        this.file = file;
    }

}
View Code

 

抽象發送類

import java.util.Properties;

import javax.mail.Session;

public abstract class AbstractSessionMailSender {
    
    protected Session session;
    
    /**
     * 初始化Session
     * @return
     */
    public static Session initSession(MailSenderConfig c) {
        Properties props = new Properties();
        if (c.getSMTPMailHost() != null && c.getSMTPMailHost().length() > 0) {
            props.put("mail.smtp.host", c.getSMTPMailHost());
        }
        
        if (c.getUsername() != null && c.getUsername().length() > 0 && 
                c.getPassword() != null && c.getPassword().length() > 0) {
            props.put("mail.smtp.auth", "true");
            return Session.getDefaultInstance(props, new SimpleAuthenticator(c.getUsername(), c.getPassword()));
        } else {
            props.put("mail.smtp.auth", "false");
            return Session.getDefaultInstance(props);
        }
    }

    /**
     * 暴露Getter、Setter提供Session的可設置性,以支持批量發送郵件/發送多次郵件時,可緩存Session
     * @return
     */
    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }
    
}
View Code

 

發送類

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

public class MailSender extends AbstractSessionMailSender {
    
    private MailSenderConfig c;
    private MimeMessage message;
    
    public MailSender(MailSenderConfig config) throws Exception {
        super();
        this.c = config;
        this.setConfig();
    }
    
    public MailSender(MailSenderConfig config, Session session) throws Exception {
        super();
        this.c = config;
        this.setConfig();
        super.setSession(session);
    }
    
    /**
     * 發送郵件
     * @throws MessagingException
     */
    public void send() throws MessagingException {
        Transport.send(message);
    }
    
    /**
     * 獲取MimeMessage,暴露此對象以便於開發者自行設置個性化的屬性(此工具類不支持的方法可由開發人員自行設置,設置完畢設置回來)
     * @return
     */
    public MimeMessage getMessage() {
        return message;
    }

    /**
     * 設置MimeMessage,暴露此對象以便於開發者自行設置個性化的屬性(此工具類不支持的方法可由開發人員自行設置,設置完畢設置回來)
     * @return
     */
    public void setMessage(MimeMessage message) {
        this.message = message;
    }
    
    /**
     * 設置Java Mail屬性
     * @throws Exception
     */
    private void setConfig() throws Exception {
        this.configValid();
        
        if (session == null) {
            session = initSession(c);
        }
        message = new MimeMessage(session);
        
        /* 發件人 */
        Address[] fromMailArray = new Address[1];
        fromMailArray[0] = new InternetAddress(c.getFromMail());
        message.addFrom(fromMailArray);
        
        if (c.getToMails() != null && c.getToMails().size() > 0) {
            for (String mail : c.getToMails()) {
                message.addRecipient(Message.RecipientType.TO, new InternetAddress(mail));
            }
        }
        if (c.getCcMails() != null && c.getCcMails().size() > 0) {
            for (String mail : c.getCcMails()) {
                message.addRecipient(Message.RecipientType.CC, new InternetAddress(mail));
            }
        }
        if (c.getToMails() != null && c.getToMails().size() > 0) {
            for (String mail : c.getToMails()) {
                message.addRecipient(Message.RecipientType.BCC, new InternetAddress(mail));
            }
        }
        
        // 郵件標題
        message.setSubject(c.getSubject());
        
        /* 正文 */
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(c.getContent(), c.getContentType());
        
        /* 封裝郵件各部分信息 */
        Multipart multipart = new MimeMultipart();
        multipart.addBodyPart(bodyPart);
        message.setContent(multipart);
        
        /* 附件 */
        BodyPart attachmentPart = null;
        DataSource ds = null;
        if (c.getAttachments() != null && c.getAttachments().size() > 0) {
            for (Attachment a : c.getAttachments()) {
                attachmentPart = new MimeBodyPart();
                ds = new FileDataSource(a.getFile());
                attachmentPart.setDataHandler(new DataHandler(ds));
                attachmentPart.setFileName(MimeUtility.encodeText(a.getFilename()));
                
                multipart.addBodyPart(attachmentPart);
            }
        }
        
        message.setContent(multipart);
    }
    
    /**
     * 配置校驗
     * @throws Exception
     */
    private void configValid() throws Exception {
        if (c == null) {
            throw new Exception("配置對象為空");
        }
        
        if (c.getSMTPMailHost() == null || c.getSMTPMailHost().length() == 0) {
            throw new Exception("SMTP服務器為空");
        }
        
        if (c.getFromMail() == null && c.getFromMail().length() == 0) {
            throw new Exception("發件人郵件為空");
        }
        
        if (c.getToMails() == null || c.getToMails().size() < 1) {
            throw new Exception("收件人郵件為空");
        }
        
        if (c.getSubject() == null || c.getSubject().length() == 0) {
            throw new Exception("郵件標題為空");
        }
        
        if (c.getContent() == null || c.getContent().length() == 0) {
            throw new Exception("郵件內容為空");
        }
    }
    
}
View Code

 

一個Junit的測試類

import java.io.File;

import javax.mail.Session;
import javax.mail.internet.MimeMessage;

import org.junit.Test;

public class ReadMe {
    
    /* 必需的信息 */
    String SMTP_MAIL_HOST = "smtp.163.com"; // 此郵件服務器地址,自行去所屬郵件服務器描述頁查詢
    String EMAIL_USERNAME = "example@163.com";
    String EMAIL_PASSWORD = "password";
    String TO_EMAIL_ADDRESS_1 = "example@163.com";
    /* 選填的信息 */
    String TO_EMAIL_ADDRESS_2 = "example@163.com";

    @Test
    public void case1() throws Exception {
        /* 使用情況一,正常使用 */
        MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST, 
                "this is a mail for test java mail framework in case1.", "this is content.", EMAIL_USERNAME);
        c.setUsername(EMAIL_USERNAME);
        c.setPassword(EMAIL_PASSWORD);
        c.addToMail(TO_EMAIL_ADDRESS_1);
        c.addToMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_1);
        c.addAttachment(new Attachment(new File("d:/1.txt")));
        
        MailSender ms = new MailSender(c);
        ms.send();
        System.out.println("sent...");
    }
    
    @Test
    public void case2() throws Exception {
        /* 使用情況二,在更多情況下,工具類所作的設置並不滿足需求,故將MimeMessage暴露以便於開發者自行設置個性化的屬性 */
        MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST, 
                "this is a mail for test java mail framework in case2.", "this is content.", EMAIL_USERNAME);
        c.setUsername(EMAIL_USERNAME);
        c.setPassword(EMAIL_PASSWORD);
        c.addToMail(TO_EMAIL_ADDRESS_1);
        c.addToMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_1);
        c.addAttachment(new Attachment(new File("d:/1.txt")));
        
        MailSender ms = new MailSender(c);
        
        MimeMessage message = ms.getMessage();
        message.setContent("this is the replaced content by MimeMessage in case2.", "text/html;charset=utf-8");
        ms.setMessage(message);
        
        ms.send();
        System.out.println("sent...");
    }
    
    @Test
    public void case3() throws Exception {
        /* 使用情況三,多次發送郵件,可緩存Session,使多次發送郵件均共享此Session,以減少重復創建Session
         * 同時需注意緩存的Session的時效性
         */
        MailSenderConfig c = new MailSenderConfig(SMTP_MAIL_HOST, 
                "this is the first mail for test java mail framework to share session in case3.", "this is content.", EMAIL_USERNAME);
        c.setUsername(EMAIL_USERNAME);
        c.setPassword(EMAIL_PASSWORD);
        c.addToMail(TO_EMAIL_ADDRESS_1);
        c.addToMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_2);
        c.addCcMail(TO_EMAIL_ADDRESS_1);
        c.addAttachment(new Attachment(new File("d:/1.txt")));
        
        Session session = MailSender.initSession(c);
        
        MailSender ms = new MailSender(c, session);
        ms.send();
        
        c.setSubject("this is the second mail for test java mail framework to share session in case3.");
        c.setContent("this is content 2.");
        ms = new MailSender(c, session);
        ms.send();
        System.out.println("sent...");
    }

}
View Code

 

關於QQ郵箱不能成功發送的解決方法

有網友發現用本程序不能使用QQ郵箱發送郵件,本人試了后確認不行。主要原因有兩個:1、QQ郵箱需要SSL;2、QQ郵箱需要先開通SMTP服務,再獲取授權碼當作密碼使用(見《什么是授權碼,它又是如何設置?》,點擊進入)。

既然找出了問題,那么解決問題相對容易:

1、設置SSL,代碼如下:

props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.port", "465");
View Code

2、然后到自己的郵箱中開啟SMTP服務后獲取授權碼當作密碼使用。

如無意外,就OK了。

關於使用Java Mail通過QQ郵箱發送郵件,這篇文章寫得很好:《Java 基於JavaMail實現向QQ郵箱發送郵件》,點擊進入

總結

目前,我遇到的需求就是這么多,如日后遇見其他常見的需求並有時間,會進一步添加。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM