diff --git a/src/main/java/org/justjava/gymcore/config/smtp/AbstractSmtpConfig.java b/src/main/java/org/justjava/gymcore/config/smtp/AbstractSmtpConfig.java new file mode 100644 index 0000000..046a72a --- /dev/null +++ b/src/main/java/org/justjava/gymcore/config/smtp/AbstractSmtpConfig.java @@ -0,0 +1,58 @@ +package org.justjava.gymcore.config.smtp; + +public abstract class AbstractSmtpConfig { + private String host; + private String port; + private String username; //use with encryption + private String password; //use with encryption + private String auth; + private String starttls; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getAuth() { + return auth; + } + + public void setAuth(String auth) { + this.auth = auth; + } + + public String getStarttls() { + return starttls; + } + + public void setStarttls(String starttls) { + this.starttls = starttls; + } +} diff --git a/src/main/java/org/justjava/gymcore/config/smtp/GoogleSmtpConfig.java b/src/main/java/org/justjava/gymcore/config/smtp/GoogleSmtpConfig.java new file mode 100644 index 0000000..e3b58fa --- /dev/null +++ b/src/main/java/org/justjava/gymcore/config/smtp/GoogleSmtpConfig.java @@ -0,0 +1,9 @@ +package org.justjava.gymcore.config.smtp; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "smtp.google") +public class GoogleSmtpConfig extends AbstractSmtpConfig { +} diff --git a/src/main/java/org/justjava/gymcore/controller/MailController.java b/src/main/java/org/justjava/gymcore/controller/MailController.java new file mode 100644 index 0000000..09f9780 --- /dev/null +++ b/src/main/java/org/justjava/gymcore/controller/MailController.java @@ -0,0 +1,35 @@ +package org.justjava.gymcore.controller; + +import jakarta.mail.MessagingException; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Email; +import lombok.RequiredArgsConstructor; +import org.justjava.gymcore.model.MailModel; +import org.justjava.gymcore.service.MailService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping(value = "/mail") +@RequiredArgsConstructor +public class MailController { + + private final MailService mailService; + + @PostMapping("/sendMail/{to}") + public ResponseEntity sendMail( @PathVariable("to") + @Email(message = "Invalid email address format") + String to, + @Valid @RequestBody MailModel mailModel) { + try { + mailService.sendMail(to, mailModel.subject(), mailModel.body()); + return ResponseEntity.ok() + .body("Email sent successfully to: " + to); + } catch (MessagingException e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("Failed to send email: " + e.getMessage()); + } + } + +} diff --git a/src/main/java/org/justjava/gymcore/model/MailModel.java b/src/main/java/org/justjava/gymcore/model/MailModel.java new file mode 100644 index 0000000..cd83d54 --- /dev/null +++ b/src/main/java/org/justjava/gymcore/model/MailModel.java @@ -0,0 +1,15 @@ +package org.justjava.gymcore.model; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public record MailModel( + @NotBlank(message = "Email subject cannot be blank") + @Size(max = 998, message = "Email subject cannot exceed 998 characters") + String subject, + + @NotBlank(message = "Email body cannot be blank") + @Size(max = 50000, message = "Email body cannot exceed 50KB") + String body +) { +} diff --git a/src/main/java/org/justjava/gymcore/service/MailService.java b/src/main/java/org/justjava/gymcore/service/MailService.java new file mode 100644 index 0000000..eb300f8 --- /dev/null +++ b/src/main/java/org/justjava/gymcore/service/MailService.java @@ -0,0 +1,47 @@ +package org.justjava.gymcore.service; + +import jakarta.mail.*; +import jakarta.mail.internet.InternetAddress; +import jakarta.mail.internet.MimeMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.justjava.gymcore.config.smtp.GoogleSmtpConfig; +import org.springframework.stereotype.Service; + +import java.util.Properties; + +@Slf4j +@Service +@RequiredArgsConstructor +public class MailService { + + private final GoogleSmtpConfig googleSmtpConfig; + + // Host, Host e-mail, password and port will be provided under yaml file. If you want to get configurations from yaml file use smtpConfigurationService. + public void sendMail(String to, String subject, String body) throws MessagingException { + + Properties props = new Properties(); + props.put("mail.transport.protocol", "smtp"); + props.put("mail.smtp.host", googleSmtpConfig.getHost()); + props.put("mail.smtp.auth", googleSmtpConfig.getAuth()); + props.put("mail.smtp.port", googleSmtpConfig.getPort()); + props.put("mail.smtp.starttls.enable", googleSmtpConfig.getStarttls()); + + + Authenticator authenticator = new Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(googleSmtpConfig.getUsername(), googleSmtpConfig.getPassword()); + } + }; + + Session session = Session.getInstance(props, authenticator); + Message message = new MimeMessage(session); + message.setFrom(new InternetAddress(googleSmtpConfig.getUsername())); + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false)); + message.setSubject(subject); + message.setText(body); + + Transport.send(message); + log.info("Email sent successfully to: {}", to); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6e95269..3ae7937 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -24,3 +24,16 @@ logging.file.name=gymcore.log logging.appender.type=FILE logging.level.root=INFO logging.level.org.justjava.gymcore=INFO + +#Google SMTP configurations +smtp.google.host: smtp.gmail.com +smtp.google.port: 587 +# smtp.google.username: ${SMTP_USERNAME:your-email@gmail.com} +# smtp.google.password: ${SMTP_PASSWORD:your-app-password} +smtp.google.auth: true +smtp.google.starttls: true + +# Security Note: +# 1. Use environment variables for credentials in production +# 2. For Gmail, use App Passwords instead of regular passwords +# 3. Enable 2FA on your Google account before generating App Passwords