programing

봄 웹 플럭스에서 반응형 전자 메일을 보내는 방법

instargram 2023. 7. 21. 20:33
반응형

봄 웹 플럭스에서 반응형 전자 메일을 보내는 방법

저는 새로운 스프링 애플리케이션 내에서 완전한 반응성을 유지하고 싶습니다.따라서 저는 MongoDB와 함께 Web-flux/reactive와 Reactive Repository를 사용합니다.

Java 메일을 기술 스택에 대응적으로 통합하는 방법을 알고 계십니까?대안은 없나요?

전자 메일을 보내고 차단하지 않는 경우 다른 스레드에서 전자 메일을 보내는 코드를 실행할 수 있습니다.Spring WebFlux를 사용하는 경우 이메일 전송 코드를 Mono(A 반응기 라이브러리 게시자)의 공장 방식으로 포장하여 쉽게 수행할 수 있습니다.

호출 가능()에서 모노

또는

Mono.fromRun.

단축 코드

Mono.fromCallable(()-> sendEmail())
    .subscribe();

여기서 sendEmail()은 전자 메일을 보내는 기능입니다.

이것은 문서에서도 권장되는 내용입니다. 동기식 차단 통화를 랩하는 방법은 무엇입니까?

롱 코드

아래는 제가 신청서에 사용하고 있는 완전한 샘플 코드입니다.

    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));

그리고 반응형 스택일 때는 구독하는 것을 잊지 마세요 :D.

저도 반응형 SMTP 클라이언트를 찾고 있었습니다.

그리고 간신히 찾았어요 ;)

여기 있습니다: https://github.com/HubSpot/NioSmtpClient

README에서:

Netty 기반 Java의 고성능 SMTP 클라이언트.이 클라이언트는 HubSpot에서 잘 테스트되고 많이 사용됩니다.

저는 이미 현지 환경에서 검증했고 정말 반응적입니다!그러나 완전한 기능을 사용합니다.Mono 또는 Flux 대신 Future를 사용하므로 수동으로 포장해야 합니다.

일반적으로 이 도서관은 좋아 보이지만 작가가 제공해준다면 더 좋을 것 같습니다.facadeSDK 사용을 단순화할 수 있습니다.(어쨌든 오픈 소스이므로 개선할 수 있습니다.)

다음은 사용 방법의 예입니다(codeStyle에 대해서는 신경쓰지 마십시오. 예를 위한 것입니다).

private static final String MESSAGE_DATA = "From: <sender@gmail.com\r\n" +
        "To: <recipient@gmail.com>\r\n" +
        "Subject: test mail\r\n\r\n" +
        "Hello stackOverFlow!";

public static void main(String[] args) {
    final SmtpSessionFactory smtpSessionFactory = createSmtpSessionFactory();

    final SmtpSessionConfig smtpSessionConfig = SmtpSessionConfig.builder().remoteAddress(InetSocketAddress.createUnresolved("smtp.gmail.com", 587)).build();
    Mono.fromFuture(smtpSessionFactory.connect(smtpSessionConfig))
            .flatMap(connection -> doInSession(connection, req(EHLO, "gmail.com")))
            .flatMap(connection -> Mono.fromFuture(connection.getSession().startTls()))
            .flatMap(connection -> Mono.fromFuture(connection.getSession().authLogin("sender@gmail.com", "SomeStrongPasswordLike123456")))
            .flatMap(connection -> doInSession(connection, req(MAIL, "FROM:<" + "sender@gmail.com" + ">")))
            .flatMap(connection -> doInSession(connection, req(RCPT, "TO:<" + "recipient@gmail.com" + ">")))
            .flatMap(connection -> doInSession(connection, req(DATA)))
            .map(connection -> connection.getSession()
                    .send(MessageContent.of(Unpooled.wrappedBuffer(MESSAGE_DATA.getBytes(StandardCharsets.UTF_8)))))
            .flatMap(Mono::fromFuture)
            .flatMap(connection -> doInSession(connection, req(QUIT)))
            .flatMap(connection -> Mono.fromFuture(connection.getSession().close()))
            .block();
}

