Skip to content
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

feat(mail): support the use of markdown in the email body #726

Merged
merged 16 commits into from
Sep 13, 2023

Conversation

woowabrie
Copy link

Resolves #714

해결하려는 문제가 무엇인가요?

  • 메일 작성 시, 본문에 스타일을 입히고 싶을 경우 마크다운으로 작성 후 html로 변환하여 입력하는 불편함이 있습니다.

어떻게 해결했나요?

  • 일반적인 메일을 작성 시, 메일 전송 전 본문을 html로 변환하는 로직을 추가했습니다.

어떤 부분에 집중하여 리뷰해야 할까요?

  • MailService의 sendMailsByBcc() 함수를 사용해 메일을 보낼 경우 본문을 마크다운으로 작성을 해야 합니다. 어드민을 사용해 작성하는 경우엔 문제가 없을 것 같은데, 기존에 /api/mail 엔드포인트를 사용해서 메일을 발송하는 경우가 있는지 확인 부탁드립니다.
  • utils, support 두 패키지가 있는데 이전 논의를 보니 정리가 안된 것 같은데, 패키지 정리를 위한 이슈 하나를 따면 어떨까요?

참고 자료


RCA 룰

r: 꼭 반영해 주세요. 적극적으로 고려해 주세요. (Request changes)
c: 웬만하면 반영해 주세요. (Comment)
a: 반영해도 좋고 넘어가도 좋습니다. 그냥 사소한 의견입니다. (Approve)

@woowabrie
Copy link
Author

local에서 메일을 보내본 결과 잘 동작 하는 것 확인했습니다.
지난 기수 모집 때 사용한 메일 내용을 기반으로 했고, 스크린샷에서 노출이 불필요한 부분은 가렸어요. ㅋㅋ

로컬 테스트를 위해 변경한 내용은 아래와 같습니다.

  • aws 관련 토큰 추가
  • 메일 본문 상단의 이미지 url 변경 (local 프론트엔드 url을 호출해서...)

스크린샷 2023-09-05 오후 5 01 24

Copy link
Contributor

@woowahan-pjs woowahan-pjs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다. 👍
코틀린 스타일로 코드를 작성하는 데 도움이 되는 몇 가지 사항을 리뷰하고 프로젝트 컨벤션을 소개해 드렸습니다.

Comment on lines 43 to 45
fun getHtmlBody(): String {
return MarkdownProcessor.generateToHtml(body)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c: 로직이 복잡하지 않고 위임만 하면 MailService에서 직접 호출할 수 있을 것 같은데, 어떻게 생각하세요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DTO에 Markdown 의존성이 생기는 것에 공감하여 이동하였습니다.

@@ -119,4 +111,16 @@ class MailService(
)
)
}

