2.4 KiB
2.4 KiB
name, description, type
| name | description | type |
|---|---|---|
| IMX[맥락] IMAP 메일 기능 확장 | 왜 이 기능들을 추가하는가, 핵심 결정 근거 | context |
IMX 맥락 — IMAP 메일 기능 확장
왜 하는가
ERP 시스템에서 메일 확인만 되면 의미가 없음. 거래처 메일 수신 후 바로 답장, 견적서 첨부파일 저장, 담당자 전달까지 워크플로우가 연결되어야 실용적.
핵심 결정 + 근거
SMTP 서비스 분리 (userMailSmtpService.ts)
- IMAP(수신)과 SMTP(송신)은 프로토콜 자체가 다름
- 파일 분리로 각각 독립적으로 교체/테스트 가능
- nodemailer는 이미 설치됨 (추가 의존성 없음)
TipTap v2 선택 (메일 에디터)
- ProseMirror 기반 → 안정적, 확장 용이
@tiptap/react공식 패키지 → Next.js 15 호환- Quill보다 번들 크기 작음 (~100KB vs ~200KB)
- dynamic import (
ssr: false)로 SSR 문제 회피
첨부파일 스트리밍
- 서버에 임시 저장하지 않음 → 디스크 절약, 보안
imapflow client.download()→stream/promises pipeline()→ HTTP 응답- 대용량 파일도 메모리 부담 없음
메일 삭제 = Trash 이동
- 즉시 삭제(
messageDelete) 대신 Trash 폴더 이동 - 실수로 삭제 시 복구 가능
- Gmail/wace.me 모두 Trash 폴더 표준 지원
폴더 구조 표시
client.list({ statusQuery: { unseen: true } })로 미읽음 수 포함- 폴더 클릭 시 기존 스트리밍 로직 재활용 (folder 파라미터 추가)
답장/전달 RFC 준수
inReplyTo,references헤더 → 메일 클라이언트에서 스레드로 묶임<blockquote>인용 → Gmail/Outlook 모두 올바르게 렌더링
관련 파일
backend-node/src/services/userMailImapService.ts— IMAP 수신 로직backend-node/src/services/imapConnectionPool.ts— 커넥션 풀 (건드리지 않음)backend-node/src/services/mailCache.ts— TTL 캐시 (건드리지 않음)frontend/app/(main)/mail/imap/page.tsx— 메인 UI
기술 참고
- imapflow
client.list()→ statusQuery 옵션으로 unseen 포함 - imapflow
client.messageMove(seqno, folder)→ UID 기반 이동 - imapflow
client.download(seqno, partId)→ ReadableStream 반환 - nodemailer
createTransport({ host, port, secure, auth })→sendMail() - RFC 2822 §3.6.4:
In-Reply-To,References헤더 - W3C HTML Threading:
<blockquote cite="mid:...">권장