-
Notifications
You must be signed in to change notification settings - Fork 0
[feat] 메일 발송 기능 구현 #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
58648bf
31f5121
40d8713
ff4cfad
82c0d1a
db28bfc
52651c0
8e3cfac
79d3fd5
6bc4251
64e7268
272bd01
526448a
b0bf4ea
b834817
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,20 @@ | ||
| package dmu.dasom.api.domain.applicant.repository; | ||
|
|
||
| import dmu.dasom.api.domain.applicant.entity.Applicant; | ||
| import dmu.dasom.api.domain.applicant.enums.ApplicantStatus; | ||
| import org.springframework.data.domain.Page; | ||
| import org.springframework.data.domain.Pageable; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
| import org.springframework.data.jpa.repository.Query; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public interface ApplicantRepository extends JpaRepository<Applicant, Long> { | ||
|
|
||
| @Query("SELECT a FROM Applicant a ORDER BY a.id DESC") | ||
| Page<Applicant> findAllWithPageRequest(final Pageable pageable); | ||
|
|
||
| // 상태별 지원자 조회 | ||
| List<Applicant> findByStatus(ApplicantStatus status); | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package dmu.dasom.api.domain.email.service; | ||
|
|
||
| import jakarta.mail.MessagingException; | ||
| import jakarta.mail.internet.MimeMessage; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.beans.factory.annotation.Autowired; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.mail.SimpleMailMessage; | ||
| import org.springframework.mail.javamail.JavaMailSender; | ||
| import org.springframework.mail.javamail.MimeMessageHelper; | ||
| import org.springframework.stereotype.Service; | ||
| import org.thymeleaf.TemplateEngine; | ||
| import org.thymeleaf.context.Context; | ||
|
|
||
| @RequiredArgsConstructor | ||
| @Service | ||
| public class EmailService { | ||
|
|
||
| private JavaMailSender javaMailSender; | ||
| private TemplateEngine templateEngine; | ||
| @Value("${spring.mail.username}") | ||
| private String from; | ||
|
|
||
| public void sendEmail(String to, String subject, String templateName, String name) throws MessagingException { | ||
| // HTML 템플릿에 전달할 데이터 설정 | ||
| Context context = new Context(); | ||
| context.setVariable("name", name); // 지원자 이름 전달 | ||
|
|
||
| // HTML 템플릿 처리 | ||
| String htmlBody = templateEngine.process(templateName, context); | ||
|
|
||
| // 이메일 생성 및 전송 | ||
| MimeMessage message = javaMailSender.createMimeMessage(); | ||
| MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); | ||
|
|
||
| helper.setTo(to); | ||
| helper.setSubject(subject); | ||
| helper.setText(htmlBody, true); | ||
| helper.setFrom(from); | ||
|
|
||
| javaMailSender.send(message); | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -79,4 +79,48 @@ public ResponseEntity<ApplicantDetailsResponseDto> updateApplicantStatus(@PathVa | |
| return ResponseEntity.ok(applicantService.updateApplicantStatus(id, request)); | ||
| } | ||
|
|
||
| @Operation(summary = "서류 결과 메일 전송") | ||
|
||
| @ApiResponses(value = { | ||
| @ApiResponse(responseCode = "200", description = "메일 전송 성공"), | ||
| @ApiResponse(responseCode = "400", description = "잘못된 요청", | ||
| content = @Content( | ||
| mediaType = "application/json", | ||
| schema = @Schema(implementation = ErrorResponse.class), | ||
| examples = { | ||
| @ExampleObject( | ||
| name = "전송 실패", | ||
| value = "{ \"code\": \"C014\", \"message\": \"이메일 전송에 실패하였습니다.\" }" | ||
| ) | ||
| } | ||
| ) | ||
| ) | ||
| }) | ||
| @PostMapping("/applicants/send-document-pass-email") | ||
| public ResponseEntity<String> sendDocumentPassEmails() { | ||
| applicantService.sendDocumentPassEmailsToApplicants(); | ||
| return ResponseEntity.ok("이메일 전송 성공"); | ||
| } | ||
|
|
||
| @Operation(summary = "최종 결과 메일 전송") | ||
| @ApiResponses(value = { | ||
| @ApiResponse(responseCode = "200", description = "메일 전송 성공"), | ||
| @ApiResponse(responseCode = "400", description = "잘못된 요청", | ||
| content = @Content( | ||
| mediaType = "application/json", | ||
| schema = @Schema(implementation = ErrorResponse.class), | ||
| examples = { | ||
| @ExampleObject( | ||
| name = "전송 실패", | ||
| value = "{ \"code\": \"C014\", \"message\": \"이메일 전송에 실패하였습니다.\" }" | ||
| ) | ||
| } | ||
| ) | ||
| ) | ||
| }) | ||
| @PostMapping("/applicants/send-final-pass-email") | ||
| public ResponseEntity<String> sendFinalPassEmail(){ | ||
| applicantService.sendFinalPassEmailsToDocumentPassApplicants(); | ||
| return ResponseEntity.ok("이메일 전송 성공"); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="ko"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| <title>지원 결과 확인</title> | ||
| <style> | ||
| body { | ||
| font-family: Arial, sans-serif; | ||
| background-color: #1a1a1a; | ||
| color: #ffffff; | ||
| margin: 0; | ||
| padding: 0; | ||
| } | ||
| .container { | ||
| max-width: 600px; | ||
| margin: 0 auto; | ||
| padding: 20px; | ||
| background-color: #1a1a1a; | ||
| border-radius: 8px; | ||
| text-align: center; | ||
| } | ||
| .header { | ||
| font-size: 24px; | ||
| font-weight: bold; | ||
| color: #00B493; | ||
| margin-bottom: 20px; | ||
| } | ||
| .sub-header { | ||
| font-size: 16px; | ||
| background-color: #00B493; | ||
| padding: 10px; | ||
| border-radius: 5px; | ||
| margin-bottom: 20px; | ||
| } | ||
| .content { | ||
| font-size: 14px; | ||
| line-height: 1.8; | ||
| } | ||
| .content p { | ||
| margin-bottom: 10px; | ||
| } | ||
| .highlight { | ||
| color: #00B493; | ||
| } | ||
| .button { | ||
| display: inline-block; | ||
| background-color: #00B493; | ||
| color: #ffffff; | ||
| padding: 12px 24px; | ||
| border-radius: 5px; | ||
| text-decoration: none; | ||
| font-size: 16px; | ||
| } | ||
| .button:hover { | ||
| background-color: #00B493; | ||
| } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <div class="container"> | ||
| <!-- Header Section --> | ||
| <div class="header">DASOM</div> | ||
|
|
||
| <!-- Sub-header Section --> | ||
| <div class="sub-header">컴퓨터소프트웨어공학과 전공동아리 다솜<br>34기 서류 합격자 조회</div> | ||
|
|
||
| <!-- Content Section --> | ||
| <div class="content"> | ||
| <p>안녕하세요, <span class="highlight" th:text="${name}"></span>님.</p> | ||
| <p>학번 마지막 <span class="highlight">4자리</span> + 전화번호 마지막 <span class="highlight">4자리</span>를 입력하여<br>지원 결과를 확인할 수 있습니다.</p> | ||
| <p>예시) <span class="highlight">08470542</span></p> | ||
|
|
||
| <!-- Button --> | ||
| <a href="https://example.com/result" class="button">결과 확인하기</a> | ||
| </div> | ||
| </div> | ||
| </body> | ||
| </html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AdminController 코멘트와 마찬가지로
메일 발송메소드를 하나로 정의하고 발송 타입에 따라 다르게 동작되도록 구현하면 좋을 것 같습니다.