diff --git a/application/src/main/java/com/pablotj/restemailbridge/application/dto/EmailDTO.java b/application/src/main/java/com/pablotj/restemailbridge/application/dto/EmailDTO.java new file mode 100644 index 0000000..02e4026 --- /dev/null +++ b/application/src/main/java/com/pablotj/restemailbridge/application/dto/EmailDTO.java @@ -0,0 +1,8 @@ +package com.pablotj.restemailbridge.application.dto; + +public record EmailDTO( + String from, + String subject, + String body +) { +} diff --git a/application/src/main/java/com/pablotj/restemailbridge/application/port/EmailConfigurationPort.java b/application/src/main/java/com/pablotj/restemailbridge/application/port/EmailConfigurationPort.java new file mode 100644 index 0000000..b3dff6a --- /dev/null +++ b/application/src/main/java/com/pablotj/restemailbridge/application/port/EmailConfigurationPort.java @@ -0,0 +1,5 @@ +package com.pablotj.restemailbridge.application.port; + +public interface EmailConfigurationPort { + String getDefaultRecipient(); +} diff --git a/application/src/main/java/com/pablotj/restemailbridge/application/usecase/SendEmailUseCase.java b/application/src/main/java/com/pablotj/restemailbridge/application/usecase/SendEmailUseCase.java new file mode 100644 index 0000000..c98c574 --- /dev/null +++ b/application/src/main/java/com/pablotj/restemailbridge/application/usecase/SendEmailUseCase.java @@ -0,0 +1,32 @@ +package com.pablotj.restemailbridge.application.usecase; + +import com.pablotj.restemailbridge.application.dto.EmailDTO; +import com.pablotj.restemailbridge.application.port.EmailConfigurationPort; +import com.pablotj.restemailbridge.domain.model.Email; +import com.pablotj.restemailbridge.domain.repository.EmailRepository; +import com.pablotj.restemailbridge.domain.service.EmailService; + +public class SendEmailUseCase { + private final EmailConfigurationPort emailConfigurationPort; + private final EmailService emailService; + private final EmailRepository emailRepository; + + public SendEmailUseCase(EmailConfigurationPort emailConfigurationPort, EmailService emailService, EmailRepository emailRepository) { + this.emailConfigurationPort = emailConfigurationPort; + this.emailService = emailService; + this.emailRepository = emailRepository; + } + + public void handle(EmailDTO emailDTO) { + String to = emailConfigurationPort.getDefaultRecipient(); + Email email = emailService.sendEmail( + Email.builder() + .from(emailDTO.from()) + .to(to) + .subject(emailDTO.subject()) + .body(emailDTO.body()) + .build() + ); + emailRepository.save(email); + } +} diff --git a/bootstrap/src/main/java/com/pablotj/restemailbridge/bootstrap/RestEmailBridgeApplication.java b/bootstrap/src/main/java/com/pablotj/restemailbridge/bootstrap/RestEmailBridgeApplication.java index cadc539..e3953b8 100644 --- a/bootstrap/src/main/java/com/pablotj/restemailbridge/bootstrap/RestEmailBridgeApplication.java +++ b/bootstrap/src/main/java/com/pablotj/restemailbridge/bootstrap/RestEmailBridgeApplication.java @@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication(scanBasePackages = "com.pablotj.restemailbridge") -@EnableJpaRepositories(basePackages = {"com.pablotj.restemailbridge.infrastructure"}) -@EntityScan(basePackages = {"com.pablotj.restemailbridge.infrastructure"}) +@EnableJpaRepositories(basePackages = {"com.pablotj.restemailbridge"}) +@EntityScan(basePackages = {"com.pablotj.restemailbridge"}) public class RestEmailBridgeApplication { public static void main(String[] args) { diff --git a/domain/src/main/java/com/pablotj/restemailbridge/domain/model/Email.java b/domain/src/main/java/com/pablotj/restemailbridge/domain/model/Email.java new file mode 100644 index 0000000..ea590bd --- /dev/null +++ b/domain/src/main/java/com/pablotj/restemailbridge/domain/model/Email.java @@ -0,0 +1,15 @@ +package com.pablotj.restemailbridge.domain.model; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class Email { + + private String from; + private String to; + private String subject; + private String body; + +} diff --git a/domain/src/main/java/com/pablotj/restemailbridge/domain/repository/EmailRepository.java b/domain/src/main/java/com/pablotj/restemailbridge/domain/repository/EmailRepository.java new file mode 100644 index 0000000..4639bd3 --- /dev/null +++ b/domain/src/main/java/com/pablotj/restemailbridge/domain/repository/EmailRepository.java @@ -0,0 +1,8 @@ +package com.pablotj.restemailbridge.domain.repository; + +import com.pablotj.restemailbridge.domain.model.Email; + +public interface EmailRepository { + + Email save(Email email); +} diff --git a/domain/src/main/java/com/pablotj/restemailbridge/domain/service/EmailService.java b/domain/src/main/java/com/pablotj/restemailbridge/domain/service/EmailService.java new file mode 100644 index 0000000..c527615 --- /dev/null +++ b/domain/src/main/java/com/pablotj/restemailbridge/domain/service/EmailService.java @@ -0,0 +1,8 @@ +package com.pablotj.restemailbridge.domain.service; + +import com.pablotj.restemailbridge.domain.model.Email; + +public interface EmailService { + + Email sendEmail(Email email); +} diff --git a/infrastructure/pom.xml b/infrastructure/pom.xml index d397999..11e20aa 100644 --- a/infrastructure/pom.xml +++ b/infrastructure/pom.xml @@ -33,6 +33,12 @@ spring-boot-starter-validation + + org.reflections + reflections + 0.10.2 + + org.mapstruct diff --git a/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/config/EmailConfigurationAdapter.java b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/config/EmailConfigurationAdapter.java new file mode 100644 index 0000000..cff4675 --- /dev/null +++ b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/config/EmailConfigurationAdapter.java @@ -0,0 +1,12 @@ +package com.pablotj.restemailbridge.infrastructure.config; + +import com.pablotj.restemailbridge.application.port.EmailConfigurationPort; +import org.springframework.stereotype.Component; + +@Component +public class EmailConfigurationAdapter implements EmailConfigurationPort { + @Override + public String getDefaultRecipient() { + return "1234@1234.com"; + } +} \ No newline at end of file diff --git a/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/config/spring/UseCaseConfig.java b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/config/spring/UseCaseConfig.java new file mode 100644 index 0000000..7e4168a --- /dev/null +++ b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/config/spring/UseCaseConfig.java @@ -0,0 +1,17 @@ +package com.pablotj.restemailbridge.infrastructure.config.spring; + +import com.pablotj.restemailbridge.application.port.EmailConfigurationPort; +import com.pablotj.restemailbridge.application.usecase.SendEmailUseCase; +import com.pablotj.restemailbridge.domain.repository.EmailRepository; +import com.pablotj.restemailbridge.domain.service.EmailService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class UseCaseConfig { + + @Bean + public SendEmailUseCase sendEmailUseCase(EmailConfigurationPort emailConfigurationPort, EmailService emailService, EmailRepository emailRepository) { + return new SendEmailUseCase(emailConfigurationPort, emailService, emailRepository); + } +} \ No newline at end of file diff --git a/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/mail/GmailOAuth2MailService.java b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/mail/GmailOAuth2MailService.java new file mode 100644 index 0000000..5cb8221 --- /dev/null +++ b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/mail/GmailOAuth2MailService.java @@ -0,0 +1,15 @@ +package com.pablotj.restemailbridge.infrastructure.mail; + +import com.pablotj.restemailbridge.domain.model.Email; +import com.pablotj.restemailbridge.domain.service.EmailService; +import org.springframework.stereotype.Component; + +@Component +public class GmailOAuth2MailService implements EmailService { + + @Override + public Email sendEmail(Email email) { + System.out.println("Sending email " + email.getSubject() + " to " + email.getTo()); + return email; + } +} diff --git a/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/persistence/MailJpa.java b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/persistence/MailJpa.java new file mode 100644 index 0000000..9684e8d --- /dev/null +++ b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/persistence/MailJpa.java @@ -0,0 +1,33 @@ +package com.pablotj.restemailbridge.infrastructure.persistence; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Table(name = "MAIL") +@Getter +@Setter +public class MailJpa { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String sender; + + @Column(nullable = false) + private String recipient; + + @Column(nullable = false) + private String subjet; + + @Column(nullable = false) + private String body; +} diff --git a/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/persistence/MailRepositoryAdapter.java b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/persistence/MailRepositoryAdapter.java new file mode 100644 index 0000000..8acf59c --- /dev/null +++ b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/persistence/MailRepositoryAdapter.java @@ -0,0 +1,28 @@ +package com.pablotj.restemailbridge.infrastructure.persistence; + +import com.pablotj.restemailbridge.domain.model.Email; +import com.pablotj.restemailbridge.domain.repository.EmailRepository; +import org.springframework.stereotype.Repository; + +@Repository +public class MailRepositoryAdapter implements EmailRepository { + + private final SpringDataMailRepository springDataMailRepository; + + public MailRepositoryAdapter(SpringDataMailRepository springDataMailRepository) { + this.springDataMailRepository = springDataMailRepository; + } + + @Override + public Email save(Email email) { + MailJpa mailJpa = new MailJpa(); + mailJpa.setSender(email.getFrom()); + mailJpa.setRecipient(email.getTo()); + mailJpa.setSubjet(email.getSubject()); + mailJpa.setBody(email.getBody()); + + springDataMailRepository.save(mailJpa); + + return email; + } +} diff --git a/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/persistence/SpringDataMailRepository.java b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/persistence/SpringDataMailRepository.java new file mode 100644 index 0000000..d880e88 --- /dev/null +++ b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/persistence/SpringDataMailRepository.java @@ -0,0 +1,7 @@ +package com.pablotj.restemailbridge.infrastructure.persistence; + +import org.springframework.data.jpa.repository.JpaRepository; + + +public interface SpringDataMailRepository extends JpaRepository { +} diff --git a/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/rest/MailController.java b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/rest/MailController.java new file mode 100644 index 0000000..5d7340a --- /dev/null +++ b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/rest/MailController.java @@ -0,0 +1,29 @@ +package com.pablotj.restemailbridge.infrastructure.rest; + +import com.pablotj.restemailbridge.application.dto.EmailDTO; +import com.pablotj.restemailbridge.application.usecase.SendEmailUseCase; +import com.pablotj.restemailbridge.infrastructure.rest.dto.SendMailRequest; +import jakarta.validation.Valid; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/v1/mail") +public class MailController { + + private final SendEmailUseCase sendEmailUseCase; + + public MailController(SendEmailUseCase sendEmailUseCase) { + this.sendEmailUseCase = sendEmailUseCase; + } + + + @PostMapping + public ResponseEntity send(@Valid @RequestBody SendMailRequest request) { + sendEmailUseCase.handle(new EmailDTO(request.from(), request.subject(), request.body())); + return ResponseEntity.ok().build(); + } +} \ No newline at end of file diff --git a/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/rest/dto/SendMailRequest.java b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/rest/dto/SendMailRequest.java new file mode 100644 index 0000000..ba07d94 --- /dev/null +++ b/infrastructure/src/main/java/com/pablotj/restemailbridge/infrastructure/rest/dto/SendMailRequest.java @@ -0,0 +1,8 @@ +package com.pablotj.restemailbridge.infrastructure.rest.dto; + +public record SendMailRequest( + String from, + String subject, + String body +) { +}