SpringBoot+RabbitMQ實現郵箱服務

由於我有兩個項目,每個項目都需要用到郵件,所以把郵件拆分出來做成了一個單獨的郵件服務,也方便以後的項目直接調用。

也就是現在有三個服務,服務A接收其他服務發送的消息,這個消息中會包含三個基本的信息,郵件標題、郵件內容、接收者的郵件號。服務B、C發送包含這三個信息的消息到服務A中,服務A拿到信息後最終發送郵件。
在這裏插入圖片描述

一、安裝RabbitMQ

我的系統是Linux(Deepin),Windows的就不演示了,只需要以下三條命令。

RabbitMq需要erlang語言的支持,在安裝RabbitMq之前需要安裝erlang。

apt-get install erlang-nox

接着安裝RabbitMQ

apt-get install rabbitmq-server

如果需要Web端可視化操作界面,還需要配置Management Plugin插件。

rabbitmq-plugins enable rabbitmq_management

安裝成功後輸入地址http://127.0.0.1:15672/進行登錄,默認賬號密碼都爲guest。

賬號和密碼可以到Web控制檯去添加,也可以用RabbitMq的命令添加(rabbitmqctl add_user 用戶名 密碼)。如果RabbitMq在雲服務器上,除了要開放端口,還要開啓遠程訪問功能,處於安全的考慮,guest這個默認的用戶只能通過http://localhost:15672 來登錄,其他的IP無法直接使用這個賬號。
在這裏插入圖片描述
在這裏插入圖片描述

二、獲取郵箱授權碼

這裏演示獲取QQ郵箱的授權碼,163大致也一樣,不過經測試,發現在使用163發送大量郵件後,過段時間再次發送就會都被標爲垃圾郵件,系統拒絕發送。這裏可能是我內容的原因(恩…所有內容大致都一樣,只是個別話不同),但使用QQ時只是偶爾發不出去。

登錄QQ郵箱後,點擊設置—賬號。
在這裏插入圖片描述
然後開啓POP3/SMTP服務,默認是關閉的。
在這裏插入圖片描述
點擊下面生成授權碼,在發送短信校驗後會給你一串字符,要保存好。
在這裏插入圖片描述

三、Spring Boot配置郵箱和RabbitMq

首先添加依賴

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-mail</artifactId>
     <version>2.1.6.RELEASE</version>
 </dependency>
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-amqp</artifactId>
     <version>2.2.6.RELEASE</version>
 </dependency>

在配置application.properties。
spring.mail.username是你的郵箱號,spring.mail.password爲上面生成的授權碼。這裏如果要用163,需要把host改成smtp.163.com。

spring.mail.host=smtp.qq.com
spring.mail.username=XXXXXXX@qq.com
spring.mail.password=上面生成的授權碼
spring.mail.port=465
spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.imap.ssl.socketFactory.fallback=false
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

RabbitMq配置,host爲主機地址。最下面設置的消息接收確認模式,這裏設置的手動確認。

spring.rabbitmq.host=ip地址
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

spring.rabbitmq.listener.simple.acknowledge-mode=manual

四、接收其他服務發送的消息

首先定義一個消息實體,其他服務自然也要發送這個實體到消息接受者上。

public class EmailInfo implements Serializable {
    private static final long serialVersionUID=1L;
    /**
     * 消息標題
     */
    private String title;
    /**
     * 消息內容
     */
    private String msg;
    /**
     * 接收者的郵箱號列表
     */
    private List<String> sendTo;
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public List<String> getSendTo() {
        return sendTo;
    }
    public void setSendTo(List<String> sendTo) {
        this.sendTo = sendTo;
    }
    public EmailInfo(String title, String msg, List<String> sendTo) {
        this.title = title;
        this.msg = msg;
        this.sendTo = sendTo;
    }
    public EmailInfo() {
    }
    @Override
    public String toString() {
        return "EmailInfo{" +
                "title='" + title + '\'' +
                ", msg='" + msg + '\'' +
                ", sendTo='" + sendTo + '\'' +
                '}';
    }
}

下面是消息接收。@RabbitListener註解可以直接創建交換器、隊列、路由建,並且綁定。當這個隊列中有消息時,會直接到process方法中處理,至於交換器和隊列等概念在以後的文章中介紹或者自行學習, 使用 @Payload 和 @Headers 註解可以拿到消息中 body和headers 信息,也可以使用@Header獲取單個 Header 屬性,channel.basicAck方法爲手動確認接收消息。

@Component
public class EmailReceiver {
    @Autowired
    JavaMailSender javaMailSender;
    @RabbitHandler
    @RabbitListener(
            bindings = @QueueBinding(
            value = @Queue(value = "email-queue",durable = "true"),
            exchange = @Exchange(name = "email-exchange",durable = "true",type = "topic"),
            key = "email.*"
    ))
    public void process(@Payload EmailInfo emailInfo,
                        @Headers Map<String,Object> header, Channel channel)  {
        Long tag =(Long) header.get(AmqpHeaders.DELIVERY_TAG);
        try {
            sendEmail(emailInfo);
            channel.basicAck(tag,false);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void sendEmail(EmailInfo info){
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom("郵箱號");
            java.lang.String[] strings = info.getSendTo().toArray(new String[]{});
            message.setTo(strings);
            message.setSubject(info.getTitle());
            message.setText(info.getMsg());
            javaMailSender.send(message);
        }catch (Exception e){
            System.out.println("發送失敗"+e.getMessage());
        }
    }
}

五、其他服務投遞消息

在其他服務中同樣需要添加依賴,並且在application.properties配置RabbitMq,可參考上面。

發送消息就比較簡單了,如下。

@Autowired
private AmqpTemplate amqpTemplate;
public  void sendMail(String title,String msg,List<String> info){
    EmailInfo emailInfo = new EmailInfo(title, msg, info);
    amqpTemplate.convertAndSend("email-exchange","email.send",emailInfo);
}

六、測試

@RestController
public class RabbitContriller {
    @Autowired
    private AmqpTemplate amqpTemplate;
    public  void sendMail(String title,String msg,List<String> info){
        EmailInfo emailInfo = new EmailInfo(title, msg, info);
        amqpTemplate.convertAndSend("email-exchange","email.send",emailInfo);
    }
    @GetMapping("sendMq")
    public String send(){
        String context = "簡單消息發送";
        EmailInfo emailInfo = new EmailInfo("標題", context, Arrays.asList("[email protected]"));
        amqpTemplate.convertAndSend("email-exchange","email.send",emailInfo);
        return "發送成功";
    }
}

訪問這個地址後,不出意外,會收到此郵件。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章