private static SmtpSessionFactory createSmtpSessionFactory() {
    ThreadFactory threadFactory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("niosmtpclient-%d").build();
    final SmtpSessionFactoryConfig config = SmtpSessionFactoryConfig.builder()
            .eventLoopGroup(new NioEventLoopGroup(4, threadFactory))
            .executor(Executors.newCachedThreadPool(threadFactory))
            .build();
    return new SmtpSessionFactory(config);
}

private static Mono<SmtpClientResponse> doInSession(SmtpClientResponse connection, SmtpRequest request) {
    return Mono.fromFuture(connection.getSession().send(request));
}

private static SmtpRequest req(SmtpCommand command, CharSequence... arguments) {
    return new DefaultSmtpRequest(command, arguments);
}

작동 방식(일반):

  1. 세션 팩토리를 정의합니다(방법 참조).createSmtpSessionFactory)
  2. 서버와 대화(연결)를 엽니다.
  3. 우리는 TLS를 시작합니다.
  4. 자격 증명으로 인증을 수행합니다.
  5. 우리는 서버에 보낸 사람의 이메일 주소를 말합니다.
  6. 우리는 서버에 수신자의 이메일 주소를 말합니다.
  7. 데이터 전송 단계를 시작합니다.
  8. 우리는 데이터를 보냅니다(데이터는 어떤 패턴을 따라야 합니다)보낸 사람: ...받는 사람: ...제목: ....참조MESSAGE_DATA가변)
  9. 대화를 끝내고 있음을 서버에 알립니다.
  10. 폐회.

제가 찾은 유용한 비 멀티캐스트 SMTP 클라이언트는 https://vertx.io/docs/vertx-mail-client/java/ 뿐입니다.
심지어 스프링-웹플럭스와 몽고드-드라이버-리액티브 스트림과 통합하여 동일한 Netty EventLoopGroup을 공유하도록 했습니다.

Mono.create<MailResult> { sink ->
  mailClient.sendMail(email) { asyncResult ->
    if (asyncResult.succeeded()) {
      sink.success(asyncResult.result()
    } else {
      sink.error(asyncResult.cause()
    }
  }
}

마이크로소프트 그래프 api를 사용하고 마이크로소프트의 exrange 서버를 사용하여 이메일 https://learn.microsoft.com/en-us/graph/use-the-api 을 보내는 것은 어떻습니까?원래 질문에 대한 답변은 아니지만, 동일한 개념을 적용할 수 있는지 또는 이 API를 사용하여 비슷한 것을 가지고 있는 사람이 있는지 궁금합니다.

해결책을 찾았어요그것은 사용합니다.spring-boot-starter-data-mongodb-reactive그리고 Mailgun 또는 SendGrid와 같은 외부 서비스의 API. WebClient WebClient를 입니다.

  1. Web Client 인스턴스 빌드(예: Sendgrid API 사용):

    String endpoint = “https://api.sendgrid.com/v3/“;
    String sendUri = endpoint + “mail/send”;
    
    WebClient client = WebClient.builder().filter(…).clientConnector(new ReactorClientHttpConnector(HttpClient.create())).baseUrl(endpoint).build()
    
  2. 응답 개체 구현:

    @Data
    class Response implements Serializable {
        private boolean status;
        private String id;
        private String message;
    }
    
    @Data
    class NotificationStatusResponse implements Serializable {
    
        private LocalDateTime timestamp;
        private int status;
        private String message;
        private String traceId;
        private String responseId;
        private String providerResponseId;
        private String providerResponseMessage;
    }
    
  3. 메시지 보내기:

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

언급URL : https://stackoverflow.com/questions/51091893/how-to-send-email-reactive-in-spring-web-flux

반응형