发送邮件

目录

发送简单文本邮件

发送HTML文件的邮件

发送带附件的邮件

基于Freemarker发送带HTML模板的邮件

多线程Executors群发邮件


案例:员工入职-发送短信和邮件告知相关信息;企业发放Offer;

     用户注册发送用于激活账号的链接;OA系统不同人员协同工作途径....

核心步骤:申请用于发送邮件的"主题邮箱"(一般企业都会 有一个主体邮箱)  在qq邮箱的账户里开启SMTP服务,然后再生成授权码即可。

加入起步依赖

 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-mail</artifactId>
      <version>${mail.version}</version>
 </dependency>

在 application.properties中配置

#邮件配置
spring.mail.host=smtp.qq.com
spring.mail.username=xxx
spring.mail.password=xxx
#hbvrvyvkpiqpjdaa
#保证一些内容安全性的加密
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
mail.send.from=xxxx

先写前端的请求类:MailRequest.java

@Data
public class MailRequest implements Serializable {
    @NotBlank(message = "邮箱主题不能为空")
    private String subject;
    @NotBlank(message = "邮箱内容不能为空")
    private String content;
    @NotBlank(message = "接收人不能为空")
    private String tos;

}

发送简单文本邮件

Service层

@Service
public class MailService {
    private static  final Logger log = LoggerFactory.getLogger(MailService.class);
    @Autowired
    private JavaMailSender mailSender;
    @Autowired
    private Environment env;

    //发送简单文本文件
    public void sendSimpleTextMail(MailDto mailDto){
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(env.getProperty("mail.send.from"));
        message.setTo(mailDto.getTos());
        message.setSubject(mailDto.getSubject());
        message.setText(mailDto.getContent());

        mailSender.send(message);
        log.info("----发送简单文本邮件成功----");

    }
}

Controller层

//发送邮件controller
@RestController
@RequestMapping("mail")
public class MailController extends AbstractController{

    @Autowired
    private MailService mailService;

    //发送简单文本文件
    @RequestMapping(value = "simple", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public BaseResponse simpleTextMail(@RequestBody @Validated MailRequest mailRequest, BindingResult result){
        String checkRes = ValidatorUtil.checkResult(result);
        if(StringUtils.isNotBlank(checkRes)){
            return new BaseResponse(StatusCode.InvalidParam.getCode(), checkRes);
        }
        BaseResponse response = new BaseResponse(StatusCode.Success);
        try{
            log.info("--发送邮件controller-发送简单文本文件:{}");
            MailDto mailDto = new MailDto();
            //复制的时候省略掉tos
            BeanUtils.copyProperties(mailRequest, mailDto, "tos");
            mailDto.setTos(StringUtils.split(mailRequest.getTos(), ","));
            mailService.sendSimpleTextMail(mailDto);
        }catch (Exception e){
            response = new BaseResponse(StatusCode.Fail);
        }
        return response;
    }
}

结果

发送HTML文件的邮件

内容:其实就是邮件的内容带上了HTML文本的标签,让邮件看起来更好看!

Service层

    //发送HTML文本文件
    public void sendHtmlMail(MailDto mailDto) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        //利用MimeMessageHelper对message进行加工
        //multipart:表示是否是富文本
        MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "utf-8");
        messageHelper.setFrom(env.getProperty("mail.send.from"));
        messageHelper.setTo(mailDto.getTos());
        messageHelper.setSubject(mailDto.getSubject());
        //html:设置为true
        messageHelper.setText(mailDto.getContent(), true);


        mailSender.send(message);
        log.info("----发送HTML文本邮件成功----");

    }

