commons-email 发送HTML邮件(结合freemarker生成html)

需求:批量发邮件给用户,邮件是html的,有个按钮点了可以下载附件或html之类的

想法:java基本的发邮件的工具是JavaMail,而我用的是alpha的comnoms-email。然后呢,html的内容也不少,不可能用StringBuilder去拼一个字符串吧,所以我就使用freemarker模板,去生成html。后面又说邮件要分状态,某个状态下是下载附件,这个是已经上传到阿里oss上了,直接打开那个oss地址就行;但某个状态是要本地生成一个html,然后上传到oss上,然后拿回调的oss地址去下载。很6的是这个本地生成的html其实是已经有了的,但是它是在前端Vue项目里的,所以说可以复用。但是呢,我还真没试过在freemaker里去搞vue,有这功夫谁会在模板引擎里用,直接前后台分离啊歪。好吧,需求如此,开干。

首先是,集成下所需的jar包:

        
            org.apache.commons
            commons-email
            1.4
        
        
            org.freemarker
            freemarker
            2.3.30
        

然后,实现发邮件的功能,同时生成html邮件。使用Juint运行commons-email官方示例。

    @Test
    public void test() throws EmailException {
        HtmlEmail email = new HtmlEmail();
        // hostName为你发送邮件的账号的smtp服务器,一般每种邮箱都有特定的smtp服务器
        // 比如:smtp.163.com是163邮箱的,端口25,身份认证是:账号和登录密码
        // smtp.qq.com是qq邮箱的,端口465,身份认证是:账号和QQ邮箱授权码
        email.setHostName("smtp.163.com");
        email.setSmtpPort(25);
        // 账号和密码
        email.setAuthentication("***@163.com", "***");
        // 将要发送邮件的接受人和称呼
        email.addTo("**@qq.com", "weic");
        // 发送人和称呼
        email.setFrom("*@163.com", "Me");
        // 邮件主题
        email.setSubject("Test email with inline image");
        // 字符编码
        email.setCharset("UTF-8");
         // embed the image and get the content id
        URL url = new URL("http://www.apache.org/images/asf_logo_wide.gif");
        String cid = email.embed(url, "Apache logo");

        // set the html message
        email.setHtmlMsg("The apache logo - ");
        // set the alternative message
        email.setTextMsg("你的email不支持html格式");
        // send the email
        email.send();
    }

运行下,可以看看你是否接收到邮件


官方实例演示邮件.png

现在思考下一个需求点,邮件不再是一个简单的html页面,可能需要一些花里胡哨的操作。那可以使用freemarker模板引擎生成对应的html,总好过自己去搞html字符串。

首先,在resources文件下新建一个email/template文件,然后将我们用到的ftl模板放入。需要注意的是如果我们是在test下跑的junit,需要在test中java的同级目录新建一个resources文件,然后通过Mark将其标记为资源文件,之后重复resources的流程。


IDEA设置文件夹为资源文件.png

index.ftl




    
    Hello World!


用于测试的Html邮件
${name}的名片

${name}

<#--

${sex}

--> <#--

${age}岁

-->

电话:

10086

邮箱:

****@**.com

juint test方法

        HtmlEmail email = new HtmlEmail();
        // hostName为你发送邮件的账号的smtp服务器,一般每种邮箱都有特定的smtp服务器
        // 比如:smtp.163.com是163邮箱的,端口25,身份认证是:账号和登录密码
        // smtp.qq.com是qq邮箱的,端口465,身份认证是:账号和QQ邮箱授权码
        email.setHostName("smtp.163.com");
        email.setSmtpPort(25);
        // 账号和密码
        email.setAuthentication("***@163.com", "***");
        // 将要发送邮件的接受人和称呼
        email.addTo("**@qq.com", "weic");
        // 发送人和称呼
        email.setFrom("*@163.com", "Me");
        // 邮件主题
        email.setSubject("Test email with inline image");
        // 字符编码
        email.setCharset("UTF-8");
        // 开启ssl
        email.setSSLCheckServerIdentity(true)
        // 读取SendEmail的根目录,这里就是target的目录
        String baseURL = Objects.requireNonNull(SendEmail.class.getClassLoader().getResource("")).getPath();
        StringWriter html = new StringWriter();
        try {
            // freemarker指定版本
            Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
            //指定对象模板存放的位置
            cfg.setDirectoryForTemplateLoading(new File(baseURL+"/email/template"));
            //设置字符集
            cfg.setDefaultEncoding("utf-8");
            // 通过map设置参数
            Map rootMap = new HashMap<>(20);
            rootMap.put("logo", "http://www.apache.org/images/asf_logo_wide.gif");
            rootMap.put("name", "Hello World!");
            rootMap.put("btnText", "点击一下");
            rootMap.put("downloadUrl", "");
            // 读取模板
            Template template = cfg.getTemplate("index.ftl");
            // 写入参数
            template.process(rootMap, html);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }

        // set the html message
        email.setHtmlMsg(html.toString());
        // set the alternative message
        email.setTextMsg("你的email不支持html格式");
        // send the email
        email.send();

看下效果:


邮件一.png

在代码中我们有一个downloadUrl参数,他的作用是点击下载一个html,但是呢,这个html需要本地去生成,然后上传到oss上。也就是说我们需要oss回调的地址,作为download的地址。

    ...
    String baseURL = Objects.requireNonNull(SendEmail.class.getClassLoader().getResource("")).getPath();
    // 在本地生成一个html
    File afile = new File(baseURL + "test.html");
    try {
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
        //指定对象模板存放的位置
        cfg.setDirectoryForTemplateLoading(new File(baseURL+"/email/template"));
        //设置字符集
        cfg.setDefaultEncoding("utf-8");
        Template template = cfg.getTemplate("resume.ftl");
        // 为resume.ftl模板写入数据
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(afile), "UTF-8"));
        template.process(result, out);
        out.flush();
        out.close();
        // 通过oss上传html
        OSS ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 通过雪花算法生成唯一文件名
        String fileName = Snowflake.generateId() + ".html";
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, fileName , afile);
        ossClient.putObject(putObjectRequest);
        ossClient.shutdown();
        // 获取地址,注:oss的相关配置应提前准备好,webHost地址为oss地址前缀
        onlinePath = webHost + fileName;
        // 如果文件存在删除
        if (afile.exists()) {
            afile.delete();
        }
    } catch (Exception e) {
        e.printStackTrace();
        // 如果文件存在删除
        if (afile.exists()) {
            afile.delete();
        }
    }
    ...

resume.ftl

!DOCTYPE html>


    
    
    


你可能感兴趣的:(commons-email 发送HTML邮件(结合freemarker生成html))