美文网首页SpringBoot整合
SpringBoot整合RabbitMq实现邮件发送

SpringBoot整合RabbitMq实现邮件发送

作者: 永动的图灵机 | 来源:发表于2020-04-05 18:01 被阅读0次

    环境说明: Centos7, Docker1.13.1

    准备

    本篇以qq邮件为例

    邮箱配置

    • 开启SMTP服务(Simple Mail Transfer Protocol 简单邮件传输协议)

    • 获取授权码

    image

    依赖配置

    • 核心依赖
    <!--amqb 通信-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    <!--java mail-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    <!--thymeleaf-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    • yml的自动配置,注意这里要使用手动ack
    spring:
      # rabbitmq
      rabbitmq:
        host: 120.79.27.209
        username: root
        password: [password]
        virtual-host: /
        listener:
          simple:
            acknowledge-mode: manual
      # qq mail
      mail:
        host: smtp.qq.com
        username: 691409320@qq.com
        password: [授权码]
        default-encoding: utf-8
        port: 587
        properties:
          mail.smtp.auth: true
          mail.smtp.connectiontimeout: 5000
          mail.smtp.timeout: 5000
          mail.smtp.writetimeout: 5000
          mail.smtp.starttls.enabl: true
      # thymeleaf
      thymeleaf:
        cache: false
    

    功能开发

    以下模拟一个场景,用户提交注册信息后,将消息提交给队列,让后队列将发送邮件通知给用户

    邮件发送

    简单示例

    • 发送一个简单的文本内容的邮件
    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class MailApplicationTests {
    
        @Autowired
        private MailProperties mailProperties;
    
        @Autowired
        private JavaMailSender mailSender;
    
        @Test
        public void sendSampleMail() {
            // 简单邮件类
            SimpleMailMessage mailMessage = new SimpleMailMessage();
            // 寄件人,默认是配置的username
            mailMessage.setFrom(mailProperties.getUsername());
            // 收件人,支持多个收件人
            mailMessage.setTo("2633357327@qq.com");
            // 邮件主题
            mailMessage.setSubject("Test simple mail");
            // 邮件的文本信息
            mailMessage.setText("Hello this is test mail from java");
    
            // 发送邮件
            mailSender.send(mailMessage);
        }
    }    
    

    查看邮件

    image

    详细功能

    • 自定义邮件表单实体
    @Data
    @Accessors(chain = true)
    public class MailForm {
        // 寄件人
        private String from;
    
        // 收件人
        private List<String> to;
    
        // 主题
        private String subject;
    
        // 文本
        private String text;
    
        // 本地附件路径
        private List<String> attachmentPath;
    
        // 模板名
        private String templateName;
    
        // 模板变量
        private Map<String,Object> contextVar;
    }
    
    • 邮件发送服务接口
    public interface MailService {
        /**
         * 发送简单邮件
         * @param form
         */
        void sendSimpleMail(MailForm form);
    
        /**
         * 发送html邮件
         * @param form
         */
        void sendHtmlMail(MailForm form);
    
        /**
         * 发送模板邮件
         * @param form
         */
        void sendTemplateMail(MailForm form);
    }
    
    • 实现类
    @Service
    @Slf4j
    public class MailServiceImpl implements MailService {
    
        @Autowired
        private JavaMailSender mailSender;
    
        @Autowired
        private MailProperties mailProperties;
    
        @Autowired
        private TemplateEngine templateEngine;
    
        @Override
        public void sendSimpleMail(MailForm form) {
            try {
                SimpleMailMessage mailMessage = new SimpleMailMessage();
                mailMessage.setFrom(mailProperties.getUsername());
                List<String> to = form.getTo();
                String[] toUsers = form.getTo().toArray(new String[to.size()]);
                mailMessage.setTo(toUsers);
                mailMessage.setSubject(form.getSubject());
                mailMessage.setText(form.getText());
    
                mailSender.send(mailMessage);
            } catch (Exception e) {
                log.error("邮件发送失败", e.getMessage());
                throw new CustomException(ResultCodeEnum.MAIL_SEND_FAILED);
            }
        }
    
        @Override
        public void sendHtmlMail(MailForm form) {
            try {
                MimeMessage mimeMessage = mailSender.createMimeMessage();
                MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
                messageHelper.setFrom(mailProperties.getUsername());
                List<String> to = form.getTo();
                String[] toUsers = form.getTo().toArray(new String[to.size()]);
                messageHelper.setTo(toUsers);
                messageHelper.setSubject(form.getSubject());
                messageHelper.setText(form.getText(), true);
    
                // 本地附件
                if (form.getAttachmentPath() != null) {
                    List<String> pathList = form.getAttachmentPath();
                    for (String attachmentPath : pathList) {
                        File file = new File(attachmentPath);
                        if (file.exists()) {
                            String fileName = file.getName();
                            FileSystemResource fsr = new FileSystemResource(file);
                            messageHelper.addAttachment(fileName, fsr);
                        }
                    }
                }
    
                mailSender.send(mimeMessage);
            } catch (Exception e) {
                log.error("邮件发送失败", e.getMessage());
                throw new CustomException(ResultCodeEnum.MAIL_SEND_FAILED);
            }
        }
    
        @Override
        public void sendTemplateMail(MailForm form) {
            try {
                Context context = new Context();
                context.setLocale(Locale.CHINA);
                context.setVariables(form.getContextVar());
                String templateMail = templateEngine.process(form.getTemplateName(), context);
                form.setText(templateMail);
                sendHtmlMail(form);
            } catch (Exception e) {
                log.error("邮件发送失败", e.getMessage());
                throw new CustomException(ResultCodeEnum.MAIL_SEND_FAILED);
            }
        }
    }
    

    RabbitMq配置

    如没有安装rabbitmq,可参考Docker安装RabbitMq

    • 配置队列
    @Configuration
    public class RabbitmqConfig {
    
        /** 邮件 **/
        @Bean
        public Queue mailQueue() {
            return new Queue(MAIL_REGISTER_QUEUE, true, false, false, null);
        }
    
        @Bean
        public Exchange mailExchange() {
            return new TopicExchange(MAIL_REGISTER_EXCHANGE, true, false, null);
        }
    
        @Bean
        public Binding orderBinding() {
            return new Binding(MAIL_REGISTER_QUEUE, Binding.DestinationType.QUEUE, MAIL_REGISTER_EXCHANGE,
                MAIL_REGISTER_ROUTING_KEY, null);
        }
    
        /** json输出 **/
        @Bean
        public MessageConverter messageConverter() {
            return new Jackson2JsonMessageConverter();
        }
    }
    
    • 注册功能控制器
    @RestController
    @RequestMapping("/api/v1/register")
    public class RegisterController {
    
        @Autowired
        RabbitTemplate rabbitTemplate;
    
        /**
         * 模拟注册,测试消息队列和邮件发送
         */
        @PostMapping
        public R mockRegister(@RequestBody UserForm form) {
            User user = new User();
            BeanUtils.copyProperties(form,user);
            user.setId(UUID.randomUUID().toString().replace("-","").toUpperCase());
    
            // 邮件通知
            rabbitTemplate.convertAndSend(MqConstant.MAIL_REGISTER_EXCHANGE,MqConstant.MAIL_REGISTER_ROUTING_KEY,form);
    
            // TODO 其他操作
    
            return R.ok().message("注册成功,注册信息将邮件通知");
        }
    }
    
    • 监听邮件
    @Service
    @Slf4j
    public class MailListenerService {
    
        @Autowired
        private MailService mailService;
    
        @RabbitListener(queues = MqConstant.MAIL_REGISTER_QUEUE)
        public void sendRegisterMail(Message message, Channel channel, UserForm form) throws IOException {
            log.info("为用户发送注册信息:[{}]", form.getUsername());
    
            try {
                MailForm mailForm = new MailForm();
                Map<String, Object> userMap = new HashMap<>();
                userMap.put("username", form.getUsername());
                userMap.put("password", form.getPassword());
                mailForm.setTo(Arrays.asList(form.getEmail())).setSubject("注册通知").setTemplateName("register")
                    .setContextVar(userMap);
                mailService.sendTemplateMail(mailForm);
    
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                log.info("邮件发送成功");
            } catch (IOException e) {
                log.error("邮件发送失败", e.getMessage());
                // 回复消息处理失败,并重新入队
                // channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                throw new CustomException(ResultCodeEnum.MAIL_SEND_FAILED);
            }
        }
    }
    
    • 开启RabbitMq @EnableRabbit

    测试

    使用postman测试

    image

    查看邮箱

    image

    详细过程,可参考源代码:github.com/chetwhy/clo…

    相关文章

      网友评论

        本文标题:SpringBoot整合RabbitMq实现邮件发送

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