248 lines
7.2 KiB
Markdown
248 lines
7.2 KiB
Markdown
---
|
|
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
|