zoukankan      html  css  js  c++  java
  • 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邮箱发送邮件》,点击进入

    总结

    目前,我遇到的需求就是这么多,如日后遇见其他常见的需求并有时间,会进一步添加。

  • 相关阅读:
    Django文档翻译:模型参考(Model Reference)
    Anthem.NET 的 "BAD RESPONSE" 问题的脚本调试技巧小结
    注意 JavaScript 中 RegExp 对象的 test 方法
    CodeProject 文章收藏 (200713)
    Django 学习纪要(1) 模版语法
    关注一下 IronPython Community Edition
    SubSonic 的字段名未转义问题修正
    Error while trying to run project: Unable to start debugging 绑定句柄无效
    Django 中自定义 tag 如何获取变量参数的值
    Karrigell 初次学习
  • 原文地址:https://www.cnblogs.com/nick-huang/p/4709508.html
Copyright © 2011-2022 走看看