159 lines
4.9 KiB
TypeScript
159 lines
4.9 KiB
TypeScript
import nodemailer from "nodemailer";
|
|
|
|
import { ACTIVATE_STATUSES } from "@/lib/constants";
|
|
import { logger } from "@/lib/logger";
|
|
import { getMailConfig } from "@/lib/mail-config";
|
|
import {
|
|
getAccountTypePlayerCount,
|
|
getAccountTypePrice,
|
|
} from "@/lib/utils";
|
|
|
|
const CTX = "mail";
|
|
|
|
function createTransporter() {
|
|
const cfg = getMailConfig();
|
|
|
|
return nodemailer.createTransport({
|
|
host: cfg.smtpHost,
|
|
port: cfg.smtpPort,
|
|
secure: cfg.smtpSecure,
|
|
auth: {
|
|
user: cfg.smtpUser,
|
|
pass: cfg.smtpPassword,
|
|
},
|
|
});
|
|
}
|
|
|
|
type SendMailOptions = {
|
|
to: string;
|
|
subject: string;
|
|
html: string;
|
|
};
|
|
|
|
const isDetailedLog = () => process.env.APP_ENV !== "production";
|
|
|
|
async function sendMail(options: SendMailOptions): Promise<boolean> {
|
|
const cfg = getMailConfig();
|
|
const detailed = isDetailedLog();
|
|
|
|
if (!cfg.sendEnabled) {
|
|
logger.info(CTX, "send skipped (MAIL_SEND_ENABLED=false)", {
|
|
to: cfg.overrideTo ?? options.to,
|
|
subject: options.subject,
|
|
});
|
|
return false;
|
|
}
|
|
|
|
const to = cfg.overrideTo ?? options.to;
|
|
const bcc = cfg.bccAddress || undefined;
|
|
|
|
if (detailed) {
|
|
logger.debug(CTX, "sending", {
|
|
to,
|
|
...(bcc && { bcc }),
|
|
subject: options.subject,
|
|
smtp: `${cfg.smtpUser}@${cfg.smtpHost}:${cfg.smtpPort}`,
|
|
...(cfg.overrideTo && { overrideTo: cfg.overrideTo }),
|
|
});
|
|
}
|
|
|
|
const t0 = Date.now();
|
|
try {
|
|
const transporter = createTransporter();
|
|
const info = await transporter.sendMail({
|
|
from: `"${cfg.fromName}" <${cfg.fromAddress}>`,
|
|
replyTo: cfg.fromAddress,
|
|
to,
|
|
bcc,
|
|
subject: options.subject,
|
|
html: options.html,
|
|
});
|
|
const duration = Date.now() - t0;
|
|
|
|
if (detailed) {
|
|
logger.info(CTX, "send ok", {
|
|
to,
|
|
subject: options.subject,
|
|
messageId: info.messageId,
|
|
duration,
|
|
});
|
|
} else {
|
|
logger.info(CTX, "send ok", { duration });
|
|
}
|
|
return true;
|
|
} catch (err) {
|
|
const duration = Date.now() - t0;
|
|
|
|
if (detailed) {
|
|
logger.error(CTX, "send failed", {
|
|
to,
|
|
subject: options.subject,
|
|
duration,
|
|
error: err instanceof Error ? err.message : String(err),
|
|
...(err instanceof Error && err.stack && { stack: err.stack }),
|
|
});
|
|
} else {
|
|
logger.error(CTX, "send failed", { duration });
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export async function sendExtensionDoneEmail(
|
|
maestroName: string,
|
|
maestroEmail: string,
|
|
newAvailableDate: string
|
|
): Promise<boolean> {
|
|
const subject = `[초코마에] ${maestroName} - 마에스트로 계정 유효기간 연장 완료`;
|
|
const html = `안녕하세요.<br/>
|
|
[초코마에] 마에스트로 계정의 유효기간 연장을 신청해 주셔서 감사합니다.<br/>
|
|
<br/>
|
|
${maestroName} - 마에스트로 계정의 유효기간이 +1년 연장되었습니다.<br/>
|
|
* 새로운 유효기간 : ${newAvailableDate}<br/>
|
|
<br/>
|
|
* 상위 요금제로 업그레이드 하시면, 유효기간이 업그레이드한 날짜로부터 1년으로 갱신됩니다.<br/>
|
|
* 유효기간이 끝나면, 비활성화된 계정과 그 안에 있는 모든 정보가 6개월 후에 자동 삭제됩니다.<br/>
|
|
<br/>
|
|
감사합니다.`;
|
|
|
|
return sendMail({ to: maestroEmail, subject, html });
|
|
}
|
|
|
|
export async function sendUpgradeDoneEmail(
|
|
maestroName: string,
|
|
maestroEmail: string,
|
|
registeredActivateStatus: number,
|
|
registeredAccountType: number,
|
|
requestedAccountType: number,
|
|
newAvailableDate: string
|
|
): Promise<boolean> {
|
|
const subject = `[초코마에] ${maestroName} - 마에스트로 계정의 요금제 업그레이드 완료 알림`;
|
|
|
|
const prevStudentCount = getAccountTypePlayerCount(registeredAccountType);
|
|
const upgradeStudentCount = getAccountTypePlayerCount(requestedAccountType);
|
|
const upgradePrice = getAccountTypePrice(requestedAccountType).toLocaleString("ko-KR");
|
|
|
|
let upgradeFromText: string;
|
|
if (registeredActivateStatus === ACTIVATE_STATUSES.TRIAL) {
|
|
upgradeFromText = `${prevStudentCount}명 (0원 : 무료 체험 기간)`;
|
|
} else {
|
|
const prevPrice = getAccountTypePrice(registeredAccountType).toLocaleString("ko-KR");
|
|
upgradeFromText = `${prevStudentCount}명 (${prevPrice}원)`;
|
|
}
|
|
|
|
const html = `안녕하세요.<br/>
|
|
[초코마에] 마에스트로 계정 요금제 업그레이드를 신청해주셔서 감사합니다.<br/>
|
|
<br/>
|
|
${maestroName} - 마에스트로 계정의 요금제가 [ ${upgradeFromText} ] 에서 [ ${upgradeStudentCount}명 (${upgradePrice}원) ] 으로 업그레이드 되었습니다.<br/>
|
|
<br/>
|
|
* 마에스트로 계정 유효기간이 오늘부터 1년으로 설정되었습니다.<br/>
|
|
<br/>
|
|
<br/>
|
|
등록하신 마에스트로 계정 정보는 마에스트로 로그인 후, [계정 정보 수정] 화면에서 변경이 가능합니다.<br/>
|
|
(변경 가능 정보 : 마에스트로 아이디, 이메일, 암호)<br/>
|
|
<br/>
|
|
감사합니다.`;
|
|
|
|
return sendMail({ to: maestroEmail, subject, html });
|
|
}
|