Controller层

    //发送HTML文本文件
    @RequestMapping(value = "html", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public BaseResponse htmlMail(@RequestBody @Validated MailRequest mailRequest, BindingResult result){
        String checkRes = ValidatorUtil.checkResult(result);
        if(StringUtils.isNotBlank(checkRes)){
            return new BaseResponse(StatusCode.InvalidParam.getCode(), checkRes);
        }
        BaseResponse response = new BaseResponse(StatusCode.Success);
        try{
            log.info("--发送邮件controller-发送HTML文本文件:{}", mailRequest);
            MailDto mailDto = new MailDto();
            //复制的时候省略掉tos
            BeanUtils.copyProperties(mailRequest, mailDto, "tos");
            mailDto.setTos(StringUtils.split(mailRequest.getTos(), ","));
            mailService.sendHtmlMail(mailDto);
        }catch (Exception e){
            response = new BaseResponse(StatusCode.Fail);
        }
        return response;
    }

运行结果 

发送带附件的邮件

内容:其实就是发送邮件的时候附带上文件而已!

application.properties-设置附件路径以及附件的名字

mail.send.attachment.one.name=图片1.jpg
mail.send.attachment.one.location=${mail.send.attachment.root.url}\\1.jpg

mail.send.attachment.two.name=图片2.png
mail.send.attachment.two.location=${mail.send.attachment.root.url}\\2.png

service-基本不变,额外调用了addAttachment()接口,如果文件名超过60的话会发生乱码问题,解决方案:直接初始化

    //发送带附件的邮件
    public void sendAppendixMail(MailDto mailDto) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        //利用MimeMessageHelper对message进行加工
        //multipart:表示是否是富文本
        MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "utf-8");
        messageHelper.setFrom(env.getProperty("mail.send.from"));
        messageHelper.setTo(mailDto.getTos());
        messageHelper.setSubject(mailDto.getSubject());
        //html:设置为true
        messageHelper.setText(mailDto.getContent(), true);

        //TODO:在messageHelper里面加入附件
        messageHelper.addAttachment(env.getProperty("mail.send.attachment.one.name"), new File(env.getProperty("mail.send.attachment.one.location")));
        messageHelper.addAttachment(env.getProperty("mail.send.attachment.two.name"), new File(env.getProperty("mail.send.attachment.two.location")));
        //TODO:当附件的文件名长度大于60 || splitlongparameters=true的时候,会出现附件乱码等其他奇奇怪怪的现象
        //解决方案:在bean初始化后后添加一个init方法,设置对应的参数为falise

        mailSender.send(message);
        log.info("----发送带附件的邮件成功----");

    }
    //在系统启动后初始化相应的参数
    @PostConstruct
    public void init(){
        System.setProperty("mail.mime.splitlongparameters", "false");
    }

controller-没有任何变化

    //发送带附件的邮件
    @RequestMapping(value = "appendix", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public BaseResponse appendixMail(@RequestBody @Validated MailRequest mailRequest, BindingResult result){
        String checkRes = ValidatorUtil.checkResult(result);
        if(StringUtils.isNotBlank(checkRes)){
            return new BaseResponse(StatusCode.InvalidParam.getCode(), checkRes);
        }
        BaseResponse response = new BaseResponse(StatusCode.Success);
        try{
            log.info("--发送邮件controller-发送带有附件的邮件:{}", mailRequest);
            MailDto mailDto = new MailDto();
            //复制的时候省略掉tos
            BeanUtils.copyProperties(mailRequest, mailDto, "tos");
            mailDto.setTos(StringUtils.split(mailRequest.getTos(), ","));
            mailService.sendAppendixMail(mailDto);
        }catch (Exception e){
            response = new BaseResponse(StatusCode.Fail);
        }
        return response;
    }

基于Freemarker发送带HTML模板的邮件

内容:不管发送多少次,邮件的内容大部分的话术是一样的,针对这些共同的术语,我们可以将其抽取出来放到"HTML模板"中。而对于那些变化的部分,我们只需要往模板塞入"对应的取值"即可,比如接受人的邮箱等等!

freemarker模板 目录/ftl/mail.ftl

<p>你好, ${mailTos} &nbsp; 欢迎您!</p>
<p><strong style="...">希望在未来的日子里,能够和大家一块成长</strong> </p>

service

    //渲染模板
    public String renderTemplate(final  String templateFile, Map<String, Object> paramMap) throws Exception{
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_26);

        //TODO:设置ftl模板所在的根目录
        cfg.setClassForTemplateLoading(this.getClass(), "/ftl");

        Template template = cfg.getTemplate(templateFile);
        return FreeMarkerTemplateUtils.processTemplateIntoString(template, paramMap);
    }
    //发送带附件的邮件
    public void sendHTMLTemplateMail(MailDto mailDto) throws Exception {
        MimeMessage message = mailSender.createMimeMessage();
        //利用MimeMessageHelper对message进行加工
        //multipart:表示是否是富文本
        MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "utf-8");
        messageHelper.setFrom(env.getProperty("mail.send.from"));
        messageHelper.setTo(mailDto.getTos());
        messageHelper.setSubject(mailDto.getSubject());
        //html:设置为true

        //渲染模板,得到html邮件内容
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("mailTos", Arrays.toString(mailDto.getTos()));
        String content = this.renderTemplate(env.getProperty("mail.template.file.location"), dataMap);
        messageHelper.setText(content, true);
        mailSender.send(message);
        log.info("----发送带附件的邮件成功----");

    }

