mailbox/backend/services/emailService.js

109 lines
3.2 KiB
JavaScript
Raw Permalink Normal View History

2025-12-16 08:18:15 +09:00
/**
* 이메일 발송 서비스 (Resend 사용)
* AWS SES 대신 Resend API를 사용하여 이메일 발송
*/
const { Resend } = require("resend");
/**
* Resend 클라이언트 생성
* DB에서 API 키를 가져와 설정
* @returns {Promise<{resend: Resend, from: string}>}
*/
const createClient = async () => {
const SystemConfig = require("../models/SystemConfig");
// DB에서 설정 조회
const configs = await SystemConfig.findAll();
const configMap = {};
configs.forEach((c) => (configMap[c.key] = c.value));
// DB 설정 우선, 없으면 환경 변수 사용
const apiKey = configMap["resend_api_key"] || process.env.RESEND_API_KEY;
if (!apiKey) {
throw new Error("Resend API 키가 설정되지 않았습니다");
}
const resend = new Resend(apiKey);
return {
resend,
from:
configMap["mail_from"] || process.env.MAIL_FROM || "admin@caadiq.co.kr",
};
};
/**
* 이메일 발송 (Resend 사용)
* @param {Object} params - 이메일 파라미터
* @param {string} [params.from] - 발신자 (선택, 없으면 기본값 사용)
* @param {string} params.to - 수신자
* @param {string} params.subject - 제목
* @param {string} params.html - HTML 본문
* @param {string} [params.text] - 텍스트 본문 (선택)
* @param {Array} [params.attachments] - 첨부파일 배열 (선택)
* @returns {Promise<Object>} Resend 발송 결과
*/
exports.sendEmail = async ({
from: senderEmail,
to,
subject,
html,
text,
attachments = [],
}) => {
try {
const { resend, from: defaultFrom } = await createClient();
// 발신자: 전달된 값 또는 기본값 사용
const actualFrom = senderEmail || defaultFrom;
// 첨부파일 변환 (Resend 형식: filename, content as Buffer/base64)
const resendAttachments = attachments.map((att) => ({
filename: att.filename,
content: Buffer.isBuffer(att.content)
? att.content
: Buffer.from(att.content, "base64"),
}));
console.log(`[Resend] 첨부파일 개수: ${attachments.length}`);
if (attachments.length > 0) {
console.log(
`[Resend] 첨부파일 정보:`,
attachments.map((a) => ({
filename: a.filename,
contentType: a.contentType,
contentLength: a.content?.length || 0,
}))
);
}
// to가 배열이면 그대로, 문자열이면 배열로 변환
const toArray = Array.isArray(to) ? to : to.split(",").map((e) => e.trim());
// html과 text 기본값 처리 (둘 다 없으면 빈 공백이라도 전달)
const finalHtml = html || text || " ";
const finalText = text || (html ? html.replace(/<[^>]*>/g, "") : " ");
const result = await resend.emails.send({
from: actualFrom,
to: toArray,
subject: subject || "(제목 없음)",
html: finalHtml,
text: finalText,
attachments: resendAttachments.length > 0 ? resendAttachments : undefined,
});
if (result.error) {
console.error("[Resend] 발송 오류:", result.error);
throw new Error(result.error.message);
}
console.log("[Resend] 메일 발송 완료:", result.data?.id);
return { messageId: result.data?.id };
} catch (error) {
console.error("[Resend] 발송 오류:", error);
throw error;
}
};