메일관리 콘솔로그 주석처리 세이브
This commit is contained in:
@@ -3,9 +3,11 @@
|
||||
* IMAP 연결 및 메일 목록 조회
|
||||
*/
|
||||
|
||||
import * as Imap from 'imap';
|
||||
// CommonJS 모듈이므로 require 사용
|
||||
const Imap = require('imap');
|
||||
import { simpleParser } from 'mailparser';
|
||||
import { mailAccountFileService } from './mailAccountFileService';
|
||||
import { encryptionService } from './encryptionService';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
@@ -57,6 +59,20 @@ export class MailReceiveBasicService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP 포트에서 IMAP 포트 추론
|
||||
*/
|
||||
private inferImapPort(smtpPort: number, imapPort?: number): number {
|
||||
if (imapPort) return imapPort;
|
||||
|
||||
if (smtpPort === 465 || smtpPort === 587) {
|
||||
return 993; // IMAPS (SSL/TLS)
|
||||
} else if (smtpPort === 25) {
|
||||
return 143; // IMAP (no encryption)
|
||||
}
|
||||
return 993; // 기본값: IMAPS
|
||||
}
|
||||
|
||||
/**
|
||||
* IMAP 연결 생성
|
||||
*/
|
||||
@@ -80,27 +96,47 @@ export class MailReceiveBasicService {
|
||||
throw new Error('메일 계정을 찾을 수 없습니다.');
|
||||
}
|
||||
|
||||
// 비밀번호 복호화
|
||||
const decryptedPassword = encryptionService.decrypt(account.smtpPassword);
|
||||
|
||||
// IMAP 설정
|
||||
const accountAny = account as any;
|
||||
const imapConfig: ImapConfig = {
|
||||
user: account.email,
|
||||
password: account.smtpPassword, // 이미 복호화됨
|
||||
host: account.smtpHost,
|
||||
port: account.smtpPort === 587 ? 993 : account.smtpPort, // SMTP 587 -> IMAP 993
|
||||
password: decryptedPassword,
|
||||
host: accountAny.imapHost || account.smtpHost,
|
||||
port: this.inferImapPort(account.smtpPort, accountAny.imapPort),
|
||||
tls: true,
|
||||
};
|
||||
|
||||
console.log(`📧 IMAP 연결 시도 - 호스트: ${imapConfig.host}, 포트: ${imapConfig.port}, 이메일: ${imapConfig.user}`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const imap = this.createImapConnection(imapConfig);
|
||||
const mails: ReceivedMail[] = [];
|
||||
|
||||
// 30초 타임아웃 설정
|
||||
const timeout = setTimeout(() => {
|
||||
console.error('❌ IMAP 연결 타임아웃 (30초)');
|
||||
imap.end();
|
||||
reject(new Error('IMAP 연결 타임아웃'));
|
||||
}, 30000);
|
||||
|
||||
imap.once('ready', () => {
|
||||
console.log('✅ IMAP 연결 성공! INBOX 열기 시도...');
|
||||
clearTimeout(timeout);
|
||||
|
||||
imap.openBox('INBOX', true, (err: any, box: any) => {
|
||||
if (err) {
|
||||
console.error('❌ INBOX 열기 실패:', err);
|
||||
imap.end();
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
console.log(`📬 INBOX 열림 - 전체 메일 수: ${box.messages.total}`);
|
||||
const totalMessages = box.messages.total;
|
||||
if (totalMessages === 0) {
|
||||
console.log('📭 메일함이 비어있습니다');
|
||||
imap.end();
|
||||
return resolve([]);
|
||||
}
|
||||
@@ -109,15 +145,23 @@ export class MailReceiveBasicService {
|
||||
const start = Math.max(1, totalMessages - limit + 1);
|
||||
const end = totalMessages;
|
||||
|
||||
console.log(`📨 메일 가져오기 시작 - 범위: ${start}~${end}`);
|
||||
const fetch = imap.seq.fetch(`${start}:${end}`, {
|
||||
bodies: ['HEADER', 'TEXT'],
|
||||
struct: true,
|
||||
});
|
||||
|
||||
console.log(`📦 fetch 객체 생성 완료`);
|
||||
|
||||
let processedCount = 0;
|
||||
const totalToProcess = end - start + 1;
|
||||
|
||||
fetch.on('message', (msg: any, seqno: any) => {
|
||||
console.log(`📬 메일 #${seqno} 처리 시작`);
|
||||
let header: string = '';
|
||||
let body: string = '';
|
||||
let attributes: any = null;
|
||||
let bodiesReceived = 0;
|
||||
|
||||
msg.on('body', (stream: any, info: any) => {
|
||||
let buffer = '';
|
||||
@@ -130,6 +174,7 @@ export class MailReceiveBasicService {
|
||||
} else {
|
||||
body = buffer;
|
||||
}
|
||||
bodiesReceived++;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -137,50 +182,88 @@ export class MailReceiveBasicService {
|
||||
attributes = attrs;
|
||||
});
|
||||
|
||||
msg.once('end', async () => {
|
||||
try {
|
||||
const parsed = await simpleParser(header + '\r\n\r\n' + body);
|
||||
msg.once('end', () => {
|
||||
// body 데이터를 모두 받을 때까지 대기
|
||||
const waitForBodies = setInterval(async () => {
|
||||
if (bodiesReceived >= 2 || (header && body)) {
|
||||
clearInterval(waitForBodies);
|
||||
|
||||
try {
|
||||
const parsed = await simpleParser(header + '\r\n\r\n' + body);
|
||||
|
||||
const fromAddress = Array.isArray(parsed.from) ? parsed.from[0] : parsed.from;
|
||||
const toAddress = Array.isArray(parsed.to) ? parsed.to[0] : parsed.to;
|
||||
const fromAddress = Array.isArray(parsed.from) ? parsed.from[0] : parsed.from;
|
||||
const toAddress = Array.isArray(parsed.to) ? parsed.to[0] : parsed.to;
|
||||
|
||||
const mail: ReceivedMail = {
|
||||
id: `${accountId}-${seqno}`,
|
||||
messageId: parsed.messageId || `${seqno}`,
|
||||
from: fromAddress?.text || 'Unknown',
|
||||
to: toAddress?.text || '',
|
||||
subject: parsed.subject || '(제목 없음)',
|
||||
date: parsed.date || new Date(),
|
||||
preview: this.extractPreview(parsed.text || parsed.html || ''),
|
||||
isRead: attributes?.flags?.includes('\\Seen') || false,
|
||||
hasAttachments: (parsed.attachments?.length || 0) > 0,
|
||||
};
|
||||
const mail: ReceivedMail = {
|
||||
id: `${accountId}-${seqno}`,
|
||||
messageId: parsed.messageId || `${seqno}`,
|
||||
from: fromAddress?.text || 'Unknown',
|
||||
to: toAddress?.text || '',
|
||||
subject: parsed.subject || '(제목 없음)',
|
||||
date: parsed.date || new Date(),
|
||||
preview: this.extractPreview(parsed.text || parsed.html || ''),
|
||||
isRead: attributes?.flags?.includes('\\Seen') || false,
|
||||
hasAttachments: (parsed.attachments?.length || 0) > 0,
|
||||
};
|
||||
|
||||
mails.push(mail);
|
||||
} catch (parseError) {
|
||||
console.error('메일 파싱 오류:', parseError);
|
||||
}
|
||||
mails.push(mail);
|
||||
console.log(`✓ 메일 #${seqno} 파싱 완료 (${mails.length}/${totalToProcess})`);
|
||||
processedCount++;
|
||||
} catch (parseError) {
|
||||
console.error(`메일 #${seqno} 파싱 오류:`, parseError);
|
||||
processedCount++;
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
});
|
||||
|
||||
fetch.once('error', (fetchErr: any) => {
|
||||
console.error('❌ 메일 fetch 에러:', fetchErr);
|
||||
imap.end();
|
||||
reject(fetchErr);
|
||||
});
|
||||
|
||||
fetch.once('end', () => {
|
||||
imap.end();
|
||||
// 최신 메일이 위로 오도록 정렬
|
||||
mails.sort((a, b) => b.date.getTime() - a.date.getTime());
|
||||
resolve(mails);
|
||||
console.log(`📭 fetch 종료 - 처리 완료 대기 중... (현재: ${mails.length}개)`);
|
||||
|
||||
// 모든 메일 처리가 완료될 때까지 대기
|
||||
const checkComplete = setInterval(() => {
|
||||
console.log(`⏳ 대기 중 - 처리됨: ${processedCount}/${totalToProcess}, 메일: ${mails.length}개`);
|
||||
if (processedCount >= totalToProcess) {
|
||||
clearInterval(checkComplete);
|
||||
console.log(`✅ 메일 가져오기 완료 - 총 ${mails.length}개`);
|
||||
imap.end();
|
||||
// 최신 메일이 위로 오도록 정렬
|
||||
mails.sort((a, b) => b.date.getTime() - a.date.getTime());
|
||||
console.log(`📤 메일 목록 반환: ${mails.length}개`);
|
||||
resolve(mails);
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// 최대 10초 대기
|
||||
setTimeout(() => {
|
||||
clearInterval(checkComplete);
|
||||
console.log(`⚠️ 타임아웃 - 부분 반환: ${mails.length}/${totalToProcess}개`);
|
||||
imap.end();
|
||||
mails.sort((a, b) => b.date.getTime() - a.date.getTime());
|
||||
resolve(mails);
|
||||
}, 10000);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
imap.once('error', (imapErr: any) => {
|
||||
console.error('❌ IMAP 연결 에러:', imapErr.message || imapErr);
|
||||
clearTimeout(timeout);
|
||||
reject(imapErr);
|
||||
});
|
||||
|
||||
imap.once('end', () => {
|
||||
console.log('🔌 IMAP 연결 종료');
|
||||
});
|
||||
|
||||
console.log('🔗 IMAP.connect() 호출...');
|
||||
imap.connect();
|
||||
});
|
||||
}
|
||||
@@ -206,11 +289,15 @@ export class MailReceiveBasicService {
|
||||
throw new Error('메일 계정을 찾을 수 없습니다.');
|
||||
}
|
||||
|
||||
// 비밀번호 복호화
|
||||
const decryptedPassword = encryptionService.decrypt(account.smtpPassword);
|
||||
|
||||
const accountAny = account as any;
|
||||
const imapConfig: ImapConfig = {
|
||||
user: account.email,
|
||||
password: account.smtpPassword,
|
||||
host: account.smtpHost,
|
||||
port: account.smtpPort === 587 ? 993 : account.smtpPort,
|
||||
password: decryptedPassword,
|
||||
host: accountAny.imapHost || account.smtpHost,
|
||||
port: this.inferImapPort(account.smtpPort, accountAny.imapPort),
|
||||
tls: true,
|
||||
};
|
||||
|
||||
@@ -302,11 +389,15 @@ export class MailReceiveBasicService {
|
||||
throw new Error('메일 계정을 찾을 수 없습니다.');
|
||||
}
|
||||
|
||||
// 비밀번호 복호화
|
||||
const decryptedPassword = encryptionService.decrypt(account.smtpPassword);
|
||||
|
||||
const accountAny = account as any;
|
||||
const imapConfig: ImapConfig = {
|
||||
user: account.email,
|
||||
password: account.smtpPassword,
|
||||
host: account.smtpHost,
|
||||
port: account.smtpPort === 587 ? 993 : account.smtpPort,
|
||||
password: decryptedPassword,
|
||||
host: accountAny.imapHost || account.smtpHost,
|
||||
port: this.inferImapPort(account.smtpPort, accountAny.imapPort),
|
||||
tls: true,
|
||||
};
|
||||
|
||||
@@ -352,13 +443,19 @@ export class MailReceiveBasicService {
|
||||
throw new Error('메일 계정을 찾을 수 없습니다.');
|
||||
}
|
||||
|
||||
// 비밀번호 복호화
|
||||
const decryptedPassword = encryptionService.decrypt(account.smtpPassword);
|
||||
// console.log(`🔐 IMAP 테스트 - 이메일: ${account.email}, 비밀번호 길이: ${decryptedPassword.length}`);
|
||||
|
||||
const accountAny = account as any;
|
||||
const imapConfig: ImapConfig = {
|
||||
user: account.email,
|
||||
password: account.smtpPassword,
|
||||
host: account.smtpHost,
|
||||
port: account.smtpPort === 587 ? 993 : account.smtpPort,
|
||||
password: decryptedPassword,
|
||||
host: accountAny.imapHost || account.smtpHost,
|
||||
port: this.inferImapPort(account.smtpPort, accountAny.imapPort),
|
||||
tls: true,
|
||||
};
|
||||
// console.log(`📧 IMAP 설정 - 호스트: ${imapConfig.host}, 포트: ${imapConfig.port}, TLS: ${imapConfig.tls}`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const imap = this.createImapConnection(imapConfig);
|
||||
@@ -408,11 +505,15 @@ export class MailReceiveBasicService {
|
||||
throw new Error('메일 계정을 찾을 수 없습니다.');
|
||||
}
|
||||
|
||||
// 비밀번호 복호화
|
||||
const decryptedPassword = encryptionService.decrypt(account.smtpPassword);
|
||||
|
||||
const accountAny = account as any;
|
||||
const imapConfig: ImapConfig = {
|
||||
user: account.email,
|
||||
password: account.smtpPassword,
|
||||
host: account.smtpHost,
|
||||
port: account.smtpPort === 587 ? 993 : account.smtpPort,
|
||||
password: decryptedPassword,
|
||||
host: accountAny.imapHost || account.smtpHost,
|
||||
port: this.inferImapPort(account.smtpPort, accountAny.imapPort),
|
||||
tls: true,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user