Skip to content

Comments

fix: 이메일 형식 변경 및 utf-8 적용 #245#246

Merged
sjk4618 merged 2 commits intodevfrom
fix/#245
Feb 7, 2026
Merged

fix: 이메일 형식 변경 및 utf-8 적용 #245#246
sjk4618 merged 2 commits intodevfrom
fix/#245

Conversation

@sjk4618
Copy link
Member

@sjk4618 sjk4618 commented Feb 7, 2026

🔥Pull requests

⛳️ 작업한 브랜치

👷 작업한 내용

  • 구글 이메일을 smtp로 보낼 때, 티켓 큐알 코드가 하나만 들어가면 피싱으로 인식하고 지연이 걸림 -> 첨부파일 추가해서 피싱메일 아닌거로 우회

🚨 참고 사항

  • 추후 비동기로 이메일 여러개 보내면 좋을 듯?, 근데 지메일에서 동시에 여러개 보내면 차단하는거 테스트 필수!

@coderabbitai
Copy link

coderabbitai bot commented Feb 7, 2026

📝 Walkthrough

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 게스트 티켓 이메일에 QR 코드 이미지 첨부 기능 추가
    • 이메일 콘텐츠 형식 개선 (HTML 및 일반 텍스트 지원)
    • 한글 폰트 지원 추가
  • Bug Fixes

    • 이메일 발송 오류 처리 개선 및 에러 메시지 명확화
  • Chores

    • 미사용 import 정리

🔍 Walkthrough

게스트 티켓 이메일 발송 시스템을 개선하기 위해 전용 예외 클래스를 추가하고, 다중 파트 이메일 콘텐츠(평문 + HTML) 지원, QR 코드 첨부, 한글 폰트 유틸리티를 도입했습니다.

📋 Changes

Cohort / File(s) Summary
예외 처리 개선
src/main/java/com/permitseoul/permitserver/domain/admin/guestticket/core/exception/GuestEmailSendException.java, src/main/java/com/permitseoul/permitserver/domain/admin/guestticket/api/service/AdminGuestTicketService.java
이메일 발송 실패 시 처리를 위한 새로운 GuestEmailSendException 클래스를 추가했으며, AdminGuestTicketService에서 일반 Exception 처리를 해당 예외로 변경하고 에러 코드를 INTERNAL_EMAIL_SEND_ERROR로 변경했습니다.
이메일 발송 로직 확장
src/main/java/com/permitseoul/permitserver/domain/admin/util/GuestTicketEmailSender.java
이메일 제목 문자열 생성, 다중 파트 콘텐츠(평문 텍스트 + HTML) 지원, QR 코드 PNG를 인라인 및 첨부 형식으로 추가, 상세한 에러 로깅 및 GuestEmailSendException 발생 로직을 추가했습니다.
폰트 유틸리티 추가
src/main/java/com/permitseoul/permitserver/domain/admin/util/PngFontUtil.java, src/main/java/com/permitseoul/permitserver/domain/admin/util/QrCodeUtil.java
클래스패스에서 한글 TTF 폰트(NotoSansKR-Regular.ttf)를 로드하는 PngFontUtil 유틸리티를 추가했으며, QrCodeUtil에서 이를 사용하도록 변경했습니다.
정리
src/main/java/com/permitseoul/permitserver/domain/admin/util/NotionResponseMapper.java
사용하지 않는 import 5개를 제거했습니다.

🎯 Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

