Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/cd-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ jobs:
JWT_SECRET=${{ secrets.JWT_SECRET }}
SES_SMTP_USERNAME=${{ secrets.SES_SMTP_USERNAME }}
SES_SMTP_PASSWORD=${{ secrets.SES_SMTP_PASSWORD }}
GMAIL_USERNAME=${{ secrets.GMAIL_USERNAME }}
GMAIL_PASSWORD=${{ secrets.GMAIL_PASSWORD }}
EOF

echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
Expand Down
2 changes: 1 addition & 1 deletion app/config
13 changes: 12 additions & 1 deletion app/src/main/kotlin/com/maggom/app/adapter/MailAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.maggom.auth.port.out.EmailSenderPort
import com.maggom.auth.port.out.TestMailPort
import com.maggom.auth.port.out.WelcomeMailPort
import com.maggom.event.domain.MarathonEvent
import com.maggom.event.port.out.MarathonEventPort
import com.maggom.event.port.out.NotificationMailPort
import jakarta.mail.internet.InternetAddress
import jakarta.mail.internet.MimeMessage
Expand All @@ -28,8 +29,14 @@ class MailAdapter(
@Value("\${spring.mail.from-name}") private val fromName: String,
@Value("\${maggom.mail.fallback.from-email:#{null}}") private val fallbackFromEmail: String?,
@Autowired(required = false) @Qualifier("gmailMailSender") private val fallbackMailSender: JavaMailSender?,
private val marathonEventPort: MarathonEventPort,
) : EmailSenderPort, WelcomeMailPort, NotificationMailPort, TestMailPort {

companion object {
private val DEFAULT_REGIONS = listOf("수도권")
private const val WELCOME_EVENTS_COUNT = 2
}

private val log = LoggerFactory.getLogger(javaClass)

override fun sendAuthCode(message: AuthCodeEmailMessage) {
Expand All @@ -46,11 +53,15 @@ class MailAdapter(
}

override fun sendWelcomeMail(to: String) {
val events = marathonEventPort.findOpenByRegions(DEFAULT_REGIONS).take(WELCOME_EVENTS_COUNT)
val context = Context(Locale.KOREAN).apply {
setVariable("events", events)
}
sendHtml(
to = to,
subject = "[마꼼] 구독을 시작했어요! 🏃",
template = "mail/welcome",
context = Context(Locale.KOREAN),
context = context,
)
}

Expand Down
50 changes: 25 additions & 25 deletions app/src/main/resources/templates/mail/welcome.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,31 @@
이런 형식으로 알림을 받아보실 수 있어요.
</p>

<!-- 샘플 카드 -->
<div style="border:1px solid #e0e7ff; border-radius:6px; padding:12px 16px; margin-bottom:8px;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="color:#312e81; font-size:14px; font-weight:700;">2026 서울 봄 마라톤</td>
<td align="right" style="white-space:nowrap;">
<span style="display:inline-block; padding:4px 12px; background:#ccc; color:#ffffff; font-size:12px; font-weight:600; border-radius:4px;">대회 사이트</span>
</td>
</tr>
</table>
<p style="margin:5px 0 0; color:#666; font-size:12px;"><strong>대회일:</strong> 2026.04.19 <span style="color:#c7d2fe; margin:0 6px;">|</span> <strong>지역:</strong> 서울시 어쩌구 <span style="color:#c7d2fe; margin:0 6px;">|</span> <strong>코스:</strong> 10K, 하프, 풀</p>
<p style="margin:3px 0 0; color:#999; font-size:12px;"><strong style="color:#888;">신청기간:</strong> 2026.03.01 ~ 2026.04.01</p>
</div>

<div style="border:1px solid #e0e7ff; border-radius:6px; padding:12px 16px; margin-bottom:20px;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="color:#312e81; font-size:14px; font-weight:700;">2026 한강 하프마라톤</td>
<td align="right" style="white-space:nowrap;">
<span style="display:inline-block; padding:4px 12px; background:#ccc; color:#ffffff; font-size:12px; font-weight:600; border-radius:4px;">대회 사이트</span>
</td>
</tr>
</table>
<p style="margin:5px 0 0; color:#666; font-size:12px;"><strong>대회일:</strong> 2026.05.10 <span style="color:#c7d2fe; margin:0 6px;">|</span> <strong>지역:</strong> 서울시 어쩌구 <span style="color:#c7d2fe; margin:0 6px;">|</span> <strong>코스:</strong> 하프</p>
<p style="margin:3px 0 0; color:#999; font-size:12px;"><strong style="color:#888;">신청기간:</strong> 2026.03.15 ~ 2026.04.20</p>
<!-- 이벤트 목록 -->
<div th:each="event : ${events}">
<div style="border:1px solid #e0e7ff; border-radius:6px; padding:12px 16px; margin-bottom:8px;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="color:#312e81; font-size:14px; font-weight:700;" th:text="${event.title}">대회명</td>
<td align="right" style="white-space:nowrap;">
<a th:href="${event.linkUrl}" target="_blank" rel="noopener noreferrer" style="display:inline-block; padding:4px 12px; background:#6366f1; color:#ffffff; font-size:12px; font-weight:600; text-decoration:none; border-radius:4px;">대회 사이트</a>
</td>
</tr>
</table>
<p style="margin:5px 0 0; color:#666; font-size:12px;">
<strong>대회일:</strong> <span th:text="${#temporals.format(event.eventDate, 'yyyy.MM.dd')}">2026.04.20</span>
<span style="color:#c7d2fe; margin:0 6px;">|</span>
<strong>지역:</strong> <span th:text="${event.region}">수도권</span>
<span style="color:#c7d2fe; margin:0 6px;">|</span>
<strong>코스:</strong> <span th:text="${#strings.listJoin(event.distances, ', ')}">10K, 하프</span>
</p>
<p style="margin:3px 0 0; color:#999; font-size:12px;">
<strong style="color:#888;">신청기간:</strong>
<span th:text="${#temporals.format(event.regStartDate, 'yyyy.MM.dd')}">2026.03.01</span>
~
<span th:text="${event.regEndDate != null ? #temporals.format(event.regEndDate, 'yyyy.MM.dd') : '미정'}">2026.04.01</span>
</p>
</div>
</div>

<p style="margin:0; color:#666; font-size:13px; line-height:1.6;">
Expand Down
Loading