跳至主要內容

📧邮件插件

wind大约 17 分钟

前言

邮件类的工具在我的记忆中市面上有很多,不过因为平时很少有这方面的业务,所以用的不多,也没有太深入的了解他们都包含了什么功能,只是我根据自己想到的可能会
需要的功能做了一些封装,可能不全面,希望大家多提意见。

安装

maven引入

  <dependency>
    <groupId>org.dromara.sms4j</groupId>
    <artifactId>sms4j-Email-core</artifactId>
    <version> 最新版本跟随sms4j </version>
  </dependency>

配置

Email-plugin不做特殊适配,不严格要求配置形式,不管你是java se还是springboot 还是solon,都可以直接进行使用,兼容JDK17。
在框架的默认中,是维护了一个配置资源池,但是不会关注资源池内的对象是否是一样的,所以你可以用它来实现类似于多租户的功能
框架不会关注你的数据的来源和方式,只会关注最终对象池中的对象。所以,你可以尽情的发挥,从数据库获取,从redis获取,从消息队列获取等等等等……
配置字段:

      端口号
     String port;
     
     发件人地址
     String fromAddress;
     
     服务器地址
     String smtpServer;
     
     账号
     String username;
     
     密码   注意的是如果你用的是QQ或者网易之类的邮箱需要的不是登录密码,而是授权码
     String password;
     
     是否开启ssl 默认开启 QQ之类的邮箱默认都需要ssl
     String isSSL = "true";
     
     是否开启验证 默认开启
     String isAuth = "true";

配置对象托管入对象池

//以下仅做演示,实际使用需要填入数据
MailSmtpConfig config = MailSmtpConfig.builder.build;

//这里的key可以是任何可对比类型,用于后续从工厂取出邮件实现类用
MailFactory.put("qq",config)

使用

我们在将配置放入配置池后,可以通过 MailFactory工厂获取到对应配置的邮件客户端实现,例如我们刚刚放置的key为“qq”的配置

MailClient mail = MailFactory.createMailClient("qq");

黑名单过滤

在发送邮件时,我们有时候需要过滤掉某些账号,这时我们可以使用黑名单过滤功能
1.首先我们实现一个位于org.dromara.email.api包的Blacklist接口,并实现getBlacklist方法,在这里,方法的返回值就是需要过滤掉的邮箱地址,至于你过滤数据的来源,框架并不进行关注
示例:

public class BlackListImpl implements BlackList {

    @Override
    public List<String> getBlackList() {
        List<String> blackList = new ArrayList<>();
        blackList.add("111111111@qq.com");
        return blackList;
    }
}

2.在获取邮件客户端实例的时候我们需要将回调的对象传递至工厂
当然,Blacklist也是一个函数式接口,你也可以通过lambda表达式来构建
示例:

MailClient mail = MailFactory.createMailClient("qq",new BlackListImpl);

提示

获取到的带有过滤黑名单过滤功能的客户端与普通的客户端方法完全一致,只是在发送时他会首先将黑名单中的号码进行排除。

方法使用

目前,插件支持

  • html模板邮件
  • 普通文本邮件
  • 携带附件的文本邮件
  • 携带附件的html模板邮件
  • 同时携带文字正文和html模板和附件的邮件(在多数的邮箱中其实并不支持这种形式,在展示的时候html会把正文覆盖,但是也有少数的邮箱支持这种的渲染)

html模板邮件

html模板邮件是框架内部进行的定义,实际上是将给定的模板进行的转译,你可以创建一个标准的html文件,然后在文件内部需要放置内容的地方用#{变量名}的形式进行替代,
这样在框架拿到html文件后会将内部的变量替换成你给定的值
示例:
html默认会读取 resources/template目录下的文件,假如我们现在在resources/template目录下放置了一个名为:mail_test.html的文件
文件内有两个变量 #{name} 和 #

Map<String,String> map = new HashMap<>();
map.put("name","这是变量name的内容");
map.put("size","这是变量size的内容");
mail.sendHtml("收件人","邮件标题","mail_test.html",map);

map,map又是map作者你咋那么喜欢Map呢! 哎,其实我也不喜欢,这不预备了其他的形式。

Parameter接口

Parameter接口是一个空接口,它用于标定你的实体类类型,这样就可以不用写map了,你的字段名就是变量名,字段值就是变量值
示例:

@Data
public class EntityText implements Parameter{
    private String name;
    private String size;
}

EntityText entity = new EntityText();
entity.setName("这是变量name的值");
entity.setSize("这是变量size的值");
mail.sendHtml("收件人","邮件标题","mail_test.html",entity);

携带附件的html邮件

sendHtml()方法有多个重载方法,覆盖了多种的适用场景,包括单人邮件,群发邮件,单人携带附件的邮件,群发携带附件的邮件等等。以下api详解中会列出所有方法的签名

