port-mailroom : 전사 사내외 메일 수집/발송 통합 게이트웨이
개별 메일함 연동 강결합 해소, KMS 자격증명 커스터디 격리, 실시간 SNS 이벤트 전파 및 404 인가 정책
01 왜 port-mailroom을 만들었는가? (Background & Value)
기존에는 사내 여러 서비스(TOMS-server, FMS 등)가 메일 기반의 수집 및 알림 기능을 구현하기 위해 각각 독립적으로 IMAP이나 Google OAuth와 결합되어 있었습니다. 이러한 개별 결합은 토큰 만료 관리 비용 증가, 중복 수집 부하 발생, 보안 유출 위협(평문 저장 등)을 가져왔습니다.
port-mailroom은 이러한 복잡한 메일 연동 체계를
전사 공용의 단일 수집/발송 게이트웨이로 격상하여, M2M 연동과 AWS SNS
이벤트 전파라는 단일화된 인터페이스로 메일 데이터를 수집하고 발송할 수 있도록 돕습니다.
- 자격증명 파편화: 각 서비스마다 Access/Refresh Token을 분산 관리 및 평문 보관
- 수집 부하 중복: 동일 메일에 대해 여러 시스템이 개별 스케줄러를 돌려 API 쿼터 소진
- 보안 정책 일관성 부족: 스팸 차단, 메일 열람 로깅 등 중앙 통제 불가
- 연동 복잡도: 메일 서버 장애 시 각 서비스가 개별적으로 재시도 및 오류 복구(Fall-back) 구현
- KMS 커스터디 격리: 토큰은 게이트웨이 외부 KMS에만 격리되어 E2E 보안 극대화
- 단일 수집 & SNS Fan-out: 한 번만 수집하고 AWS SNS로 필요한 모든 서비스에 전파
- 자동화된 프로비저닝 (JIT): 도메인 기반의 테넌트 자동 매칭으로 관리자 개입 불필요
- 초고속 원문/첨부파일 SSOT: 서비스별 중복 적재 없이 Presigned URL로 즉각 단건 조회
mailbox 모듈이 KMS와 결합하여 전담합니다. 수집기조차
단기 액세스 토큰만 받아 사용하므로 토큰 유출 원천 차단.
event_outbox를 거쳐 SNS 토픽으로 발행됩니다. 사내
시스템은 SQS로 이벤트를 받아 즉시 후속 비즈니스를 트리거합니다.
02 핵심 아키텍처 원칙 (Core Architecture)
🔄 3대 핵심 데이터 파이프라인 (Data Flows)
@domain.com을 바탕으로 적절한 테넌트 자동 매칭 및
프로비저닝
mailbox 모듈을 통해 Google 연동 동의 및 토큰 교환
event_outbox를 거쳐 AWS SNS로 이벤트 발행
apiHref를 활용하여 게이트웨이에 메타 조회
MailMessageReceivedEvent 페이로드에는
본문 내용이나 첨부파일 데이터가 포함되지 않습니다.
이는 SNS 256KB 크기 제한을 준수하고, 큐 브로드캐스트로 인한 민감 정보 평문 유출을
막기 위함입니다. 이벤트는 상태 전이만 알리며(포인터 역할), 실제 원문과 첨부파일은
Egress API(Presigned URL)를 통해 인증된 클라이언트가 Fetch합니다.
03 사내 개발자 연동 가이드 (Integration Steps)
연동 서비스는 client_credentials 방식을 사용합니다. TOMS-server 등은
단일 Client ID로 자신이 담당하는 화주들의 Tenant ID들을 Admin API를
통해 Grant 받아야 합니다.
# PortLogics IdP에서 Access Token 발급
curl -X POST https://id.portlogics.kr/oauth2/token \
-u "CLIENT_ID:CLIENT_SECRET" \
-d "grant_type=client_credentials"
# M2M 계정에 Tenant Grant 등록 (운영자 Admin API 요청 필요)
# mkhwang@portlogics.com 문의
메일이 게이트웨이에 수집되면 즉시 SNS 토픽 mailroom-events로
발송됩니다. 연동 서비스의 SQS Queue에 다음 Filter Policy를 적용하여 구독하세요.
{
"eventType": ["mail.message.received"],
"direction": ["INBOUND", "OUTBOUND"] // 선택적 필터링
}
SNS Payload 규격 (snake_case 컨버전 적용)
{
"tenant_id": "tnt_a1b2c3d4",
"event_type": "mail.message.received",
"message_id": "msg_f9e8d7c6",
"thread_id": "thr_11223344",
"mailbox": "forwarding@portlogics.com",
"from": "partner@vendor.com",
"subject": "[긴급] 선적 서류 송부의 건",
"has_attachment": true,
"direction": "INBOUND",
"internal_date": "2026-08-24T03:00:00.000Z",
"api_href": "/messages/msg_f9e8d7c6"
}
이벤트 수신 후 상세 내용이 필요할 때 호출합니다. (게이트웨이 Base URL
https://dev-mailroom.portlogics-server.com/api/v1 사용)
curl -X GET https://dev-mailroom.portlogics-server.com/api/v1/messages/msg_f9e8d7c6 \
-H "Authorization: Bearer M2M_TOKEN"
대용량 다운로드 처리 (302 Redirect)
본문 EML(원문)과 첨부파일은 호출 즉시 S3 Presigned URL로 HTTP 302 리다이렉트됩니다.
클라이언트 HTTP 모듈에서 Redirect를 허용(Follow)하도록 설정해야 합니다.
GET /messages/{id}/raw
// 반환: HTTP 302 Location: https://s3.amazonaws.com/...
GET /attachments/{attachment_id}
// 반환: HTTP 302 Location: https://s3.amazonaws.com/...
04 주요 이벤트 표준 규격 (Published Language)
| Event Type | 설명 및 트리거 시점 | 주요 처리 로직 |
|---|---|---|
| mail.message.received | 신규 메일(INBOUND) 또는 발송 사본(OUTBOUND) 게이트웨이 수집 완료 | TOMS 서류 자동 분류, CRM 티켓 생성 트리거 |
| mailbox.needs_reauth | 특정 메일함의 Google Refresh Token 만료 또는 연동 해제 발생 감지 | 담당자에게 연동 갱신 안내 알림 발송 |
| mailbox.connected | 메일함 최초 연동 및 JIT 프로비저닝 완료 | 수집 스케줄러 등록 및 초기 상태 세팅 |
05 운영 정책 및 FAQ
MessageAccessPolicy에 의해 클라이언트가 가진 Tenant Grant 범위를 벗어나는
데이터 접근은 존재 노출 금지 원칙에 따라 엄격히 404 Not Found
처리됩니다. 이는 타 화주의 메일 존재 여부를 악의적으로 유추하는 행위를 원천 차단하기
위한 보안 스펙입니다.
port-mailroom 게이트웨이 코어의
Message Block Rules(운영자 단독 차단 규칙)에 의해 스팸, 악성 도메인,
차단 키워드가 포함된 메일은 수집 파이프라인에서 자동 차단되며 SNS 이벤트 자체가
발행되지 않습니다. 연동 서비스는 순도 높은 비즈니스 메일만 수신하게 됩니다.