controller

    @RequestMapping(value = "html/template",method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public BaseResponse htmlTemplateMail(@RequestBody @Validated MailRequest mailRequest, BindingResult result){
        String checkRes = ValidatorUtil.checkResult(result);
        if(StringUtils.isNotBlank(checkRes)){
            return new BaseResponse(StatusCode.InvalidParam.getCode(), checkRes);
        }
        BaseResponse response = new BaseResponse(StatusCode.Success);
        try{
            log.info("--发送邮件controller-发送HTML模板的邮件:{}", mailRequest);
            MailDto mailDto = new MailDto();
            //复制的时候省略掉tos
            BeanUtils.copyProperties(mailRequest, mailDto, "tos");
            mailDto.setTos(StringUtils.split(mailRequest.getTos(), ","));
            mailService.sendHTMLTemplateMail(mailDto);
        }catch (Exception e){
            response = new BaseResponse(StatusCode.Fail);
        }
        return response;
    }

多线程Executors群发邮件

基于Executors-多线程群发邮件,减少单线程群发邮件的时间与压力!

案例:给所有有效用户推送一条"春节祝福语"或者"App重大版本更新消息"

新建一张user表

create table user(
	id int(11) not null auto_increment,
    name varchar(255) character set utf8mb4 default null comment "名字",
    code varchar(255) character set utf8mb4 default null comment "工号",
    email varchar(255) character set utf8mb4 default null comment "邮箱",
    is_active int(11) default 1,
    primary key(id)
)engine=InnoDB auto_increment=343587 default charset=utf8 comment="用户信息表";

select * from user;
insert into user(name, code, email) values ("aaa", "1234", "1577153977@qq.com");
insert into user(name, code, email) values ("bbb", "5678", "1784287593@163.com");
insert into user(name, code, email) values ("ccc", "5679", "1784287593@126.com");
insert into user(name, code, email) values ("ddd", "5", "1@qq.com");
insert into user(name, code, email) values ("eee", "6", "2@qq.com");
insert into user(name, code, email) values ("fff", "7", "3@qq.com");
insert into user(name, code, email) values ("ggg", "8", "4@qq.com");
insert into user(name, code, email) values ("hhh", "9", "5@qq.com");

通过逆向工程生成Userm UserMapper, UserMapper.xml

创建发送邮件的ThreadMailDto

//单个线程要做的任务-给邮箱发送邮件
public class ThreadMailDto implements Callable<Boolean> {
    private MailDto mailDto;
    private MailService mailService;

    public ThreadMailDto(MailDto mailDto, MailService mailService) {
        this.mailDto = mailDto;
        this.mailService = mailService;
    }
    //此处为每个线程实例执行的任务
    public Boolean call() throws Exception {
        mailService.sendHTMLTemplateMail(mailDto);
        return true;
    }
}

service层:创建线程池去实现

@Service
public class ThreadMailService  {

    private static final Logger log = LoggerFactory.getLogger(ThreadMailService.class);
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MailService mailService;
    //多线程群发邮件
    public void sendThreadsMail(final MailDto dto) throws Exception{
        Set<String> set = userMapper.selectAllMails();
        if(set != null && !set.isEmpty(s)) {
            //TODO:并发多线程实例
            ExecutorService executorService = Executors.newFixedThreadPool(10);

            List<ThreadMailDto> list = Lists.newLinkedList();
            //遍历set(邮箱集合)中的每个元素,构造成一个ThreadMailDto对象
            set.forEach(email -> {
                dto.setTos(new String[]{email});
                list.add(new ThreadMailDto(dto, mailService));
            });
            executorService.invokeAll(list);
        }
        log.info("......多线程群发邮件成功.......");
    }
}

Controller层

    //多线程群发邮件
    @RequestMapping(value = "threads",method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public BaseResponse threadsMail(@RequestBody @Validated MailRequest mailRequest, BindingResult result){
        String checkRes = ValidatorUtil.checkResult(result);
        if(StringUtils.isNotBlank(checkRes)){
            return new BaseResponse(StatusCode.InvalidParam.getCode(), checkRes);
        }
        BaseResponse response = new BaseResponse(StatusCode.Success);
        try{
            log.info("--发送邮件controller-多线程群发邮件:{}", mailRequest);
            MailDto mailDto = new MailDto();
            //复制的时候省略掉tos
            BeanUtils.copyProperties(mailRequest, mailDto, "tos");
            mailDto.setTos(StringUtils.split(mailRequest.getTos(), ","));
            threadMailService.sendThreadsMail(mailDto);

        }catch (Exception e){
            response = new BaseResponse(StatusCode.Fail);
        }
        return response;
    }

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值