如何在 spring web-flux 中发送电子邮件反应性

kal*_*mar 13 jakarta-mail spring-boot reactive-streams spring-webflux

我想在我的新 Spring 应用程序中保持完全的反应性。因此,我将 web-flux/ reactor 和 ReactiveRepository 与 MongoDB 一起使用。

您知道如何将 java-mail 反应式地集成到技术堆栈中吗?任何替代方案?

Gor*_*oro 5

为了发送电子邮件并且仍然是非阻塞的,您可以在另一个线程中运行有关发送电子邮件的代码。如果您使用 Spring WebFlux,则可以轻松完成此操作,只需将用于发送电子邮件的代码包装在Mono(Reactor 库发布器)的以下工厂方法中即可。

Mono.fromCallable()

或者

Mono.fromRunnable()

短代码

Mono.fromCallable(()-> sendEmail())
    .subscribe();
Run Code Online (Sandbox Code Playgroud)

其中sendEmail()是发送电子邮件的函数。

这也是文档中推荐的内容 - How Do I Wrap a Synchronous, Blocking Call?

长代码

以下是我在应用程序中使用的完整示例代码 -

    Mono.fromCallable(() -> {
            try {
                MimeMessageHelper helper = new MimeMessageHelper(sender.createMimeMessage());
                helper.setTo(to);
                helper.setSubject(subject);
                helper.setText(body);
                sender.send(helper.getMimeMessage());
                log.info("Email send successfully, subject {} , to {}", subject, to);
                return true;
            } catch (Exception e) {
                log.warn("Failed to send email with subject {}, due to {}",subject,e.getMessage(), e});
                return false;
            }

 )
.subscribe(result -> log.info("Mail sent {}", result));
Run Code Online (Sandbox Code Playgroud)

当它是反应式堆栈时,永远不要忘记订阅:D


Vla*_*gov -2

我找到了解决办法。它使用spring-boot-starter-data-mongodb-reactiveMailgun 或 SendGrid 等外部​​服务的 API。关键点是使用响应式 WebClient :

\n\n
    \n
  1. 构建 WebClient 实例(例如,使用 Sendgrid API):

    \n\n
    String endpoint = \xe2\x80\x9chttps://api.sendgrid.com/v3/\xe2\x80\x9c;\nString sendUri = endpoint + \xe2\x80\x9cmail/send\xe2\x80\x9d;\n\nWebClient client = WebClient.builder().filter(\xe2\x80\xa6).clientConnector(new ReactorClientHttpConnector(HttpClient.create())).baseUrl(endpoint).build()\n
    Run Code Online (Sandbox Code Playgroud)
  2. \n
  3. 实现响应对象:

    \n\n
    @Data\nclass Response implements Serializable {\n    private boolean status;\n    private String id;\n    private String message;\n}\n\n@Data\nclass NotificationStatusResponse implements Serializable {\n\n    private LocalDateTime timestamp;\n    private int status;\n    private String message;\n    private String traceId;\n    private String responseId;\n    private String providerResponseId;\n    private String providerResponseMessage;\n}\n
    Run Code Online (Sandbox Code Playgroud)
  4. \n
  5. 发送您的信息:

    \n\n
    public Mono<NotificationStatusResponse> send(NotificationMessage<EmailId> email) throws NotificationSendFailedException {\n\n    Mono<NotificationStatusResponse> response = null;\n    try {\n        MultiValueMap<String, Object> formMap = new LinkedMultiValueMap<>(); // email parameters here: from, to, subject, html etc.\n        response = client.post().uri(sendUri)\n        .header("Authorization", "Basic " + \xe2\x80\x9cyour credentials here\xe2\x80\x9d)\n        .contentType(MediaType.MULTIPART_FORM_DATA).syncBody(formMap).retrieve()\n        .bodyToMono(Response.class).map(this::getNotificationStatusResponse)\n        .doOnSuccess(message -> log.debug("sent email successfully"))\n        .doOnError((error -> log.error("email failed ", error)));\n    } catch (WebClientException webClientException) {\n        throw new NotificationSendFailedException("webClientException received", webClientException);\n    }\n    return response;\n\n    NotificationStatusResponse getNotificationStatusResponse(Response response) {\n        NotificationStatusResponse notificationStatusResponse = new NotificationStatusResponse();\n        notificationStatusResponse.setStatus(200);\n        notificationStatusResponse.setTimestamp(LocalDateTime.now());\n        notificationStatusResponse.setProviderResponseId(response.getId());\n        notificationStatusResponse.setProviderResponseMessage(response.getMessage());\n        return notificationStatusResponse;\n    }\n}\n
    Run Code Online (Sandbox Code Playgroud)
  6. \n
\n