---
name: IMX[맥락] IMAP 메일 기능 확장
description: 왜 이 기능들을 추가하는가, 핵심 결정 근거
type: 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:...">` 권장