发送文字邮件

文字邮件的方法与发送html的方法类似,不过更加的简单

mail.sendHtml("收件人","邮件标题","邮件内容");

携带附件的文本邮件

Map<String,String> map = new HashMap<String,String>();
map.put("发送后显示的文件名","文件的路径")
mail.sendHtml("收件人","邮件标题","邮件内容",map);

API详解

所有重载方法的签名如下
这些方法都来自于 org.dromara.email.api包下的MailClient接口,方法上都有相应的javaDoc注释,可以翻阅java文档来获取具体的适用方法


    /**
     *  sendMail
     * <p> 发送纯文本邮件
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param body 邮件正文
     * @author :Wind
    */
    void sendMail(String mailAddress, String title ,String body);

    /**
     *  sendMail
     * <p> 群体发送纯文本邮件
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param body 邮件正文
     * @author :Wind
    */
    void sendMail(List<String> mailAddress ,String title ,String body);

    /**
     *  sendEmail
     * <p>发送带有附件的文本邮件
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param body 邮件正文
     * @param files 附件,可添加多个
     * @author :Wind
    */
    void sendEmail(String mailAddress, String title, String body,Map<String,String> files);

    /**
     *  sendEmail
     * <p>发送带有附件的文本邮件
     * @param mailAddress 收件人地址 多个收件人地址请按英文','字符隔开
     * @param title 邮件标题
     * @param body 邮件正文
     * @param zipName 压缩包名称 比如 附件.zip
     * @param files 附件,可添加多个
     * @author :Wind
     */
    void sendEmail(String mailAddress, String title, String body, String zipName, Map<String,String> files);

    /**
     *  sendEmail
     * <p>群体发送带有附件的文本邮件
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param body 邮件正文
     * @param files 附件,可添加多个
     * @author :Wind
     */
    void sendEmail(List<String> mailAddress, String title, String body, Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,无正文
     * <p> 将默认读取resources/template下的html文件,第三个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param htmlName 邮件正文
     * @param parameter key为模板的变量名称 无需携带大括号  value为模板变量所对应的值
     * @author :Wind
    */
    void sendHtml(String mailAddress, String title , String htmlName, Map<String,String> parameter);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,无正文
     * <p> 将默认读取resources/template下的html文件,第三个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param htmlName 邮件正文
     * @param parameter key为模板的变量名称 无需携带大括号  value为模板变量所对应的值
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title , String htmlName, Map<String,String> parameter);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,无正文
     * <p> 将默认读取resources/template下的html文件,第三个参数为html的名称,需携带尾缀
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param htmlName 邮件模板名称
     * @param parameter 实体
     * @author :Wind
     */
    void sendHtml(String mailAddress, String title , String htmlName, Parameter parameter);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,无正文
     * <p> 将默认读取resources/template下的html文件,第三个参数为html的名称,需携带尾缀
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param htmlName 邮件模板名称
     * @param parameter 实体
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title , String htmlName, Parameter parameter);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,无正文,带附件
     * <p> 将默认读取resources/template下的html文件,第三个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param htmlName 邮件模板名称
     * @param parameter 实体
     * @param files 附件,可添加多个
     * @author :Wind
     */
    void sendHtml(String mailAddress, String title , String htmlName,Map<String,String> parameter,Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,无正文,带附件
     * <p> 将默认读取resources/template下的html文件,第三个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param htmlName 邮件模板名称
     * @param parameter 实体
     * @param files 附件,可添加多个
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title , String htmlName,Map<String,String> parameter,Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,无正文,带附件
     * <p> 将默认读取resources/template下的html文件,第三个参数为html的名称,需携带尾缀
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param htmlName 邮件模板名称
     * @param parameter 实体
     * @param files 附件,可添加多个
     * @author :Wind
     */
    void sendHtml(String mailAddress, String title , String htmlName,Parameter parameter,Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,无正文,带附件
     * <p> 将默认读取resources/template下的html文件,第三个参数为html的名称,需携带尾缀
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param htmlName 邮件模板名称
     * @param parameter 实体
     * @param files 附件,可添加多个
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title , String htmlName,Parameter parameter,Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param htmlName 邮件正文
     * @param parameter key为模板的变量名称 无需携带大括号  value为模板变量所对应的值
     * @author :Wind
     */
    void sendHtml(String mailAddress, String title ,String body, String htmlName, Map<String,String> parameter);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param htmlName 邮件正文
     * @param parameter key为模板的变量名称 无需携带大括号  value为模板变量所对应的值
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title ,String body, String htmlName, Map<String,String> parameter);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param htmlName 邮件正文
     * @param parameter 实体
     * @author :Wind
     */
    void sendHtml(String mailAddress, String title ,String body, String htmlName, Parameter parameter);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param htmlName 邮件正文
     * @param parameter 实体
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title ,String body, String htmlName, Parameter parameter);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文和附件
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param htmlName 邮件正文
     * @param parameter key为模板的变量名称 无需携带大括号  value为模板变量所对应的值
     * @param files 附件,可添加多个 key 为文件名,value为文件的路径
     * @author :Wind
     */
    void sendHtml(String mailAddress, String title ,String body, String htmlName, Map<String,String> parameter,Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文和附件
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址 多个收件人地址请按英文','字符隔开
     * @param title 邮件标题
     * @param body 邮件文本正文 可为空
     * @param htmlName 邮件正文
     * @param parameter key为模板的变量名称 无需携带大括号  value为模板变量所对应的值
     * @param zipName 压缩包名称 比如 附件.zip
     * @param files 附件,可添加多个 key 为文件名,value为文件的路径
     * @author :bleachtred
     */
    void sendHtml(String mailAddress, String title, String body, String htmlName, Map<String,String> parameter, String zipName, Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文和附件
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址 多个收件人地址请按英文','字符隔开
     * @param title 邮件标题
     * @param body 邮件文本正文 可为空
     * @param htmlName 邮件正文
     * @param parameter 字段名称为变量名称,字段值为变量值
     * @param zipName 压缩包名称 比如 附件.zip
     * @param files 附件,可添加多个 key 为文件名,value为文件的路径
     * @author :Wind
     */
    void sendHtml(String mailAddress, String title, String body, String htmlName, Parameter parameter, String zipName, Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文和附件
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param htmlName 邮件正文
     * @param parameter key为模板的变量名称 无需携带大括号  value为模板变量所对应的值
     * @param files 附件,可添加多个 key 为文件名,value为文件的路径
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title ,String body, String htmlName, Map<String,String> parameter,Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文和附件
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param htmlName 邮件正文
     * @param parameter 字段名称为变量名称,字段值为变量值
     * @param files 附件,可添加多个 key 为文件名,value为文件的路径
     * @author :Wind
     */
    void sendHtml(String mailAddress, String title ,String body, String htmlName, Parameter parameter,Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文和附件
     * <p> 将默认读取resources/template下的html文件,第四个参数为html的名称,需携带尾缀
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param htmlName 邮件正文
     * @param parameter 字段名称为变量名称,字段值为变量值
     * @param files 附件,可添加多个 key 为文件名,value为文件的路径
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title ,String body, String htmlName, Parameter parameter,Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文和附件
     * <p> 从用户给定的输入流获取html模板文件
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param html html模板的输入流,这个流可以来自任何来源,例如网络请求,或是本地文件,或者对象存储等
     * @param parameter key为模板的变量名称 无需携带大括号  value为模板变量所对应的值
     * @param files 附件,可添加多个 key 为文件名,value为文件的路径
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title , String body, InputStream html, Map<String, String> parameter, Map<String,String> files);

    /**
     *  sendHtml
     * <p> 读取模板发送html邮件,并携带正文和附件
     * <p> 从用户给定的输入流获取html模板文件
     * <p> 用户可以自己编写一个实体类,并实现Parameter接口,编写get和set方法,这样一来字段的名称则为模板变量名称,对象的值则为模板变量的值
     * @param mailAddress 收件人地址,添加多个
     * @param title 邮件标题
     * @param body 邮件文本正文
     * @param html html模板的输入流,这个流可以来自任何来源,例如网络请求,或是本地文件,或者对象存储等
     * @param parameter 字段名称为变量名称,字段值为变量值
     * @param files 附件,可添加多个 key 为文件名,value为文件的路径
     * @author :Wind
     */
    void sendHtml(List<String> mailAddress, String title ,String body, InputStream html, Parameter parameter,Map<String,String> files);

小技巧

在使用中,如果我们不经常更改配置信息,并且配置信息很少的情况下,我们可以将工厂构建出来的 MailClient 对象交给容器托管(例如spring或者solon)
spring示例:

@Configuration
public class MailConfig{
    @Bean("qqMailClient")
    public MailClient qqMailClient(){
        //以下仅做演示,实际使用需要填入数据
        MailSmtpConfig config = MailSmtpConfig.builder.build;
        //这里的key可以是任何可对比类型,用于后续从工厂取出邮件实现类用
        MailFactory.put("qq",config);
        return  MailFactory.createMailClient("qq");
    }
}

solon示例:

@Configuration
public class MailConfig{
    @Bean
    public MailClient qqMailClient(){
        //以下仅做演示,实际使用需要填入数据
        MailSmtpConfig config = MailSmtpConfig.builder.build;
        //这里的key可以是任何可对比类型,用于后续从工厂取出邮件实现类用
        MailFactory.put("qq",config);
        return  MailFactory.createMailClient("qq");
    }
}