feat(docker): mail setup — 파일럿 공존(한 사람 먼저) 켜기 · 끄기와 자체 확인

전면 전환 전에 한 사람만 같은 @arasystem.it.kr 주소로 새 서버를 쓰고 나머지 직원은 mailcow 에 둔다.
MX 는 mailcow 그대로이고 mailcow 의 Transport Map 이 시범 주소 하나만 새 서버로 넘긴다 —
새 서버는 자기에게 없는 사내 주소를 mailcow 로 중계해야 해서 루트 env 두 개(MAIL_PILOT_LEGACY_HOST ·
MAIL_PILOT_LEGACY_IPS)로 setup 이 맞추게 했다.

- 켜는 차례는 막는 것부터: 시범 표시(기존 서버 IP 의 자동 차단 예외) → RCPT 가드(인증 없는 세션의 없는 사내 주소 550) ·
  위조 막기(사내 도메인 MAIL FROM 은 mailcow IP 에서만) · 그 IP 의 SPF · 역방향 DNS · DMARC 검사와 받는 쪽 한도 예외 →
  리로드 → 켜기 전 가드 확인 → legacy 경로 · 발송 전략(인증한 제출 · 엔진이 만든 메일만 legacy) → 리로드 →
  allowRelaying → 켠 뒤 확인. allowRelaying 은 저장 즉시 먹어 가드보다 먼저 켜면 열린 중계가 된다.
- 가드 없는 relay 를 setup 이 만들지 않는다: 가드는 "2초 안에 550"으로 가린다(가드 거절은 곧바로 · 엔진 자체 거절은
  waitOnFail 5초 뒤). 아니면 켜지 않거나 바로 다시 끄고, 끄지 못하면 가드만이라도 다시 건 뒤 사실대로 알리고 멈춘다.
  끌 때는 allowRelaying 을 먼저 끄고 엔진에서 다시 읽어 꺼진 것을 본 뒤에만 나머지를 뺀다 — 주인을 모르는 relay 는
  끄지도 가드를 빼지도 않는다.
- 설명 칸이 없는 식의 주인은 시범 표시의 주소로 가린다 — 같은 꼴의 운영자 설정은 덮어쓰지 않고, 헷갈리면 멈춘다.
- 운영은 env 파일의 값으로만 켜고(포트 25 만 · 문서 대역 · 사설로 풀리는 이름 · 자기 자신 거부), 값이 빠졌다고
  저절로 끄지 않는다(끄기는 --end-pilot). 처음 켤 때 DKIM TXT 가 없거나 엔진의 키와 다르면 켜지 않는다.
  개발은 셸 값으로 한 번 시험한다.

리뷰 세 번(H1 · M1 · M2 · L1~L9 → N1~N8 → R1~R4)을 반영했다. 개발 엔진(0.16.27, 기존 서버 역 Mailpit)에서
켬 · 같은 값으로 다시([유지]) · 끔을 돌려 끈 뒤 엔진 설정이 처음과 같았다.
mailcow 쪽 절차와 운영 흐름은 아직 해 보지 않았다 — mail/README.md "파일럿 공존".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-30 09:37:25 +09:00
parent 4c1737f222
commit 258ebf2180
4 changed files with 2025 additions and 69 deletions
+7
View File
@@ -159,6 +159,13 @@ MAIL_TRUSTED_NETWORKS=
# (선택) 웹메일 로그인·대리 접근을 막을 계정 — 주소 전체를 콤마로. 비어 있어도 위 관리자(MAIL_ADMIN_LOCAL_PART)는 항상 막힌다.
# 관리자를 더 만들었다면 여기에 넣는다 (setup 이 빠진 관리자 계정을 [주의] 로 알려 준다)
# MAIL_BLOCKED_ACCOUNTS=ops@arasystem.test
# 시범 공존 — 한 사람만 새 서버를 먼저 쓰고 나머지 직원은 기존 서버(mailcow)에 남을 때 (mail/README.md "파일럿 공존"). 비우면 꺼짐.
# 개발은 비워 두고, 시험할 때만 셸에서 일회성으로 준다 (기존 서버 역 = Mailpit — 개발에서는 셸 값을 일부러 받는다):
# MAIL_PILOT_LEGACY_HOST=mailpit:1025 node --env-file=.env.development mail/scripts/setup.mjs
# 값 없이 다시 실행하면 setup 이 시범 설정을 지운다. 기존 서버 주소 — host · host:port · [host]:port (포트 기본 25)
MAIL_PILOT_LEGACY_HOST=
# 기존 서버가 이 서버에 붙을 때의 IPv4 · CIDR (콤마). 개발은 비우면 백엔드 컨테이너 주소(개발의 시험 SMTP 가 나가는 곳)
MAIL_PILOT_LEGACY_IPS=
# 개발용 테스트 직원 계정(ara.kim@ 등)의 공통 비밀번호 — 개발 환경에서만 만들어진다
MAIL_DEV_USER_PASSWORD=change-me-in-local-env
# 개발 전용 메일 수집기 — 사내 도메인 밖으로 보낸 메일이 여기에만 쌓인다