📌 Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (1 warning, 2 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive 연결된 이슈 #245에서는 '이메일 형식 변경 및 utf-8 적용'만 기술되었으나, 구체적인 요구사항이나 수용 기준이 제공되지 않아 직접적인 준수 여부 판단 불가. 이슈 #245의 상세 요구사항을 명확히 정의하여 PR 변경사항과의 직접적인 일관성을 확인하시기 바랍니다.
Out of Scope Changes check ❓ Inconclusive PngFontUtil 추가와 QrCodeUtil 폰트 변경은 QR 코드 렌더링 개선으로 보이나, 이메일 형식 변경이라는 주요 목표와의 명시적 연결이 불명확함. PngFontUtil 및 QR 코드 폰트 변경이 이메일 형식 변경 목표와 어떻게 연관되는지 설명하시기 바랍니다.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목 '이메일 형식 변경 및 utf-8 적용'은 변경사항의 주요 내용(이메일 첨부파일 추가, 예외 처리 개선)과 부분적으로 관련되어 있지만 실제 구현의 핵심(QR 코드 첨부파일 추가)을 명확히 반영하지 못함.
Description check ✅ Passed PR 설명에서 '구글 이메일 smtp로 보낼 때 티켓 QR 코드 첨부파일 추가'는 변경사항과 관련이 있으며, 피싱 우회 목적도 명확하게 설명됨.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/#245

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/permitseoul/permitserver/domain/admin/guestticket/api/service/AdminGuestTicketService.java (1)

37-62: ⚠️ Potential issue | 🟠 Major

이메일 발송 실패 시 티켓 상태 관리 문제 - 부분 실패 데이터 정합성 이슈

issueGuestTickets() 메서드에는 @Transactional 어노테이션이 없으며, 각 반복마다 saveGuestTickets() 호출 시 티켓이 DB에 저장되고 즉시 커밋됩니다. 이메일 발송 실패 시:

  • 이미 저장된 게스트의 티켓은 updateGuestTicketToReadyStatus() 호출 전에 DB에 커밋된 상태
  • GuestEmailSendException 발생 시 updateGuestTicketToReadyStatus() (51번 라인)에 도달하지 않음
  • 예외가 던져지며 루프 종료
  • 실패한 게스트의 티켓은 DB에 존재하지만 상태 업데이트 없이 남음

트랜잭션 경계 추가 또는 부분 실패 시 보상(compensation) 로직 검토가 필요합니다.

🤖 Fix all issues with AI agents
In
`@src/main/java/com/permitseoul/permitserver/domain/admin/util/GuestTicketEmailSender.java`:
- Around line 88-91: The catch block in GuestTicketEmailSender that logs toEmail
and guestName must avoid writing PII; replace those values in the log with
either masked versions (e.g., maskLocalPart(toEmail)) or a non-identifying
internal id, and update the log statement in the catch of send (references:
toEmail, guestName, log.error call) to only include non-PII fields and the
exception message/stack; also throw the GuestEmailSendException with the
original exception as the cause (new GuestEmailSendException(e)) so debugging
retains the root cause while keeping logs PII-free.
🧹 Nitpick comments (4)
src/main/java/com/permitseoul/permitserver/domain/admin/util/GuestTicketEmailSender.java (2)

74-74: 주석 처리된 코드 정리 필요

주석 처리된 helper.setSubject(...) 코드가 남아 있습니다. 더 이상 사용하지 않으므로 제거하는 것이 좋습니다.


77-83: 첨부파일과 인라인 이미지를 동일한 소스로 추가하는 방식 확인

동일한 ByteArrayResource를 인라인(addInline)과 첨부(addAttachment)에 모두 사용하고 있습니다. ByteArrayResource는 반복 읽기가 가능하므로 기능적으로는 문제가 없으나, 이메일 용량이 QR 이미지 수 × 2배로 증가합니다. 티켓 수가 많을 경우 이메일 크기 제한에 주의하세요.

src/main/java/com/permitseoul/permitserver/domain/admin/util/PngFontUtil.java (1)

14-25: 폰트 파일은 정상 배포되지만 폴백 폰트 전략 개선 권장

NotoSansKR-Regular.ttf 파일은 src/main/resources/fonts/ 디렉토리에 정상적으로 포함되어 있으므로, Maven 빌드 시 자동으로 JAR에 포함됩니다. 다만, 파일 로딩 실패 시 SansSerif 폴백 폰트는 한국어 글리프를 지원하지 않아 QR 코드 위의 이벤트명이 깨질 수 있습니다.

예외 발생 시에도 한국어 렌더링을 보장하기 위해 다음을 고려하세요:

  • DejaVu Sans 등 한글을 지원하는 폴백 폰트 사용
  • 또는 폰트 로딩 실패 시 더 강한 에러 처리 (예: 초기화 실패 로깅)
src/main/java/com/permitseoul/permitserver/domain/admin/guestticket/core/exception/GuestEmailSendException.java (1)

1-4: 예외 원인(cause)을 명시적으로 전달할 수 있도록 생성자를 추가하면 좋습니다.

현재 GuestTicketCoreExceptionRuntimeException을 상속하고 있어 기술적으로는 new GuestEmailSendException(cause)로 원본 예외를 전달할 수 있습니다. 다만 명시적 생성자가 없어 이 기능이 드러나지 않습니다. 또한 GuestTicketEmailSender에서 원본 예외를 로깅하고 있으므로 정보 손실은 없는 상태입니다.

코드 가독성과 의도를 명확히 하기 위해 다음과 같이 생성자를 추가하는 것을 권장합니다:

♻️ 명시적 생성자 추가 제안
 public class GuestEmailSendException extends GuestTicketCoreException {
+    public GuestEmailSendException() {
+        super();
+    }
+
+    public GuestEmailSendException(final Throwable cause) {
+        super(cause);
+    }
 }

이후 GuestTicketEmailSender에서 throw new GuestEmailSendException(e);로 원본 예외를 명시적으로 전달하면 예외 체인이 유지됩니다.

Comment on lines +88 to +91
} catch (Exception e) {
log.error("[Guest Ticket Email] 발송 실패 - to={}, guestName={}, event={}, ticketCount={}",
toEmail, guestName, eventName, ticketCodes.size(), e);
throw new GuestEmailSendException();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

에러 로그에 이메일(PII) 포함 — 개인정보 유출 위험

Line 89-90에서 toEmailguestName을 에러 로그에 직접 기록하고 있습니다. 이메일 주소와 이름은 개인식별정보(PII)이며, 로그 시스템에 저장될 경우 GDPR/개인정보보호법 위반 가능성이 있습니다.

이메일은 마스킹 처리하거나, 식별 가능한 내부 ID로 대체하는 것을 권장합니다. 또한, new GuestEmailSendException()에 원인 예외(e)를 전달하면 디버깅이 용이합니다.

🛡️ PII 마스킹 및 예외 원인 전달 제안
         } catch (Exception e) {
-            log.error("[Guest Ticket Email] 발송 실패 - to={}, guestName={}, event={}, ticketCount={}",
-                    toEmail, guestName, eventName, ticketCodes.size(), e);
-            throw new GuestEmailSendException();
+            log.error("[Guest Ticket Email] 발송 실패 - event={}, ticketCount={}",
+                    eventName, ticketCodes.size(), e);
+            throw new GuestEmailSendException(e);
         }
🤖 Prompt for AI Agents
In
`@src/main/java/com/permitseoul/permitserver/domain/admin/util/GuestTicketEmailSender.java`
around lines 88 - 91, The catch block in GuestTicketEmailSender that logs
toEmail and guestName must avoid writing PII; replace those values in the log
with either masked versions (e.g., maskLocalPart(toEmail)) or a non-identifying
internal id, and update the log statement in the catch of send (references:
toEmail, guestName, log.error call) to only include non-PII fields and the
exception message/stack; also throw the GuestEmailSendException with the
original exception as the cause (new GuestEmailSendException(e)) so debugging
retains the root cause while keeping logs PII-free.

@sjk4618 sjk4618 merged commit 41ae872 into dev Feb 7, 2026
2 checks passed
@sjk4618 sjk4618 deleted the fix/#245 branch February 7, 2026 17:51
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.

fix: 이메일 형식 변경 및 utf-8 적용

1 participant