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

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

@@ -0,0 +1,232 @@
/**
* 메일 발송 이력 관리 서비스 (파일 기반)
*/
import fs from 'fs';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';
import {
SentMailHistory,
SentMailListQuery,
SentMailListResponse,
AttachmentInfo,
} from '../types/mailSentHistory';
const SENT_MAIL_DIR = path.join(__dirname, '../../data/mail-sent');
class MailSentHistoryService {
constructor() {
// 디렉토리 생성 (없으면)
if (!fs.existsSync(SENT_MAIL_DIR)) {
fs.mkdirSync(SENT_MAIL_DIR, { recursive: true });
}
}
/**
* 발송 이력 저장
*/
async saveSentMail(data: Omit<SentMailHistory, 'id' | 'sentAt'>): Promise<SentMailHistory> {
const history: SentMailHistory = {
id: uuidv4(),
sentAt: new Date().toISOString(),
...data,
};
const filePath = path.join(SENT_MAIL_DIR, `${history.id}.json`);
fs.writeFileSync(filePath, JSON.stringify(history, null, 2), 'utf-8');
console.log('💾 발송 이력 저장:', history.id);
return history;
}
/**
* 발송 이력 목록 조회 (필터링, 페이징)
*/
async getSentMailList(query: SentMailListQuery): Promise<SentMailListResponse> {
const {
page = 1,
limit = 20,
searchTerm = '',
status = 'all',
accountId,
startDate,
endDate,
sortBy = 'sentAt',
sortOrder = 'desc',
} = query;
// 모든 발송 이력 파일 읽기
const files = fs.readdirSync(SENT_MAIL_DIR).filter((f) => f.endsWith('.json'));
let allHistory: SentMailHistory[] = [];
for (const file of files) {
try {
const filePath = path.join(SENT_MAIL_DIR, file);
const content = fs.readFileSync(filePath, 'utf-8');
const history: SentMailHistory = JSON.parse(content);
allHistory.push(history);
} catch (error) {
console.error(`발송 이력 파일 읽기 실패: ${file}`, error);
}
}
// 필터링
let filtered = allHistory;
// 상태 필터
if (status !== 'all') {
filtered = filtered.filter((h) => h.status === status);
}
// 계정 필터
if (accountId) {
filtered = filtered.filter((h) => h.accountId === accountId);
}
// 날짜 필터
if (startDate) {
filtered = filtered.filter((h) => h.sentAt >= startDate);
}
if (endDate) {
filtered = filtered.filter((h) => h.sentAt <= endDate);
}
// 검색어 필터 (제목, 받는사람)
if (searchTerm) {
const term = searchTerm.toLowerCase();
filtered = filtered.filter(
(h) =>
h.subject.toLowerCase().includes(term) ||
h.to.some((email) => email.toLowerCase().includes(term)) ||
(h.cc && h.cc.some((email) => email.toLowerCase().includes(term)))
);
}
// 정렬
filtered.sort((a, b) => {
let aVal: any = a[sortBy];
let bVal: any = b[sortBy];
if (sortBy === 'sentAt') {
aVal = new Date(aVal).getTime();
bVal = new Date(bVal).getTime();
} else {
aVal = aVal ? aVal.toLowerCase() : '';
bVal = bVal ? bVal.toLowerCase() : '';
}
if (sortOrder === 'asc') {
return aVal > bVal ? 1 : -1;
} else {
return aVal < bVal ? 1 : -1;
}
});
// 페이징
const total = filtered.length;
const totalPages = Math.ceil(total / limit);
const start = (page - 1) * limit;
const end = start + limit;
const items = filtered.slice(start, end);
return {
items,
total,
page,
limit,
totalPages,
};
}
/**
* 특정 발송 이력 조회
*/
async getSentMailById(id: string): Promise<SentMailHistory | null> {
const filePath = path.join(SENT_MAIL_DIR, `${id}.json`);
if (!fs.existsSync(filePath)) {
return null;
}
try {
const content = fs.readFileSync(filePath, 'utf-8');
return JSON.parse(content) as SentMailHistory;
} catch (error) {
console.error('발송 이력 읽기 실패:', error);
return null;
}
}
/**
* 발송 이력 삭제
*/
async deleteSentMail(id: string): Promise<boolean> {
const filePath = path.join(SENT_MAIL_DIR, `${id}.json`);
if (!fs.existsSync(filePath)) {
return false;
}
try {
fs.unlinkSync(filePath);
console.log('🗑️ 발송 이력 삭제:', id);
return true;
} catch (error) {
console.error('발송 이력 삭제 실패:', error);
return false;
}
}
/**
* 통계 조회
*/
async getStatistics(accountId?: string): Promise<{
totalSent: number;
successCount: number;
failedCount: number;
todayCount: number;
thisMonthCount: number;
successRate: number;
}> {
const files = fs.readdirSync(SENT_MAIL_DIR).filter((f) => f.endsWith('.json'));
let allHistory: SentMailHistory[] = [];
for (const file of files) {
try {
const filePath = path.join(SENT_MAIL_DIR, file);
const content = fs.readFileSync(filePath, 'utf-8');
const history: SentMailHistory = JSON.parse(content);
// 계정 필터
if (!accountId || history.accountId === accountId) {
allHistory.push(history);
}
} catch (error) {
console.error(`발송 이력 파일 읽기 실패: ${file}`, error);
}
}
const now = new Date();
const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()).toISOString();
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1).toISOString();
const totalSent = allHistory.length;
const successCount = allHistory.filter((h) => h.status === 'success').length;
const failedCount = allHistory.filter((h) => h.status === 'failed').length;
const todayCount = allHistory.filter((h) => h.sentAt >= todayStart).length;
const thisMonthCount = allHistory.filter((h) => h.sentAt >= monthStart).length;
const successRate = totalSent > 0 ? Math.round((successCount / totalSent) * 100) : 0;
return {
totalSent,
successCount,
failedCount,
todayCount,
thisMonthCount,
successRate,
};
}
}
export const mailSentHistoryService = new MailSentHistoryService();