diff --git a/src/main/java/com/project/syncly/domain/auth/email/EmailSenderImpl.java b/src/main/java/com/project/syncly/domain/auth/email/EmailSenderImpl.java
index 55eb49a..c501609 100644
--- a/src/main/java/com/project/syncly/domain/auth/email/EmailSenderImpl.java
+++ b/src/main/java/com/project/syncly/domain/auth/email/EmailSenderImpl.java
@@ -1,8 +1,11 @@
package com.project.syncly.domain.auth.email;
+import jakarta.mail.MessagingException;
+import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
-import org.springframework.mail.SimpleMailMessage;
+import org.springframework.core.io.ClassPathResource;
import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
@Service
@@ -13,10 +16,98 @@ public class EmailSenderImpl implements EmailSender {
@Override
public void send(String to, String subject, String content) {
- SimpleMailMessage message = new SimpleMailMessage();
- message.setTo(to);
- message.setSubject(subject);
- message.setText(content);
- javaMailSender.send(message);
+ try {
+ MimeMessage message = javaMailSender.createMimeMessage();
+ MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
+
+ helper.setTo(to);
+ helper.setSubject(subject);
+
+ String body = createEmailTemplate(content);
+ helper.setText(body, true);
+
+ // 돌고래 이미지 첨부
+ ClassPathResource dolphinImage = new ClassPathResource("static/syncly_dolphin.png");
+ helper.addInline("dolphinLogo", dolphinImage);
+
+ javaMailSender.send(message);
+ } catch (MessagingException e) {
+ throw new RuntimeException("이메일 전송에 실패했습니다.", e);
+ }
+ }
+
+ private String createEmailTemplate(String verificationCode) {
+ StringBuilder body = new StringBuilder();
+ body.append("");
+ body.append("");
+ body.append("
");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append("");
+ body.append("");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append("  ");
+ body.append(" ");
+ body.append(" 이메일 인증");
+ body.append(" 회원가입을 위한 인증코드입니다 ");
+ body.append(" | ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" | ");
+ body.append(" 안녕하세요, ");
+ body.append(" ");
+ body.append(" Syncly 회원가입을 환영합니다. ");
+ body.append(" 아래 인증코드를 입력하여 이메일 인증을 완료해 주세요.");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ").append(verificationCode).append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" 보안 안내 ");
+ body.append(" ");
+ body.append(" • 이 인증코드는 10분간 유효합니다 ");
+ body.append(" • 타인에게 코드를 공유하지 마세요 ");
+ body.append(" • 본인이 요청하지 않은 경우 이메일을 무시하세요");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" 만약 회원가입을 요청하지 않으셨다면, 이 이메일을 무시하셔도 됩니다.");
+ body.append(" ");
+ body.append(" | ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" | ");
+ body.append(" ");
+ body.append(" © 2025 Syncly. All rights reserved. ");
+ body.append(" 함께 만들어가는 협업 워크스페이스");
+ body.append(" ");
+ body.append(" | ");
+ body.append(" ");
+ body.append(" ");
+ body.append(" | ");
+ body.append("
");
+ body.append("
");
+ body.append("");
+ body.append("");
+
+ return body.toString();
}
}
diff --git a/src/main/java/com/project/syncly/domain/workspace/service/InvitationMailServiceImpl.java b/src/main/java/com/project/syncly/domain/workspace/service/InvitationMailServiceImpl.java
index 86f2680..7f4ffa3 100644
--- a/src/main/java/com/project/syncly/domain/workspace/service/InvitationMailServiceImpl.java
+++ b/src/main/java/com/project/syncly/domain/workspace/service/InvitationMailServiceImpl.java
@@ -7,8 +7,10 @@
import jakarta.mail.MessagingException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.ClassPathResource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import java.util.Random;
@@ -63,17 +65,87 @@ private String generateRandomToken() {
public MimeMessage createMail(String mail, String number) {
try {
MimeMessage message = javaMailSender.createMimeMessage();
+ MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
- message.setFrom(senderEmail);
- message.setRecipients(MimeMessage.RecipientType.TO, mail);
- message.setSubject("이메일 인증");
+ helper.setFrom(senderEmail);
+ helper.setTo(mail);
+ helper.setSubject("이메일 인증");
String body = "";
- body += "워크스페이스 초대 수락 링크입니다.
";
- body += "";
- body += "감사합니다.
";
-
- message.setText(body, "UTF-8", "html");
+ body += "";
+ body += "";
+ body += "";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += "";
+ body += "";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += "  ";
+ body += " ";
+ body += " 워크스페이스 초대";
+ body += " Syncly 워크스페이스에 초대되었습니다 ";
+ body += " | ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " | ";
+ body += " 안녕하세요, ";
+ body += " ";
+ body += " 새로운 워크스페이스에서 함께 협업하실 수 있도록 초대장을 보내드립니다. ";
+ body += " 아래 버튼을 클릭하여 초대를 수락해 주세요.";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " 버튼이 작동하지 않나요? ";
+ body += " ";
+ body += " 아래 링크를 복사하여 브라우저에 붙여넣으세요: ";
+ body += " " + number + "";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " 이 초대장은 7일간 유효합니다. 만약 이 이메일을 예상하지 못했다면 무시하셔도 됩니다.";
+ body += " ";
+ body += " | ";
+ body += " ";
+ body += " ";
+ body += " ";
+ body += " | ";
+ body += " ";
+ body += " © 2025 Syncly. All rights reserved. ";
+ body += " 함께 만들어가는 협업 워크스페이스";
+ body += " ";
+ body += " | ";
+ body += " ";
+ body += " ";
+ body += " | ";
+ body += "
";
+ body += "
";
+ body += "";
+ body += "";
+
+ helper.setText(body, true);
+
+ // 이미지 첨부 (CID 방식)
+ ClassPathResource dolphinImage = new ClassPathResource("static/syncly_dolphin.png");
+ helper.addInline("dolphinLogo", dolphinImage);
return message;
diff --git a/src/main/resources/static/syncly_dolphin.png b/src/main/resources/static/syncly_dolphin.png
new file mode 100644
index 0000000..9e3614b
Binary files /dev/null and b/src/main/resources/static/syncly_dolphin.png differ