메일관리 콘솔로그 주석처리 세이브

This commit is contained in:
leeheejin
2025-10-02 18:22:58 +09:00
parent bf58e0c878
commit b4c5be1f17
28 changed files with 3081 additions and 460 deletions

View File

@@ -3,12 +3,28 @@ 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, subject: req.body.subject });
const { accountId, templateId, to, subject, variables, customHtml } = req.body;
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 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) {
@@ -34,14 +50,53 @@ export class MailSendSimpleController {
});
}
// 첨부파일 처리 (한글 파일명 지원)
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,
to,
cc,
bcc,
subject,
variables,
customHtml,
attachments: attachments.length > 0 ? attachments : undefined,
});
if (result.success) {

View File

@@ -0,0 +1,140 @@
import { Request, Response } from 'express';
import { mailSentHistoryService } from '../services/mailSentHistoryService';
export class MailSentHistoryController {
/**
* 발송 이력 목록 조회
*/
async getList(req: Request, res: Response) {
try {
const query = {
page: req.query.page ? parseInt(req.query.page as string) : undefined,
limit: req.query.limit ? parseInt(req.query.limit as string) : undefined,
searchTerm: req.query.searchTerm as string | undefined,
status: req.query.status as 'success' | 'failed' | 'all' | undefined,
accountId: req.query.accountId as string | undefined,
startDate: req.query.startDate as string | undefined,
endDate: req.query.endDate as string | undefined,
sortBy: req.query.sortBy as 'sentAt' | 'subject' | undefined,
sortOrder: req.query.sortOrder as 'asc' | 'desc' | undefined,
};
const result = await mailSentHistoryService.getSentMailList(query);
return res.json({
success: true,
data: result,
});
} catch (error: unknown) {
const err = error as Error;
console.error('발송 이력 목록 조회 실패:', err);
return res.status(500).json({
success: false,
message: '발송 이력 조회 중 오류가 발생했습니다.',
error: err.message,
});
}
}
/**
* 특정 발송 이력 상세 조회
*/
async getById(req: Request, res: Response) {
try {
const { id } = req.params;
if (!id) {
return res.status(400).json({
success: false,
message: '발송 이력 ID가 필요합니다.',
});
}
const history = await mailSentHistoryService.getSentMailById(id);
if (!history) {
return res.status(404).json({
success: false,
message: '발송 이력을 찾을 수 없습니다.',
});
}
return res.json({
success: true,
data: history,
});
} catch (error: unknown) {
const err = error as Error;
console.error('발송 이력 조회 실패:', err);
return res.status(500).json({
success: false,
message: '발송 이력 조회 중 오류가 발생했습니다.',
error: err.message,
});
}
}
/**
* 발송 이력 삭제
*/
async deleteById(req: Request, res: Response) {
try {
const { id } = req.params;
if (!id) {
return res.status(400).json({
success: false,
message: '발송 이력 ID가 필요합니다.',
});
}
const success = await mailSentHistoryService.deleteSentMail(id);
if (!success) {
return res.status(404).json({
success: false,
message: '발송 이력을 찾을 수 없습니다.',
});
}
return res.json({
success: true,
message: '발송 이력이 삭제되었습니다.',
});
} catch (error: unknown) {
const err = error as Error;
console.error('발송 이력 삭제 실패:', err);
return res.status(500).json({
success: false,
message: '발송 이력 삭제 중 오류가 발생했습니다.',
error: err.message,
});
}
}
/**
* 통계 조회
*/
async getStatistics(req: Request, res: Response) {
try {
const accountId = req.query.accountId as string | undefined;
const stats = await mailSentHistoryService.getStatistics(accountId);
return res.json({
success: true,
data: stats,
});
} catch (error: unknown) {
const err = error as Error;
console.error('통계 조회 실패:', err);
return res.status(500).json({
success: false,
message: '통계 조회 중 오류가 발생했습니다.',
error: err.message,
});
}
}
}
export const mailSentHistoryController = new MailSentHistoryController();