Skip to content

Commit

Permalink
Merge pull request #38 from jkuznik/Task-34-Async-Mail-Sending
Browse files Browse the repository at this point in the history
Task 34 async mail sending
  • Loading branch information
jkuznik authored Nov 14, 2024
2 parents 7aaf019 + 29a1ed5 commit fc8ae58
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 6 deletions.
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/pl/ateam/disasteralerts/_config/EmailConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package pl.ateam.disasteralerts._config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.scheduling.annotation.EnableAsync;

import java.util.Properties;

@EnableAsync
@EnableRetry
@Configuration
public class EmailConfig {

@Value("${spring.mail.username}")
String username;

@Value("${spring.mail.password}")
String password;

@Bean
public JavaMailSender javaMailSender() {

JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("smtp.gmail.com");
mailSender.setPort(587);

mailSender.setUsername(username);
mailSender.setPassword(password);

Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");

return mailSender;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ void sendNotifications(AlertAddDTO alertAddDTO) {
Set<UserDTO> interestedUsers = userFacade.getInterestedUsers(alertAddDTO.location());

notificationManager.addEmailService();
// notificationManager.addSMSService(); //TODO: temporary mute after test functionality
// notificationManager.addSMSService(); //TODO: after test functionality temporary mute and TODO: add logic for handling dynamic user preference changes
notificationManager.createAlert(alertAddDTO, interestedUsers);

notificationManager.removeEmailService();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,63 @@
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import org.eclipse.angus.mail.smtp.SMTPSenderFailedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import pl.ateam.disasteralerts.disasteralert.dto.AlertAddDTO;
import pl.ateam.disasteralerts.user.dto.UserDTO;

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
@RequiredArgsConstructor
class EmailService implements AlertListener{
class EmailService implements AlertListener {

private static final Logger logger = LoggerFactory.getLogger(EmailService.class);

private final JavaMailSender mailSender;

@Override
public void addedAlert(AlertAddDTO alertAddDTO, Set<UserDTO> interestedUsers) {
ExecutorService executor = Executors.newFixedThreadPool(3);

interestedUsers.forEach(interestedUser -> {
sendEmail(interestedUser.email(),"Alert", alertAddDTO.description());
executor.submit(() -> {
try {
sendEmail(interestedUser.email(), "Alert for " + alertAddDTO.location(), alertAddDTO.description());
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
});

executor.shutdown();
}

@Recover
public String handleMessagingException(MessagingException e) {
logger.error("Max attempts reached. Failed to send email after 4 attempts.");
logger.error("Error message: {}", e.getMessage());

return "Max attempts reached. Failed to send email";
}

@Retryable(
retryFor = SMTPSenderFailedException.class,
maxAttempts = 4,
backoff = @Backoff(delay = 3000)
)
public void sendEmail(String recipient, String subject, String content) {
try {
MimeMessage message = mailSender.createMimeMessage();
Expand All @@ -40,6 +69,9 @@ public void sendEmail(String recipient, String subject, String content) {
helper.setText(content, true);

mailSender.send(message);

logger.info("Email sent to " + recipient + " with subject " + subject + " and content " + content);

} catch (MessagingException e) {
logger.error("Error creating email message: {}", e.getMessage());
throw new RuntimeException("Problem with creating the message", e);
Expand Down
8 changes: 5 additions & 3 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ spring:
port: 587
username: [email protected]
password: ihrbtliplvclxosl
# username: ${DISASTER_EMAIL_ACCOUNT}
# password: ${DISASTER_EMAIL_PASSWORD}
properties:
mail:
smtp:
Expand All @@ -19,6 +21,6 @@ spring:
enable: true
ssl:
trust: smtp.gmail.com
connectiontimeout: 5000
timeout: 5000
writetimeout: 5000
connectiontimeout: 10000
timeout: 10000
writetimeout: 10000

0 comments on commit fc8ae58

Please sign in to comment.