--- name: zioinfo-mail-orchestrator description: > zioinfo-mail 웹메일 시스템 구축 오케스트레이터. 지오정보기술 SMTP 서버(Postfix + Dovecot)를 활용한 React+FastAPI 웹메일 클라이언트를 workspace/zioinfo-mail/ 에 구축하고 서버(mail.zioinfo.co.kr:8025)에 배포한다. FastAPI IMAP/SMTP 프록시 백엔드, React 3-패널 메일 UI 프론트엔드, nginx+systemd 인프라를 에이전트 팀으로 병렬 구현한다. 다음 상황에서 반드시 사용: (1) 'webmail', '웹메일', 'zioinfo-mail', '메일 시스템 구축'; (2) '메일 클라이언트', '이메일 UI', 'IMAP 연동', 'SMTP 연동'; (3) mail.zioinfo.co.kr 관련 작업; (4) 다시 실행, 업데이트, 수정, 보완. --- # zioinfo-mail 웹메일 시스템 오케스트레이터 **실행 모드:** 하이브리드 - Phase 1 (인프라 검증): 서브 에이전트 (mail-infra-setup) - Phase 2 (Backend + Frontend 구현): **병렬 서브 에이전트** - Phase 3 (통합 배포): 에이전트 팀 (3명 협업) --- ## 시스템 개요 ``` 사용자 브라우저 ↓ HTTPS:8025 nginx (/var/www/mail) → React SPA ↓ /api/ FastAPI (127.0.0.1:8026) ↓ IMAP:993 (SSL) ↓ SMTP:587 (STARTTLS) Dovecot Postfix (읽기) (발송) ``` **기존 인프라:** | 항목 | 값 | |------|-----| | Postfix | active, `mail.zioinfo.co.kr` | | Dovecot | active, IMAP/POP3, maildir:~/Maildir | | TLS cert | `/etc/ssl/guardia/server.crt` | | 계정 | ythong / info / admin @zioinfo.co.kr | | 웹메일 URL | `https://mail.zioinfo.co.kr:8025` | --- ## Phase 0: 컨텍스트 확인 ``` workspace/zioinfo-mail/ 존재 여부: - 없음 → 초기 구현 (Phase 1부터 전체) - 있음 + backend/만 요청 → mail-backend-dev만 재실행 - 있음 + frontend/만 요청 → mail-frontend-dev만 재실행 - 있음 + 배포 요청 → Phase 3만 실행 ``` --- ## Phase 1: 인프라 사전 검증 (서브 에이전트) **mail-infra-setup** 에이전트 실행 (읽기 전용 검증): ```python # 검증 항목 1. IMAP localhost:993 접속 테스트 2. SMTP localhost:587 접속 테스트 3. 포트 8025/8026 사용 가능 여부 4. /opt/mail/, /var/www/mail/ 생성 가능 여부 5. Gitea zio/zioinfo-mail 저장소 존재 여부 ``` 결과를 `_workspace/infra-check.json`에 저장. IMAP/SMTP 접속 실패 시 → Postfix/Dovecot 설정 점검 후 재시도. --- ## Phase 2: Backend + Frontend 병렬 구현 (서브 에이전트) **mail-backend-dev** + **mail-frontend-dev** 동시 실행: ### mail-backend-dev 작업 목록 ``` workspace/zioinfo-mail/backend/ ├── main.py ← FastAPI 앱 (포트 8026) ├── auth.py ← IMAP 로그인 → JWT 발급 ├── imap_client.py ← aioimaplib 연결 풀 ├── smtp_client.py ← aiosmtplib 발송 ├── mail_parser.py ← 메일 파싱 (한글, 첨부파일) ├── models.py ← Pydantic 스키마 └── requirements.txt ``` **핵심 구현 포인트:** - JWT 페이로드에 IMAP 자격증명 AES 암호화 포함 - IMAP 연결 풀: 사용자당 1개 재사용 - 한글 제목/본문 인코딩: `chardet` + `email.header.decode_header` - 첨부파일: `/tmp/mail_attach_{uid}/` 임시 저장 후 스트리밍 ### mail-frontend-dev 작업 목록 ``` workspace/zioinfo-mail/frontend/ ├── package.json ← react, typescript, vite, axios, zustand, dompurify ├── vite.config.ts ← outDir: '../dist', proxy: /api → :8026 ├── src/ │ ├── App.tsx │ ├── pages/Login.tsx ← 로그인 │ ├── pages/Mail.tsx ← 3-패널 메인 │ ├── components/ │ │ ├── FolderTree.tsx ← 좌측 폴더 트리 │ │ ├── MailList.tsx ← 중앙 목록 │ │ ├── MailView.tsx ← 우측 본문 │ │ └── Compose.tsx ← 작성 모달 │ ├── api/mailApi.ts ← axios 클라이언트 │ └── store/mailStore.ts ← zustand ``` **Backend API 스펙** (`_workspace/api-spec.md` 참조): - Backend 완료 후 API 스펙 파일 생성 → Frontend에서 읽어 구현 --- ## Phase 3: 통합 배포 (에이전트 팀) 3명 팀 구성: mail-backend-dev + mail-frontend-dev + mail-infra-setup ### 3-1. Frontend 빌드 ```bash cd workspace/zioinfo-mail/frontend && npm run build # dist/ → workspace/zioinfo-mail/dist/ ``` ### 3-2. 서버 업로드 (mail-infra-setup 담당) ```bash # Backend: paramiko sftp → /opt/mail/backend/ # Frontend dist: bundle → /var/www/mail/ # Python venv: pip install requirements.txt ``` ### 3-3. systemd + nginx 설정 ```bash # /etc/systemd/system/zioinfo-mail.service 작성 # /etc/nginx/sites-available/zioinfo-mail 작성 # systemctl enable + start zioinfo-mail # nginx -t && systemctl reload nginx # ufw allow 8025/tcp ``` ### 3-4. Gitea repo 생성 + push ```bash # Gitea API로 zio/zioinfo-mail repo 생성 # repos/zioinfo-mail/ 로컬 git init # bundle → server → push ``` ### 3-5. deploy_server.py에 zioinfo-mail 추가 ```python # /opt/zioinfo/deploy_server.py에 zioinfo-mail 배포 함수 추가 elif repo == "zioinfo-mail": steps = [ ("git pull", [...]), ("npm build", [...]), ("copy dist", ["bash", "-c", "cp -r {SRC}/dist/. /var/www/mail/"]), ("pip install", [...]), ("restart", ["systemctl", "restart", "zioinfo-mail"]), ("health check", [...]), ] ``` --- ## Phase 4: 검증 ```bash # 1. 서비스 상태 systemctl is-active zioinfo-mail curl -f http://localhost:8026/health # 2. IMAP 로그인 테스트 curl -X POST http://localhost:8026/auth/login \ -d '{"username":"ythong@zioinfo.co.kr","password":"1q2w3e!Q"}' # 3. 메일 목록 조회 curl http://localhost:8026/mail/messages \ -H "Authorization: Bearer {token}" # 4. nginx 응답 curl -f http://localhost:8025/ ``` --- ## 데이터 흐름 ``` _workspace/ ├── infra-check.json ← Phase 1 결과 ├── api-spec.md ← Backend → Frontend 전달 └── deploy-result.json ← Phase 3 결과 ``` --- ## 에러 핸들링 | 에러 | 원인 | 처리 | |------|------|------| | IMAP 연결 실패 | Dovecot SSL 설정 | `/etc/ssl/guardia/server.crt` 확인 | | SMTP 인증 실패 | SASL 설정 | `postconf smtpd_sasl_*` 확인 | | npm build 실패 | node_modules 없음 | `npm ci` 재시도 | | 포트 충돌 | 8026 이미 사용 | 8027로 변경 | | HTML 메일 XSS | DOMPurify 미적용 | iframe sandbox 사용 | --- ## 테스트 시나리오 **정상 흐름:** 1. `https://mail.zioinfo.co.kr:8025` 접속 2. `ythong@zioinfo.co.kr` / `1q2w3e!Q` 로그인 3. 받은메함 목록 표시 4. 메일 클릭 → 본문 조회 5. 작성 → To: `info@zioinfo.co.kr` → 발송 6. 발신 계정 받은메함에서 수신 확인 **에러 흐름:** - 잘못된 비밀번호 → 401 응답 + "인증 실패" 메시지 --- ## should-trigger - "웹메일 만들어줘" - "zioinfo-mail 구축" - "메일 클라이언트 개발" - "mail.zioinfo.co.kr 배포" - "IMAP 연동 웹메일" - "다시 실행", "수정", "보완" ## should-NOT-trigger - "GUARDiA에서 메일 알림 보내줘" → guardia-orchestrator (ITSM 알림) - "메일 서버 설정해줘" → Postfix/Dovecot 직접 설정 (인프라 작업) - "홈페이지 문의 메일 연동" → homepage-cms-orchestrator