Files
AriWeb-Suite/modules/arimail/README.md
T

69 lines
11 KiB
Markdown

# AriMail — mail.arihakdang.com / mail.heart-m.com
**AriMail**(1.0.0 까지의 이름은 mail-gateway, 저장소 https://source.ibit.kr/OZ-Group/AriMail)은 웹 메일함과 IMAP·POP3·SMTP 서버를 갖춘 메일 게이트웨이입니다.
수신·발신은 **Resend** 또는 **내장 Haraka**(직접 수신 MX / 직접 발송) 또는 외부 SMTP 중계 중에서 설정으로 고릅니다. www.arihakdang.com 관리자 메일함(`server/mailbox.mjs`)을 참고해
별도 사이트로 분리했고, 다음을 더합니다.
- **설정 파일과 초기 설정 페이지**(1.0.0~): Resend 키·중계 서버·Haraka·사이트 정보 같은 운영 설정은 `data/config.json` 에 두고, 배포 뒤 전용 포트(8791, 토큰)의 초기 설정 페이지나 `/admin → 메일 서비스 설정` 에서 채웁니다(재시작 없음). 환경 파일에는 배포에 필요한 값만 남습니다.
- **발송 모듈화**(1.0.0~): `server/providers/`(resend · smtp 중계 · 내장 Haraka)와 `sendMail()` 한 지점. 새 서비스는 모듈 하나를 더해 끼웁니다.
- **자동 설정·DNS 모듈**(1.0.5~): 설정 화면의 "자동 설정" 이 Resend 도메인 등록·검증·웹훅(비밀키 자동 저장), DNS 레코드(Google Cloud DNS / AWS Route 53 자동 적용, 그 밖에는 안내), 내장 Haraka 준비(DKIM·PTR·설치)를 진단·실행하고 상황별 안내 끝에 "메일 사용 준비 완료" 를 알립니다.
- **내장 Haraka**(1.0.0~): `haraka/`(run.mjs 관리 프로세스 + arimail 플러그인)와 `deploy/haraka-apply.sh`. 수신(25 → 게이트웨이 저장)과 발신(로컬 제출 포트 → MX 직접 배달, DKIM 서명)을 설정으로 켭니다.
- **이중 수신**: Resend 웹훅(`email.received`) + 1시간마다 수신 목록 동기화(웹 메일함을 열어 두면 1분마다 빠른 확인). 같은 메일은 한 번만 저장.
- **원본 보관**: Resend 가 서명 URL 로 주는 원본 `.eml` 을 그대로 저장(없으면 본문·헤더·첨부로 재구성). 첨부 바이트도 함께 보관.
- **웹 메일함**: 3단(폴더·목록·읽기 창) 레이아웃, 중요 표시·읽지 않음·첨부 필터, 일괄 삭제/이동/읽음, 답장·전체답장·전달, 원본 다운로드, 첨부.
- **HTML 편집기**: 글꼴·크기·색·강조·정렬·목록·링크·인용·구분선·본문 이미지(cid 인라인 첨부로 발송)·HTML 소스 편집, 임시 저장 자동화.
- **관리자 페이지** `/admin`(0.8.4~): 별도 로그인(같은 관리자 계정)을 거치는 고정 주소. 게이트웨이 사용자 계정(로그인 ID·이름·비밀번호·역할·상태·POP/IMAP 허용)을 추가·수정·삭제하고 서버 상태를 봅니다. 메일함 주소는 `로그인ID@도메인` 으로 자동 지정. 웹·POP·IMAP·SMTP 동일 인증.
- **IMAP**: `mail.arihakdang.com:993`(TLS)/`143`(STARTTLS). INBOX/Sent/Drafts/Trash 가 웹 메일함과 같은 저장소. 읽음·플래그·이동·삭제 공유, IDLE·MOVE·UIDPLUS·APPEND.
- **POP3**: `mail.arihakdang.com:995`(TLS)/`110`(STLS, 관리자 설정에 따라 일반 접속 로그인도 허용 — Gmail 의 POP 가져오기용). 계정은 www 관리자 계정 그대로. 한 번 내려준 메일은 다시 주지 않음.
- **SMTP 제출**(0.8.1~): `mail.arihakdang.com:465`(TLS)/`587`(STARTTLS). 웹 메일과 같은 아이디·비밀번호로 인증하고, 실제 발송은 서버 내부의 Resend API 키로 합니다(키는 사용자에게 노출되지 않음). 보낸 메일은 보낸 메일함에 바로 저장.
- **기한 없는 보관**(0.8.0~): 메일은 휴지통에서 영구 삭제할 때만 원본·첨부와 함께 지우고, 지운 메일은 재수신하지 않음.
- **설정 화면**: IMAP·SMTP·POP 메일 프로그램 설정 안내, 화면 기본값, 계정별 POP/IMAP 접속 허용 스위치. 로그인 화면의 (?) 접속 안내. 화면 상단에 버전 표시.
- **메일 전달·자동 응답**(0.8.16~): 설정 화면에서 받은 메일을 지정 주소(최대 5개)로 전부 전달하고, 지정한 메시지로 자동 회신(기한 없음 또는 날짜·시간 단위 기간)합니다.
되풀이 방지(전달 표시 헤더·`Auto-Submitted`), 같은 상대 24시간 1회, 자동 발송 메일 제외, 처리 기록은 메일 상세에 표시.
- **독립 설치**(0.8.18~): `WWW_DB_FILE` 을 비우면 www 사이트 없이 게이트웨이 계정만으로 동작합니다(첫 관리자 `admin`/`adminpasswd` 자동 생성(0.8.24~), `server/user-cli.mjs` 로 계정 추가·비밀번호 재설정, `SITE_TITLE`/`SITE_BRAND` 로 화면 이름 변경).
- **비밀번호 정책**(0.8.24~): 관리자 페이지에서 최소 글자 수(6~64, 기본 6)와 대·소문자 혼용·숫자·특수문자 요구를 켜고 끕니다. 예전의 10자 고정 규칙을 대체.
- **비밀번호 변경 보호·도메인 기반 서비스 이름·자동 새로고침**(0.8.25~): 자기 비밀번호 변경은 현재 비밀번호 확인 + 두 번 입력 + 보기 단추. 왼쪽 위 이름은 메일 도메인에서(`heart-m.com` → "HEART-M 메일"). 배포 뒤 열어 둔 화면은 `X-App-Version` 을 보고 스스로 새로 고침.
배포 파일은 `deploy/sites/<이름>.env` 사이트 설정 + `.in` 템플릿이며, 현재 mail.arihakdang.com(www 연동)과 mail.heart-m.com(독립) 두 사이트가 있습니다.
의존성 없음(Node 22.13+ 의 `node:sqlite`, `node:tls`). 문구는 `lang/ko.json` 한 곳에 둡니다.
```bash
npm test # 인증·웹훅·동기화·보관·발송·POP3·IMAP·SMTP·설정/발송 모듈/Haraka 수신/초기 설정 회귀 테스트
DB_FILE=./data/mail-gateway.sqlite MAILBOX=admin@example.test node server/index.mjs # 운영 설정은 ./data/config.json 과 초기 설정 페이지(8791)
```
설치·운영은 [docs/SETUP.md](docs/SETUP.md), 배포 파일은 `deploy/`, 변경 이력은 [CHANGELOG.md](CHANGELOG.md) 를 보세요.
## 구조
| 파일 | 역할 |
|---|---|
| `server/index.mjs` | HTTP(127.0.0.1:8790) + POP3 + 주기 작업 |
| `server/api.mjs` | 로그인, 메일함 API, 설정 API, Resend 웹훅 |
| `server/store.mjs` | 수신 저장(웹훅/동기화), 원본, 시각 정규화, 세션 정리, 초안·발송 |
| `server/automation.mjs` | 수신 메일 자동 처리(0.8.16~): 메일 전달·자동 응답, 되풀이 방지 규칙, 처리 기록(auto_actions) |
| `server/smtp.mjs` | SMTP 제출 서버(EHLO/STARTTLS/AUTH PLAIN·LOGIN/MAIL/RCPT/DATA), 로그인 인증 후 내부 키로 Resend 발송·보낸 메일함 저장 |
| `server/pop3.mjs` | POP3 서버(USER/PASS, AUTH PLAIN, STLS, UIDL, TOP), 전달 기록 |
| `server/imap.mjs` | IMAP4rev1 서버(SELECT/FETCH/STORE/SEARCH/MOVE/COPY/EXPUNGE/APPEND/IDLE, STARTTLS) |
| `server/imap-mime.mjs` | 원본 MIME 해석: ENVELOPE, BODYSTRUCTURE, 섹션 추출, APPEND 요약 |
| `server/auth.mjs` | www 관리자 인증(PBKDF2, 별칭 admin) + 게이트웨이 계정(mail_users) 관리(회원 가입·승인 대기 포함), 세션, 계정별 설정(prefs: 외부 이미지·POP/IMAP·전달·자동 응답) |
| `server/files.mjs` | 0.9.3: 대용량 첨부파일 — 디스크 스트리밍 업로드, 발송 시 토큰 링크(/dl/<토큰>)와 본문 블록, 랜딩 페이지·횟수 차감 다운로드, 기한·횟수 만료 삭제·정리, 시스템 상한(LIMIT_LARGE_FILE_*)·관리자 설정(50% 기본) |
| `server/limits.mjs` | 0.9.0: 시스템 제한(환경 변수 LIMIT_*)·관리자 제한·계정별 메일함 크기, 사용량(MIME 기준)·발송/수신 제한 검사, POP/IMAP 서비스 스위치, 회원 가입 설정, 메일 현황 집계(일·주·월) |
| `server/user-cli.mjs` | 계정 명령줄 도구(0.8.18~): 독립 설치의 첫 관리자 생성, 비밀번호 재설정, 목록 |
| `server/config.mjs` | 1.0.0: 운영 설정 파일(config.json) — 스키마, 환경 변수 가져오기·우선순위, 저장 즉시 적용, 비밀값 가림, 초기 설정 토큰, DKIM 키·DNS 레코드 |
| `server/domains.mjs` | 1.0.7: 다중 도메인 — 도메인 등록부(data/domains.json)와 테넌트(도메인별 env: DB·설정·파일), Host·로그인 ID·주소로 도메인 고르기, 추가·중지·삭제, "메일 서비스 없음" 안내 화면 |
| `server/usage.mjs` | 1.0.9: 메일 사용량 정보 제공 API(`/api/usage`) — 도메인·계정별 디스크 사용량·메일 수·발송량(일/주/월·일별 추이), 비밀 키(Bearer)·허용 IP·시도 제한으로 보호된 읽기 전용([docs/USAGE-API.md](docs/USAGE-API.md)) |
| `server/webmaker.mjs`, `server/webmaker-snapshot.mjs` | 1.0.8: webmaker 인증 모드 — 웹메이커(WebHosting_AI_agent) 데이터 디렉터리를 읽기 전용 스냅샷으로 읽어(직접 또는 sudo 도우미) 같은 scrypt 로 비밀번호 검사, 도메인 ↔ 사이트 대응(사이트 사용자·소유자·웹메이커 관리자 → `아이디@도메인`), 관리자 페이지의 읽기 전용 행 |
| `server/setup.mjs` | 1.0.0: 초기 설정 페이지 API(/api/setup/*)와 전용 포트(8791, 토큰) 서버, Haraka 상태 읽기. 1.0.7: 전체 설정(도메인 목록·추가·중지, ?domain= 으로 도메인별 설정) |
| `server/dns/` | 1.0.5: DNS 모듈 — `index.mjs`(모듈 선택·필요한 레코드 계산·SPF 병합·적용·반영 확인), `google.mjs`(Cloud DNS, 서비스 계정 JWT), `route53.mjs`(Route 53, SigV4), `common.mjs`(공개 조회·PTR) |
| `server/provision.mjs` | 1.0.5: 자동 설정 계획 — 단계별 진단(buildPlan)과 실행(runPlan): Resend 도메인·검증·웹훅, DNS 적용, Haraka DKIM·설치·PTR, SMTP 중계 확인 |
| `server/providers/` | 1.0.0: 발송·수신 서비스 모듈 — `index.mjs`(sendMail 선택·상태), `resend.mjs`(Resend API, 옛 server/resend.mjs; 1.0.11: 발신 도메인 검증 상태 진단 `mail_domain_unverified`/`mail_domain_missing` — 레코드별 없음/값 다름, 자동 재검증), `smtp.mjs` + `smtp-client.mjs`(SMTP 중계·내장 Haraka 제출) |
| `haraka/` | 1.0.0: 내장 Haraka — `package.json`(Haraka + dkim 플러그인), `run.mjs`(설정 파일을 보고 Haraka 설정 생성·실행·상태 기록), `plugins/arimail.js`(게이트웨이 연결: relay 판정·RCPT 확인·원본 전달) |
| `web/setup.*` | 1.0.0: 메일 서비스 설정 화면(전용 포트와 /setup 공용). 1.0.7: 전용 포트에서는 전체 설정(도메인 카드 + 고른 도메인의 설정) |
| `server/mime.mjs` | RFC 5322 메시지 생성, POP 전송 정규화 |
| `server/sanitize.mjs` | 수신 HTML 정제(www 의 sanitize_mail.py 와 같은 허용 목록) |
| `web/` | 웹 메일 화면(로그인·회원 가입·접속 안내, 3단 메일함, HTML 편집기(8색 팔레트), 설정(비밀번호 변경·사용량·전달·자동 응답))과 관리자 페이지(/admin: 계정 관리·회원 가입/제한/서비스 설정, 서버 상태·메일 현황) |
| `deploy/` | 사이트 설정(`sites/*.env`, `new-site.sh` 로 생성), `nginx-apply.sh`(vhost 만 다시 적용, 0.9.5), `haraka-apply.sh`(내장 Haraka npm 설치·서비스 등록, 1.0.0), `domain-nginx.sh`(추가 도메인 호스트의 nginx vhost·인증서, 1.0.7), `webmaker-access.sh`(웹메이커 계정 읽기 도우미·sudoers, 1.0.8), `site-mail-path.sh`(사이트의 `/mail` 을 웹 메일로 — `nginx/mail-path.conf.in`, 1.0.8)과 템플릿(systemd·nginx·certbot 훅·환경 파일 `.in`), setup/deploy 스크립트(끝에 초기 설정 페이지 주소 출력), 인증서 자동 발급 타이머(`tls-when-ready.sh`). 설치 옵션 `LOGIN_MODE`(standalone 기본 / www / webmaker)와 시스템 제한 `LIMIT_*` |