美文网首页
Javax.Mail 工具类

Javax.Mail 工具类

作者: wang6771264 | 来源:发表于2019-02-14 16:35 被阅读0次
    • 1.基础Model

    package com.maple.common.utils.mail;
    
    import javax.activation.DataHandler;
    import java.util.List;
    import java.util.Map;
    
    import lombok.Data;
    
    @Data
    public class MailMessage {
        /**
         * 内容ID
         */
        private String contentID;
        /**
         * 主题
         */
        private String subject;
        /**
         * 内容(包括html)
         */
        private String content;
        /**
         * 文本格式类型(例子:text/html; charset=utf-8)
         */
        private String subType;
        /**
         * 图片传入,适用于HTML邮件,key:cid名称;value:文件路径
         */
        private Map<String, String> images;
        /**
         * 附件上传
         */
        private List<String> attachments;
        /**
         * 文件
         */
        private DataHandler dh;
        /**
         * 描述
         */
        private String description;
    }
    

    package com.maple.common.utils.mail;
    
    import java.util.Map;
    
    import lombok.Data;
    
    /**
     * 填充模板的邮件实体
     */
    @Data
    public class MailTmplMessage extends MailMessage {
        private String tmplPath;
        private Map<String, String> params;
    }
    
    • 2.辅助类

    package com.maple.common.utils.mail;
    
    import java.io.File;
    import java.net.URL;
    import java.util.Date;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class CacheEntity<T> {
        Logger logger = LoggerFactory.getLogger(getClass());
        Date date;
        URL url;
        long lastModified;
        long hit;
        long length;
        T t;
    
        public long getLastModified() {
            return lastModified;
        }
    
        public void setLastModified(long lastModified) {
            this.lastModified = lastModified;
        }
    
        public long getHit() {
            return hit;
        }
    
        public void setHit(long hit) {
            this.hit = hit;
        }
    
        public long getLength() {
            return length;
        }
    
        public void setLength(long length) {
            this.length = length;
        }
    
        public T getT() {
            return t;
        }
    
        public void setT(T t) {
            this.t = t;
        }
    
        public boolean validate(File file) {
            if (file != null) {
                if (file.lastModified() != this.lastModified) {
                    return false;
                }
                if (file.length() != this.length) {
                    return false;
                }
            }
            logger.debug("url {} hit {}", url, ++hit);
            return true;
        }
    
        public CacheEntity(URL url, File file, T t) {
            this.url = url;
            this.date = new Date(System.currentTimeMillis());
            this.hit = 0;
            if (file != null) {
                this.lastModified = file.lastModified();
                this.length = file.length();
            }
            this.t = t;
        }
    
        public String toString() {
            if (date == null) {
                return "Hit #" + hit;
            }
            return "Hit #" + hit + " since " + date;
        }
    }
    

    package com.maple.common.utils.mail;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    import java.util.WeakHashMap;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public abstract class AbsFileCache<T> {
        protected Logger logger = LoggerFactory.getLogger(getClass());
        WeakHashMap<String, CacheEntity<T>> cache;
    
        public AbsFileCache(int cacheSize) {
            cache = new WeakHashMap<String, CacheEntity<T>>(cacheSize);
        }
        
        public T get(String path) throws IOException {
            URL url = this.getClass().getClassLoader().getResource(path);
            if (url != null) {
                logger.info("load file:"+url);
                String protocol = url.getProtocol();
                File file = null;
                InputStream is = null;
                if ("jar".equals(protocol) || "zip".equals(protocol)) {
                    String jarFile = url.getFile();
                    int pos = jarFile.indexOf("!");
                    if (pos > 0) {
                        jarFile = jarFile.substring(0, pos);
                    }
                    file = new File(jarFile);
                    is = url.openStream();
                } else if ("file".equals(protocol)) {
                    file = new File(url.getFile());
                    is = new FileInputStream(file);
                } else {
                    logger.warn("not support the protocol {} with {}", protocol, url);
                }
                CacheEntity<T> ce = cache.get(path);
                if (ce != null && ce.validate(file)) {
                    return ce.getT();
                } else {
                    try {
                        T t = createCache(is);
                        ce = new CacheEntity<T>(url, file, t);
                        cache.put(path, ce);
                        return t;
                    } finally {
                        if (is != null) {
                            is.close();
                        }
                    }
                }
            } else {
                logger.warn("not found the file {}", path);
            }
            return null;
        }
    
        protected abstract T createCache(InputStream is) throws IOException;
    }
    

    package com.maple.common.utils.mail;
    
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    import groovy.text.StreamingTemplateEngine;
    import groovy.text.Template;
    
    public final class TemplateCache extends AbsFileCache<Template> {
    
        StreamingTemplateEngine templateEngine = new StreamingTemplateEngine();
    
        private TemplateCache() {
            super(256);
        }
    
        private static class TemplateCacheHolder {
            private static TemplateCache Ins = new TemplateCache();
        }
    
        public static TemplateCache getIns() {
            return TemplateCacheHolder.Ins;
        }
    
        @Override
        public Template createCache(InputStream is) {
            Template t;
            try {
                t = templateEngine.createTemplate(new InputStreamReader(is, "UTF-8"));
                return t;
            } catch (Exception e) {
                logger.error("create template error", e);
                throw new RuntimeException(e);
            }
        }
    
    }
    


    • 3.邮件发送类

      Props参数配置可以在https://javaee.github.io/javamail/docs/api/中找到,一般邮件发送都是用smtp/pop3即可。*
      *使用groovy的模板引擎参数找不到会报错,不会填充完毕,最终选择使用Velocity来做,Spring有velociy的支持。
    package com.maple.common.utils.mail;
    
    import javax.activation.DataHandler;
    import javax.activation.DataSource;
    import javax.activation.FileDataSource;
    import javax.annotation.PostConstruct;
    import javax.mail.Authenticator;
    import javax.mail.BodyPart;
    import javax.mail.Flags;
    import javax.mail.Folder;
    import javax.mail.Message;
    import javax.mail.MessagingException;
    import javax.mail.Multipart;
    import javax.mail.Part;
    import javax.mail.PasswordAuthentication;
    import javax.mail.Session;
    import javax.mail.Transport;
    import javax.mail.event.MessageCountAdapter;
    import javax.mail.event.MessageCountEvent;
    import javax.mail.internet.MimeBodyPart;
    import javax.mail.internet.MimeMessage;
    import javax.mail.internet.MimeMultipart;
    import javax.mail.internet.MimeUtility;
    import javax.mail.util.ByteArrayDataSource;
    import java.io.File;
    import java.io.IOException;
    import java.io.StringWriter;
    import java.io.UnsupportedEncodingException;
    import java.util.Date;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Properties;
    
    import com.alibaba.fastjson.JSON;
    import com.sun.mail.imap.IMAPFolder;
    import groovy.text.Template;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    import org.springframework.util.CollectionUtils;
    
    /**
     * 邮件工具类
     */
    @Slf4j
    @Component
    public class MailService {
         @Autowired
         private Velocity velocity;
    
        private static final String username = "xxxx@qq.com";
        //此处需要注意的是,这里的密码是邮箱的第三方访问授权码,不是真正的邮箱密码
        private static final String password = "sfhfaqvyvfhzdjii";
    
        Authenticator auth = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        };
    
        Properties props = new Properties();
    
        @PostConstruct
        public void init(){
            //基础参数设置
            props.put("mail.smtp.host", "smtp.qq.com");
            props.put("mail.imap.host", "imap.qq.com");
            //pop3参数设置
            props.put("mail.pop3.user", "2294808913@qq.com");
            props.put("mmail.pop3.host", "pop.qq.com");
            props.put("mail.pop3.ssl.enable", true);
            props.put("mail.pop3.port", 995);
            props.put("mail.smtp.port", 465);
            props.put("mail.smtp.ssl.enable", "true");
    
            props.put("mail.smtp.starttls.enable", "true");
            props.put("mail.debug", "true");
        }
    
        public void sendTmplEmail(String recipients, MailTmplMessage msg, Message.RecipientType type){
            StringWriter sw = new StringWriter();
            try {
                //参数找不到会报错,不可取
                Template t = TemplateCache.getIns().get(msg.getTmplPath());
                t.make(msg.getParams()).writeTo(sw);
    
                msg.setContent(sw.toString());
            } catch (IOException e) {
                log.error("File tmpl assembly failed! params:{}", JSON.toJSONString(msg.getParams()), e);
            }
            sendMail(recipients, msg, type);
        }
    
        /**
         * @param type:Message.RecipientType.TO常量表示收件人类型是邮件接收者
         *             Message.RecipientType.CC常量表示收件人类型是抄送者
         *             Message.RecipientType.BCC常量表示收件人的类型是密送着
         *
         */
        public void sendMail(String recipients, MailMessage msg, Message.RecipientType type) {
            // set any other needed mail.smtp.* properties here
            Session session = Session.getDefaultInstance(props, auth);
            // set the message content here
    //        msg.setContent(mp);
    
            try {
                MimeMessage mimeMessage = new MimeMessage(session);
                mimeMessage.setFrom(username);
    
                mimeMessage.setSubject(msg.getSubject());
    
                //HTML页面
                if (msg.getSubType().contains("text/html")) {
                    Multipart multipart = new MimeMultipart();
                    mimeMessage.setContent(multipart);
                    MimeBodyPart htmlBody = new MimeBodyPart();
                    multipart.addBodyPart(htmlBody);
                    htmlBody.setContent(msg.getContent(), msg.getSubType());
    
                    //HTML内嵌图片
                    if (!CollectionUtils.isEmpty(msg.getImages())) {
                        addImages(multipart, msg.getImages());
                    }
                }else{
                    mimeMessage.setText(msg.getContent());
                }
    
                //上传附件
                if (!CollectionUtils.isEmpty(msg.getAttachments())) {
                    Multipart multipart;
                    if(mimeMessage.getContent() != null){
                        multipart = (MimeMultipart)mimeMessage.getContent();
                    }else{
                        multipart = new MimeMultipart();
                    }
    
                    for (String attachment : msg.getAttachments()) {
                        multipart.addBodyPart(createAttachment(attachment));
                    }
                }
    
                mimeMessage.setSentDate(new Date());
                mimeMessage.setRecipients(type, recipients);
    
                Transport transport = session.getTransport();
    
                transport.send(mimeMessage, username, password);
            } catch (MessagingException e) {
                log.error("send mail failed! content! Email:{}", JSON.toJSONString(msg), e);
            } catch (IOException e) {
                log.error("create attachment failed! Email:{}", JSON.toJSONString(msg), e);
            }
        }
    
        /**
         * 上传附件
         */
        private BodyPart createAttachment(String attachment){
            try {
                MimeBodyPart mbp = new MimeBodyPart();
                DataSource fds = new FileDataSource(attachment);
                mbp.setFileName(MimeUtility.encodeText(fds.getName()));
                DataHandler dh = new DataHandler(fds);
    
                mbp.setDataHandler(dh);
                return mbp;
            } catch (MessagingException e) {
                log.error("add attachment failed! fileName:{}", attachment, e);
            } catch (UnsupportedEncodingException e) {
                log.error("file format error! fileName:{}", attachment, e);
            }
    
            return null;
        }
    
        /**
         * html文件添加图片
         * 注意:如果在html文本中未标记cid,文件会被当做附件处理
         */
        private void addImages(Multipart multipart, Map<String, String> images) {
            for (Entry<String, String> entry : images.entrySet()) {
                MimeBodyPart imageBody = new MimeBodyPart();
                try {
                    imageBody.setContentID(entry.getKey());
                    DataSource fds = new FileDataSource(entry.getValue());
                    imageBody.setFileName(MimeUtility.encodeText(fds.getName()));
                    DataHandler dh = new DataHandler(fds);
                    imageBody.setDataHandler(dh);
    
                    multipart.addBodyPart(imageBody);
                } catch (MessagingException e) {
                    log.error("add image failed! ContentID:{}", entry.getKey(), e);
                } catch (UnsupportedEncodingException e) {
                    log.error("file format error! fileName:{}", entry.getValue(), e);
                }
            }
        }
    
        /**
         * 添加附件(文件形式添加)
         * @param file
         */
        public void addAttachment(File file){
            DataSource ds = new FileDataSource(file) {
                public String getContentType() {
                    return "mytype/mysubtype";
                }
            };
            MimeBodyPart mbp = new MimeBodyPart();
            try {
                mbp.setDataHandler(new DataHandler(ds));
                //早期的javamail可以使用该方法编码
                mbp.setFileName(MimeUtility.encodeText(file.getName()));
                //对应的解码
    //            String filename = MimeUtility.decodeText(mbp.getFileName());
                mbp.setFileName(file.getName());
                mbp.setDisposition(Part.ATTACHMENT);
            } catch (MessagingException e) {
                log.error("add attachment failed!", e);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 添加附件(byte形式添加)
         * @param data
         */
        public void addAttachment(String data){
            MimeBodyPart mbp = new MimeBodyPart();
            data = "any ASCII data";
            try {
                DataSource ds = new ByteArrayDataSource(data, "application/x-any");
                mbp.setDataHandler(new DataHandler(ds));
            } catch (MessagingException e) {
                log.error("add ASCII data failed!", e);
            } catch (IOException e) {
                log.error("read byte data failed! data:{}", data, e);
            }
        }
    }
    
    • 4.测试类

    package com.maple.example;
    
    import javax.mail.Message.RecipientType;
    import java.io.IOException;
    import java.io.StringWriter;
    import java.util.HashMap;
    import java.util.Map;
    
    import com.maple.common.utils.mail.MailService;
    import com.maple.common.utils.mail.MailTmplMessage;
    import com.maple.common.utils.mail.TemplateCache;
    import groovy.text.Template;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.junit4.SpringRunner;
    
    @RunWith(SpringRunner.class)
    //@SpringBootTest
    public class StudyApplicationTests {
    
        @Test
        public void contextLoads() {
    
        }
    
        //    @Autowired
        private MailService mailService = new MailService();
    
        @Test
        public void sendMailTest() {
            MailTmplMessage msg = new MailTmplMessage();
            msg.setSubject("测试html邮件主题");
    
            Map<String, String> map = new HashMap<>();
            map.put("title", "测试邮件标题");
            map.put("first", "大写头");
            map.put("testMan", "王威");
    
            msg.setParams(map);
    
            //html照片
            String userDir = System.getProperties().get("user.dir").toString();
    
            Map<String, String> images = new HashMap<>();
            images.put("image", userDir + "/src/main/resources/img/test_email.jpg");
            images.put("email2", userDir + "/src/main/resources/img/email2.png");
    
            msg.setImages(images);
            msg.setTmplPath("templates/mail/testMail.html");
            msg.setSubType("text/html; charset=utf-8");
            msg.setDescription("Maple test send!");
    
            mailService.sendTmplEmail("858869180@qq.com,2294808913@qq.com", msg, RecipientType.TO);
        }
    
        /**
         * 参数找不到会报错,不可取
         */
        @Test
        public void tmplGroovyTest(){
            Map<String, String> map = new HashMap<>();
            map.put("title", "测试邮件标题");
            map.put("first", "大写头");
            map.put("testMan", "王威");
    
            try {
                Template t = TemplateCache.getIns().get("templates/mail/testMail.html");
                StringWriter sw = new StringWriter();
                t.make(map).writeTo(sw);
                System.out.println(sw.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 5.配置文件

      • 5.1 pom文件

            <dependency>
                <groupId>javax.mail</groupId>
                <artifactId>javax.mail-api</artifactId>
                <version>1.6.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-all -->
            <dependency>
                <groupId>org.codehaus.groovy</groupId>
                <artifactId>groovy-all</artifactId>
                <version>${groovy.version}</version>
                <type>pom</type>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity -->
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity</artifactId>
                <version>1.7</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-mail</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-velocity</artifactId>
            </dependency>
    
    • 5.2 velocity配置文件

    directive.foreach.counter.name = velocityCount
    directive.foreach.counter.initial.value = 1
    
    input.encoding=UTF-8
    output.encoding=UTF-8
    Velocity.ENCODING_DEFAULT=UTF-8
    Velocity.INPUT_ENCODING=UTF-8
    Velocity.OUTPUT_ENCODING=UTF-8
    
    default.contentType=text/html; charset=UTF-8 
    
    #layout  
    tools.view.servlet.layout.directory=/WEB-INF/view/layout/ 
    
      本片文章仅作为记录,如有错误,请评论指出多多交流谢谢!

    相关文章

      网友评论

          本文标题:Javax.Mail 工具类

          本文链接:https://www.haomeiwen.com/subject/wdpkeqtx.html