java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot集成邮件服务

SpringBoot集成邮件服务的完整实现方案

作者:半夜修仙

本文详细讲解如何在Spring Boot项目中快速集成邮件发送功能,包括依赖引入、邮箱配置、工具类封装以及结合RabbitMQ实现异步发送,帮助开发者提升注册等业务场景的响应速度,避免阻塞主流程,需要的朋友可以参考下

1.引入邮箱依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

2.配置邮箱

spring:
  mail:
    host: smtp.qq.com
    username: 你的QQ邮箱@qq.com
    password: 你的授权码  #需要自己去邮箱内开启SMTP服务
    default-encoding: UTF-8
    port: 465
    protocol: smtp
    properties:
      mail:
        smtp:
          auth: true
          ssl:
            enable: true
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory

3.测试发送一封简单的邮件:

@Autowired
JavaMailSender javaMailSender;

@Test
public void test() throws Exception {
    // 创建一个邮件消息
    MimeMessage message = javaMailSender.createMimeMessage();
    // 创建 MimeMessageHelper
    MimeMessageHelper helper = new MimeMessageHelper(message, false);
    // 发件人邮箱和名称
    helper.setFrom("747692844@qq.com", "springdoc");
    // 收件人邮箱
    helper.setTo("admin@springboot.io");
    // 邮件标题
    helper.setSubject("Hello");
    // 邮件正文,第二个参数表示是否是HTML正文
    helper.setText("Hello <strong> World</strong>! ", true);
    // 发送
    javaMailSender.send(message);
}

实际代码-前置条件:

1.将邮件发送功能封装在一个公共类里,方便其他地方调用

package com.bite.common.utils;

import jakarta.mail.internet.MimeMessage;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;

import java.util.Optional;

public class Mail {
    private JavaMailSender javaMailSender;
    private MailProperties mailProperties;

    public Mail(JavaMailSender javaMailSender, MailProperties mailProperties) {
        this.javaMailSender = javaMailSender;
        this.mailProperties = this.mailProperties;
    }

    public void send(String to, String subject, String content) throws Exception {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false);
        //发件人名称
        String personal = Optional.ofNullable(mailProperties.getProperties().get("personal"))
                .orElse(mailProperties.getUsername());
        helper.setFrom(mailProperties.getUsername(), personal);
        helper.setTo(to);    //收件人
        helper.setSubject(subject);    //邮件主题
        helper.setText(content, true);

        javaMailSender.send(mimeMessage);
    }
}

2.写Spring 邮件配置类,哪个服务需要就写在哪个服务里,也可以提出来写在服务的公共类里

package com.bite.common.config;

import com.bite.common.utils.Mail;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;


@Configuration
public class MailConfig {
    @Bean
    @ConditionalOnProperty(prefix="spring.mail",name="username")
     //只有配置文件中存在spring.data.redis.host配置项时,
    // 才会把 Redis 工具类注册为 Bean 放入 Spring 容器;
    // 没配置该属性就不创建这个 Bean,防止未配置 Redis 时报错
    //如blog服务配置没有redis相关配置,所以该服务就不创建这个bean,而user服务则有这个redis配置,则创建这个Bean
    


public Mail mail(JavaMailSender javaMailSender, MailProperties mailProperties) {
        return new Mail(javaMailSender,mailProperties);

    }
}

例子展示:

某服务的注册业务(Service)代码:

@Override
    public Integer register(UserInfoRegisterRequest registerRequest) {
        //校验参数:
        checkUserInfo(registerRequest);
        //校验通过,才是用户注册,插入数据库
        UserInfo userInfo = BeanConvert.convertUserInfoByEncrypt(registerRequest);
        try{
            int result = userInfoMapper.insert(userInfo);
            if(result==1){
                //存储数据到redis中
                //若redis存储失败,会导致查询时查不到信息,那么就从数据库中去查询,所以此处的异常暂不处理
                redis.set(buildKey(userInfo.getUserName()), JsonUtil.toJson(userInfo),EXPIRE_TIME);

                //⭐注册成功主动推送用户数据到 RabbitMQ,交给消费者异步处理发邮件,不阻塞注册接口响应速度,这就是引入MQ的作用
                userInfo.setPassword("");
                rabbitTemplate.convertAndSend(Constants.USER_EXCHANGE_NAME,"",JsonUtil.toJson(userInfo));


                return userInfo.getId();
            }else{
                throw new BlogException("用户注册失败");
            }
        }catch (Exception e){
            log.error("用户注册失败,e:",e);
            throw new BlogException("用户注册失败");

        }

    }

