import nodemailer from 'nodemailer'; import handlebars from 'handlebars'; import fs from 'fs'; import path from 'path'; import i18next from 'i18next'; // Nodemailer Transporter 생성 const transporter = nodemailer.createTransport({ host: process.env.Email_Host, port: parseInt(process.env.Email_Port || '465'), secure: process.env.Email_Secure === 'true', auth: { user: process.env.Email_User_Name, pass: process.env.Email_Password, }, }); // // Handlebars 템플릿 로더 함수 // function loadTemplate(templateName: string, data: Record) { // const templatePath = path.join(process.cwd(), 'lib', 'mail', 'templates', `${templateName}.hbs`); // const source = fs.readFileSync(templatePath, 'utf8'); // const template = handlebars.compile(source); // return template(data); // } function applyLayout(layoutName: string, content: string, context: Record) { const layoutPath = path.join(process.cwd(), 'lib', 'mail', 'layouts', `${layoutName}.hbs`); const layoutSource = fs.readFileSync(layoutPath, 'utf8'); const layoutTemplate = handlebars.compile(layoutSource); return layoutTemplate({ ...context, body: content }); } // Partials 자동 등록 function registerPartials() { const partialsDir = path.join(process.cwd(), 'lib', 'mail', 'partials'); const filenames = fs.readdirSync(partialsDir); filenames.forEach((filename) => { const name = path.parse(filename).name; const filepath = path.join(partialsDir, filename); const source = fs.readFileSync(filepath, 'utf8'); handlebars.registerPartial(name, source); // {{> header }}, {{> footer }} }); } // 템플릿 불러오기 + layout/partials 적용 function loadTemplate(templateName: string, context: Record, layout = 'base') { registerPartials(); const templatePath = path.join(process.cwd(), 'lib', 'mail', 'templates', `${templateName}.hbs`); const source = fs.readFileSync(templatePath, 'utf8'); const template = handlebars.compile(source); const content = template(context); // 본문 먼저 처리 return applyLayout(layout, content, context); // base.hbs로 감싸기 } handlebars.registerHelper('t', function(key: string, options: any) { // options.hash에는 Handlebars에서 넘긴 named parameter들(location=location 등)이 들어있음 return i18next.t(key, options.hash || {}); }); export { transporter, loadTemplate };