[Practice] 메일 전송 (4)
2021. 4. 20. 15:53ㆍSpring/Practice
1. 문제
- 문의 게시판 글에 답변을 달았을 때 메일로 답변 정보를 전송하는 API
2. 풀이
- schema.sql
...
create table BOARD
(
ID BIGINT auto_increment primary key,
CONTENTS CLOB,
REG_DATE TIMESTAMP,
TITLE VARCHAR(255),
BOARD_TYPE_ID BIGINT,
USER_ID BIGINT,
TOP_YN BOOLEAN DEFAULT FALSE,
PUBLISH_START_DATE DATE,
PUBLISH_END_DATE DATE,
REPLY_CONTENTS CLOB,
constraint FK_BOARD_BOARD_TYPE_ID foreign key (BOARD_TYPE_ID) references BOARD_TYPE (ID),
constraint FK_BOARD_USER_ID foreign key (USER_ID) references USER (ID)
);
- data.sql
...
INSERT INTO MAIL_TEMPLATE(ID, TEMPLATE_ID, TITLE, CONTENTS, SEND_EMAIL, SEND_USER_NAME, REG_DATE) VALUES
(1, 'USER_RESET_PASSWORD', '{USER_NAME}님의 비밀번호 초기화 요청입니다.', '<div><p>{USER_NAME}님 안녕하세요.</p><p>아래 링크를 클릭하여, 비밀번호를 초기화해주세요.</p><p><a href="{SERVER_URL}/reset?key={RESET_PASSWORD_KEY}">초기화</a></p></div>',
'ozofweird@gmail.com', '관리자', '2021-01-01 01:01:01.000000'),
(2, 'BOARD_ADD', '{USER_NAME}님이 글을 게시하였습니다.', '<div><p>제목: {BOARD_TITLE}</p><p>내용</p><div>{BOARD_CONTENTS}</div></div>',
'ozofweird@gmail.com', '관리자', '2021-01-01 01:01:01.000000'),
(3, 'BOARD_REPLY', '{USER_NAME}님이 글에 답변하였습니다.', '<p>제목: {BOARD_TITLE}</p><p>내용</p><div>{BOARD_CONTENTS}</div><p>답변</p><div>{BOARD_REPLY_CONTENTS}</div></div>',
'ozofweird@gmail.com', '관리자', '2021-01-01 01:01:01.000000');
- Board.java
package com.example.jpa.sample.board.entity;
import com.example.jpa.sample.user.entity.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@ManyToOne
@JoinColumn
private User user;
@ManyToOne
@JoinColumn
private BoardType boardType;
@Column
private String title;
@Column
private String contents;
@Column
private LocalDateTime regDate;
@Column
private boolean topYn;
@Column
private LocalDate publishStartDate;
@Column
private LocalDate publishEndDate;
@Column // 답변 내용
private String replyContents;
}
- BoardReplyInput.java
package com.example.jpa.sample.board.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class BoardReplyInput {
private String replyContents;
}
- board_reply.html (resource - mail-template)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{USER_NAME}님이 글에 답변하였습니다.</title>
</head>
<body>
<div>
<p>제목: {BOARD_TITLE}</p>
<p>내용</p>
<div>
{BOARD_CONTENTS}
</div>
<p>답변</p>
<div>{BOARD_REPLY_CONTENTS}</div>
</div>
</body>
</html>
- BoardService.java
package com.example.jpa.sample.board.service;
import com.example.jpa.sample.board.entity.Board;
import com.example.jpa.sample.board.entity.BoardBadReport;
import com.example.jpa.sample.board.entity.BoardComment;
import com.example.jpa.sample.board.entity.BoardType;
import com.example.jpa.sample.board.model.*;
import java.util.List;
public interface BoardService {
...
ServiceResult replyBoard(Long id, BoardReplyInput boardReplyInput);
}
- BoardServiceImpl.java
package com.example.jpa.sample.board.service;
import com.example.jpa.sample.board.entity.*;
import com.example.jpa.sample.board.model.*;
import com.example.jpa.sample.board.repository.*;
import com.example.jpa.sample.common.MailComponent;
import com.example.jpa.sample.common.exception.BizException;
import com.example.jpa.sample.mail.entity.MailTemplate;
import com.example.jpa.sample.mail.repository.MailTemplateRepository;
import com.example.jpa.sample.user.entity.User;
import com.example.jpa.sample.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@RequiredArgsConstructor
@Service
public class BoardServiceImpl implements BoardService {
private final BoardTypeRepository boardTypeRepository;
private final BoardRepository boardRepository;
private final BoardTypeCustomRepository boardTypeCustomRepository;
private final BoardHitsRepository boardHitsRepository;
private final BoardLikeRepository boardLikeRepository;
private final BoardBadReportRepository boardBadReportRepository;
private final BoardScrapRepository boardScrapRepository;
private final BoardBookmarkRepository boardBookmarkRepository;
private final BoardCommentsRepository boardCommentsRepository;
private final UserRepository userRepository;
private final MailTemplateRepository mailTemplateRepository;
private final MailComponent mailComponent;
...
@Override
public ServiceResult replyBoard(Long id, BoardReplyInput boardReplyInput) {
Optional<Board> optionalBoard = boardRepository.findById(id);
if(!optionalBoard.isPresent()) {
throw new BizException("게시글이 존재하지 않습니다.");
}
Board board = optionalBoard.get();
board.setReplyContents(boardReplyInput.getReplyContents());
boardRepository.save(board);
// 메일 전송 로직
Optional<MailTemplate> optionalMailTemplate = mailTemplateRepository.findByTemplateId("BOARD_ADD");
optionalMailTemplate.ifPresent((e) -> {
String fromEmail = e.getSendEmail();
String fromName = e.getSendUserName();
String title = e.getTitle().replaceAll("\\{USER_NAME\\}", board.getUser().getName());
String contents = e.getContents().replaceAll("\\{BOARD_CONTENTS\\}", board.getContents())
.replaceAll("\\{BOARD_REPLY_CONTENTS\\}", boardReplyInput.getReplyContents());
mailComponent.send(fromEmail, fromName, board.getUser().getEmail(), board.getUser().getName(), title, contents);
});
return ServiceResult.success();
}
}
- ApiAdminBoardController.java
package com.example.jpa.sample.board.controller;
import com.example.jpa.sample.board.entity.BoardBadReport;
import com.example.jpa.sample.board.model.BoardReplyInput;
import com.example.jpa.sample.board.model.ServiceResult;
import com.example.jpa.sample.board.service.BoardService;
import com.example.jpa.sample.common.model.ResponseResult;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequiredArgsConstructor
@RestController
public class ApiAdminBoardController {
private final BoardService boardService;
...
//------------------------------------------------------------------------------
// 문제 4
@PostMapping("/api/admin/board/{id}/reply")
public ResponseEntity<?> reply(@PathVariable Long id, @RequestBody BoardReplyInput boardReplyInput) {
ServiceResult result = boardService.replyBoard(id, boardReplyInput);
return ResponseResult.success(result);
}
}
728x90
'Spring > Practice' 카테고리의 다른 글
[Practice] 스케쥴러 활용 (2) (0) | 2021.04.20 |
---|---|
[Practice] 스케쥴러 활용 (1) (0) | 2021.04.20 |
[Practice] 메일 전송 (3) (0) | 2021.04.20 |
[Practice] 메일 전송 (2) (0) | 2021.04.20 |