fun createCommonMailBodyFrom(mailData: MailData): String {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c: 보다 간결하고 명확한 함수 이름을 제안해 봐요!

Suggested change
fun createCommonMailBodyFrom(mailData: MailData): String {
fun String.toMarkdownBody(): String {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리턴 되는 문자열이 html이라 toHtmlBody로 변경했어요.

@@ -119,4 +111,16 @@ class MailService(
)
)
}

fun createCommonMailBodyFrom(mailData: MailData): String {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: MailService 외에 사용하는 곳이 없어 보이네요. public이 아닌 private으로 바꾸면 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

미리보기 기능을 만들 때 필요해서 public으로 두었습니다.


private val logger = KotlinLogging.logger { }

class FakeMailSender : MailSender {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: 가짜 객체는 테스트 디렉터리로 이동해야 하지 않을까요?


class FakeMailSender : MailSender {
override fun send(toAddress: String, subject: String, body: String) {
logger.info("send mail: to - {}, subject - {}", toAddress, subject)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: 코틀린 스타일로 작성해 볼까요?

logger.debug("hello {}", heavyWorld(13)) // 항상 연산
logger.debug { "hello ${heavyWorld(33)}" } // debug 레벨 로그 남길 때만 연산

object MarkdownProcessor {
private val flavour = CommonMarkFlavourDescriptor()

fun generateToHtml(source: String): String {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a: text 또는 markdownText와 같이 사용 중인 API에서 지정한 매개 변수 이름을 따르는 것은 어떨까요?

@@ -63,7 +63,7 @@
padding-right: 8px;
"
>
<span th:utext="${content}"></span>
[(${content})]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a: 이 문법은 무슨 뜻인가요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

content가 html string이여서 text inlining 을 적용했습니다.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

첨부하신 문서는 Thymeleaf 2.1 버전이라서 찾을 수 없네요! 3.x의 기능인 것 같은데, 스프링 부트는 오랫동안 3.x를 사용해 왔더라고요.
https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#expression-inlining

import support.test.IntegrationTest

@IntegrationTest
@ContextConfiguration(classes = [TestMailConfig::class])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: 자주 변경될 수 있는 애너테이션은 상단으로 옮기는 것이 좋습니다.

Comment on lines 17 to 18
val body = "안녕하세요. 우아한테크코스입니다.\n" + "\n" +
"1주 차 미션은 개발 환경을 세팅하고, GitHub에 과제를 제출하는 등 미션 외에도 추가로 익혀야 하는 부분들이 있어 가벼운 미션으로 준비했어요."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: 수많은 이스케이프가 필요한 문자열의 경우 3중 따옴표 문자열을 사용하면 더 깔끔하게 표현할 수 있습니다.
https://kotlinlang.org/docs/strings.html#multiline-strings

val commonMailBody = mailService.createCommonMailBodyFrom(mailData)

Then("본문이 포함된 HTML로 작성된다.") {
println(commonMailBody)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: 콘솔로 출력하는 대신 테스트 코드를 더 보완하면 어떨까요?

@woowahan-pjs woowahan-pjs changed the base branch from master to develop September 8, 2023 00:33
private val flavour: MarkdownFlavourDescriptor = CommonMarkFlavourDescriptor()

fun markdownToHtml(markdownText: String): String {
val parsedTree = MarkdownParser(flavour).buildMarkdownTreeFromString(markdownText)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c: MarkdownParser도 flavour처럼 객체 하나만 만들어둬도 괜찮을 것 같아요

private val markdownParser = MarkdownParser(flavour)

안녕하세요. 우아한테크코스입니다.

1주 차 미션은 개발 환경을 세팅하고, GitHub에 과제를 제출하는 등 미션 외에도 추가로 익혀야 하는 부분들이 있어 가벼운 미션으로 준비했어요.
""".trimIndent()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c: trimIndent() 처리를 MailData 에서 처리하는건 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trimIndent() 는 테스트 문자열을 멀티라인으로 작성하면서 Indentation이 생겨서 추가했습니다. 검사할 예상 값과 인덴트 차이가 발생해서요!
테스트가 아닌 상황에서는 발생하지 않아서(혹은 인덴트가 있어도 렌더링에는 문제가 없어서) 서비스 코드에 추가하지 않아도 될 것 같아요. ㅎㅎ

@woowabrie
Copy link
Author

@woowahan-pjs @kang-hyungu
좋은 의견들 감사합니다. ㅎㅎ 코멘트 주신 사항들 적용했어요.
확인 부탁드려요~

Copy link
Contributor

@woowahan-pjs woowahan-pjs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

메일을 작성할 때 템플릿에 이미 <body>가 있으므로 마크다운을 HTML로 변환할 때 <body>를 추가하지 않는 함수를 하나 더 추가하였습니다.
나머지는 문제 없어요! 수고해 주셔서 감사합니다. 👍

import org.springframework.context.annotation.Import
import support.test.IntegrationTest

@Import(TestMailConfiguration::class)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ContextConfiguration@Import의 차이점은 무엇일까요?

@woowahan-pjs woowahan-pjs changed the title feat(administrator): support markdown for common mail body feat(mail): support the use of markdown in the email body Sep 9, 2023
@woowahan-pjs woowahan-pjs merged commit eb83941 into develop Sep 13, 2023
@woowahan-pjs woowahan-pjs deleted the feature/markdown-to-html branch September 13, 2023 07:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

메일 본문 마크다운 문법을 지원한다.
3 participants