import { Request, Response } from 'express'; import { mailSendSimpleService } from '../services/mailSendSimpleService'; export class MailSendSimpleController { /** * 메일 발송 (단건 또는 소규모) - 첨부파일 지원 */ async sendMail(req: Request, res: Response) { try { console.log('📧 메일 발송 요청 수신:', { accountId: req.body.accountId, to: req.body.to, cc: req.body.cc, bcc: req.body.bcc, subject: req.body.subject, attachments: req.files ? (req.files as Express.Multer.File[]).length : 0, }); // FormData에서 JSON 문자열 파싱 const accountId = req.body.accountId; const templateId = req.body.templateId; const modifiedTemplateComponents = req.body.modifiedTemplateComponents ? JSON.parse(req.body.modifiedTemplateComponents) : undefined; // 🎯 수정된 템플릿 컴포넌트 const to = req.body.to ? JSON.parse(req.body.to) : []; const cc = req.body.cc ? JSON.parse(req.body.cc) : undefined; const bcc = req.body.bcc ? JSON.parse(req.body.bcc) : undefined; const subject = req.body.subject; const variables = req.body.variables ? JSON.parse(req.body.variables) : undefined; const customHtml = req.body.customHtml; // 필수 파라미터 검증 if (!accountId || !to || !Array.isArray(to) || to.length === 0) { console.log('❌ 필수 파라미터 누락'); return res.status(400).json({ success: false, message: '계정 ID와 수신자 이메일이 필요합니다.', }); } if (!subject) { return res.status(400).json({ success: false, message: '메일 제목이 필요합니다.', }); } // 템플릿 또는 커스텀 HTML 중 하나는 있어야 함 if (!templateId && !customHtml) { return res.status(400).json({ success: false, message: '템플릿 또는 메일 내용이 필요합니다.', }); } // 첨부파일 처리 (한글 파일명 지원) const attachments: Array<{ filename: string; path: string; contentType?: string }> = []; if (req.files && Array.isArray(req.files)) { const files = req.files as Express.Multer.File[]; // 프론트엔드에서 전송한 정규화된 파일명 사용 (한글-분석.txt 방식) let parsedFileNames: string[] = []; if (req.body.fileNames) { try { parsedFileNames = JSON.parse(req.body.fileNames); console.log('📎 프론트엔드에서 받은 파일명들:', parsedFileNames); } catch (e) { console.warn('파일명 파싱 실패, multer originalname 사용'); } } files.forEach((file, index) => { // 클라이언트에서 전송한 파일명 우선 사용, 없으면 multer의 originalname 사용 let originalName = parsedFileNames[index] || file.originalname; // NFC 정규화 확실히 수행 originalName = originalName.normalize('NFC'); attachments.push({ filename: originalName, path: file.path, contentType: file.mimetype, }); }); console.log('📎 최종 첨부파일 정보:', attachments.map(a => ({ filename: a.filename, path: a.path.split('/').pop() }))); } // 메일 발송 const result = await mailSendSimpleService.sendMail({ accountId, templateId, modifiedTemplateComponents, // 🎯 수정된 템플릿 컴포넌트 전달 to, cc, bcc, subject, variables, customHtml, attachments: attachments.length > 0 ? attachments : undefined, }); if (result.success) { return res.json({ success: true, data: result, message: '메일이 발송되었습니다.', }); } else { return res.status(500).json({ success: false, message: result.error || '메일 발송 실패', }); } } catch (error: unknown) { const err = error as Error; return res.status(500).json({ success: false, message: '메일 발송 중 오류가 발생했습니다.', error: err.message, }); } } /** * 대량 메일 발송 */ async sendBulkMail(req: Request, res: Response) { try { const { accountId, templateId, subject, recipients } = req.body; // 필수 파라미터 검증 if (!accountId || !templateId || !subject || !recipients || !Array.isArray(recipients)) { return res.status(400).json({ success: false, message: '필수 파라미터가 누락되었습니다.', }); } if (recipients.length === 0) { return res.status(400).json({ success: false, message: '수신자가 없습니다.', }); } console.log(`📧 대량 발송 요청: ${recipients.length}명`); // 대량 발송 실행 const result = await mailSendSimpleService.sendBulkMail({ accountId, templateId, subject, recipients, }); return res.json({ success: true, data: result, message: `${result.success}/${result.total} 건 발송 완료`, }); } catch (error: unknown) { const err = error as Error; console.error('❌ 대량 발송 오류:', err); return res.status(500).json({ success: false, message: '대량 발송 중 오류가 발생했습니다.', error: err.message, }); } } /** * SMTP 연결 테스트 */ async testConnection(req: Request, res: Response) { try { const { accountId } = req.body; if (!accountId) { return res.status(400).json({ success: false, message: '계정 ID가 필요합니다.', }); } const result = await mailSendSimpleService.testConnection(accountId); return res.json(result); } catch (error: unknown) { const err = error as Error; return res.status(500).json({ success: false, message: '연결 테스트 실패', error: err.message, }); } } } export const mailSendSimpleController = new MailSendSimpleController();