通过这段代码主动推送用户数据到 RabbitMQ

(⭐)rabbitTemplate.convertAndSend(Constants.USER_EXCHANGE_NAME,"",JsonUtil.toJson(userInfo));

生产者

注册成功主动推送用户数据到 RabbitMQ,交给消费者异步处理发邮件,不阻塞注册接口响应速度

消费者

消费收到的用户数据并做出下一步操作,如:发送邮箱

package com.bite.user.listener;

import com.bite.common.constant.Constants;
import com.bite.common.utils.JsonUtil;
import com.bite.common.utils.Mail;
import com.bite.user.dataobject.UserInfo;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;


@Slf4j
@Component
public class UserQueueListener {
    //⭐
    @Autowired
    private Mail mail;
    
    //写法二(消费注解内直接声明交换机 / 队列 / 绑定,服务启动自动创建,无需额外配置类;缺点是 MQ 资源分散在各个监听类):
    @RabbitListener(bindings=@QueueBinding(
            value=@Queue(value=Constants.USER_QUEUE_NAME,durable="true"),
            exchange=@Exchange(value=Constants.USER_EXCHANGE_NAME,type= ExchangeTypes.FANOUT)
    ))
    public void handler(Message message, Channel channel) throws IOException {
        long deliveryTag=message.getMessageProperties().getDeliveryTag();
        try{
            String body = new String(message.getBody());
            log.info("收到用户信息,body:{}",body);
            //TODO 发送注册成功邮件
            UserInfo userInfo= JsonUtil.parseJson(body, UserInfo.class);
           //⭐发送邮箱
             mail.send(userInfo.getEmail(),"恭喜加入XM博客社区",buildContent(userInfo.getUserName()));
            


//确认
            channel.basicAck(deliveryTag,true);
        }catch(Exception e){
            //否定确认
            channel.basicNack(deliveryTag,true,true);
            log.error("邮件发送失败,e:",e);
        }
    }

//发送的邮箱内容
    private String buildContent(String userName){
        StringBuilder builder=new StringBuilder();
        builder.append("尊敬的").append(userName).append(",您好!").append("<br/>");
        builder.append("感谢您注册成为我们博客社区的一员!我们很高兴您加入我们的大家庭!<br/>");
        builder.append("您的注册信息如下:用户名: ").append(userName).append("<br/>");
        builder.append("为了您的账号安全,请妥善保管您的登录信息.如果使用过程中,遇到任何问题,欢迎联系我们的支持团队. XXXX@bXM.com <br/>");
        builder.append("再次感谢您的加入,我们期待看到您的精彩内容!<br/>")
                .append("最好的祝愿<br/>")
                .append("XM博客团队");

        return builder.toString();
    }
}

发送邮件前置条件:公共类里的:

①⭐把 Mail 工具类创建成Spring Bean,放进容器:

package com.bite.common.config;

import com.bite.common.utils.Mail;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;


@Configuration
public class MailConfig {
    @Bean
    @ConditionalOnProperty(prefix="spring.mail",name="username")
    public Mail mail(JavaMailSender javaMailSender, MailProperties mailProperties) {
        return new Mail(javaMailSender,mailProperties);

    }
}

②:⭐邮箱发送操作实现逻辑:

封装底层发邮件逻辑:创建邮件、设置发件人 / 收件人 / HTML 正文、调用发送 API。 提供对外暴露的方法:send(String to, String subject, String content)

package com.bite.common.utils;

import jakarta.mail.internet.MimeMessage;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;

import java.util.Optional;


public class Mail {
    private JavaMailSender javaMailSender;
    private MailProperties mailProperties;

    public Mail(JavaMailSender javaMailSender, MailProperties mailProperties) {
        this.javaMailSender = javaMailSender;
        this.mailProperties = mailProperties;
    }

    public void send(String to, String subject, String content) throws Exception {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false);
        //发件人名称
        String personal = Optional.ofNullable(mailProperties.getProperties().get("personal"))
                .orElse(mailProperties.getUsername());
        helper.setFrom(mailProperties.getUsername(), personal);
        helper.setTo(to);    //收件人
        helper.setSubject(subject);    //邮件主题
        helper.setText(content, true);

        javaMailSender.send(mimeMessage);
    }
}

三者关系:

@Autowired
private Mail mail;

以上就是SpringBoot集成邮件服务的完整实现方案的详细内容,更多关于SpringBoot集成邮件服务的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文