Files
vexplor/backend-node/src/services/userMailSmtpService.ts
syc0123 4c42cc7b53 feat: 사용자 메일 관리 IMAP 구현
- IMAP 계정 등록/수정/삭제/연결테스트
- SSE 스트리밍으로 메일 목록 로드 (폴더별 지원)
- 메일 상세 조회, 읽음 처리, 삭제(휴지통 이동), 폴더 이동
- 첨부파일 다운로드 (ReadableStream 진행바)
- SMTP 발송, 답장, 전달
- imapConnectionPool, mailCache 서비스
- encryptionService Node 22+ 호환 수정
- authMiddleware query token 지원 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:17:20 +09:00

64 lines
2.1 KiB
TypeScript

import nodemailer from 'nodemailer';
import { encryptionService } from './encryptionService';
import { UserMailAccount } from './userMailAccountService';
export interface SendMailDto {
to: string;
cc?: string;
subject: string;
html: string;
text?: string;
inReplyTo?: string;
references?: string;
}
class UserMailSmtpService {
private getSmtpConfig(account: UserMailAccount) {
const decryptedPassword = encryptionService.decrypt(account.password);
// IMAP host에서 SMTP host 추론
const smtpHost = account.host
.replace(/^imap\./, 'smtp.')
.replace(/^mail\./, 'smtp.');
// 포트 추론: TLS → 465, plain → 587
const port = account.useTls ? 465 : 587;
return {
host: smtpHost,
port,
secure: account.useTls, // 465: true, 587: false (STARTTLS)
auth: { user: account.username, pass: decryptedPassword },
tls: { rejectUnauthorized: false },
};
}
async sendMail(account: UserMailAccount, dto: SendMailDto): Promise<{ success: boolean; message: string }> {
try {
const transporter = nodemailer.createTransport(this.getSmtpConfig(account));
await transporter.sendMail({
from: `${account.displayName} <${account.email}>`,
to: dto.to,
cc: dto.cc,
subject: dto.subject,
html: dto.html,
text: dto.text,
inReplyTo: dto.inReplyTo,
references: dto.references,
});
return { success: true, message: '발송 완료' };
} catch (err) {
return { success: false, message: err instanceof Error ? err.message : '발송 실패' };
}
}
async testSmtpConnection(account: UserMailAccount): Promise<{ success: boolean; message: string }> {
try {
const transporter = nodemailer.createTransport(this.getSmtpConfig(account));
await transporter.verify();
return { success: true, message: 'SMTP 연결 성공' };
} catch (err) {
return { success: false, message: err instanceof Error ? err.message : 'SMTP 연결 실패' };
}
}
}
export const userMailSmtpService = new UserMailSmtpService();