가이드 · 이메일 api
제품 팀은 이메일 API를 어떻게 안전하게 구현해야 하나요?
이메일 API는 폼에서 제공업체를 직접 호출하는 방식이 아니라 비동기적이고 권한이 통제되는 워크플로로 구현하세요. 호출자를 인증하고, 검증된 From 도메인의 테넌트 소유권을 확인하고, 메시지를 검증하고 크기를 확인한 뒤, 안정적인 애플리케이션 작업 ID를 부여해 한 번만 큐에 넣고 워커에서 제출하세요. 접수되면 제공업체 메시지 ID를 기록하고, 전송 이벤트를 멱등하게 수집하고, 영구 반송과 스팸 신고는 발송 제외 처리하세요. 중복 위험을 통제할 수 있을 때만 상한이 있는 재시도를 사용하세요. 자격 증명은 서버 측에 두고, 로그에는 메시지 데이터를 최소화하며, API 접수, 메일 서버 전달, 받은편지함 도달을 구분하세요.
제공업체를 고르기 전에 API 경계를 정의하세요
이메일 API는 제공업체의 세부 사항을 제품 코드에 모두 노출하지 않으면서 애플리케이션의 의도를 드러내야 합니다. 메시지, 발신 도메인, API 키, 이벤트, 발송 제외 항목에 대한 리소스를 정의하세요. 호출자가 통제할 수 있는 필드를 결정하세요. From, To, Reply-To, 제목, 텍스트, HTML, 그리고 허용 목록에 있는 소수의 헤더가 여기에 해당합니다. 제공업체의 서명이나 라우팅과 충돌할 수 있는, 호출자가 지정한 전송 헤더는 거부하세요. 발송은 결과가 따르는 쓰기 작업으로 취급하세요. 응답은 메일함 결과를 암시하지 않고 애플리케이션 메시지 리소스와 그 현재 상태를 식별해야 합니다. 제공업체 계정, 리전, 구성 세트, 전송 식별자는 어댑터 뒤에 두세요. 이 경계 덕분에 제공업체 마이그레이션이 가능해지고, 권한 부여, 보관, 남용 통제가 놓일 안정적인 자리가 생깁니다.
호출자를 인증하고 모든 발신 도메인에 대해 권한을 확인하세요
API 키는 단방향 해시로만 저장하고 전체 시크릿은 한 번만 표시하세요. 각 키에 워크스페이스 소유자, 상태, 생성 시각, 폐기 경로를 부여하고, 한 연동이 발송만 또는 이벤트 읽기만 해야 한다면 더 좁은 범위(scope)를 추가하세요. 인증은 누가 자격 증명을 제시했는지에 답하고, 권한 부여는 그 주체가 요청한 From 도메인과 메시지 리소스를 사용할 수 있는지를 결정합니다. 클라이언트가 보낸 도메인 식별자를 신뢰하지 말고, 배치 엔드포인트를 포함해 모든 발송에서 도메인 소유권을 확인하세요. 프로덕션 트래픽을 활성화하기 전에 제공업체의 검증을 요구하세요. 제공업체 자격 증명이나 워크스페이스 API 키를 브라우저 JavaScript, 쿼리 문자열, 분석 도구, 오류 메시지에 넣지 마세요. 멀티 테넌트 API에서는 메시지, 이벤트, 발송 제외, 수신함, 도메인 식별자에 대한 객체 수준 권한 부여가 특히 중요합니다.
도메인을 검증하고 인증을 정렬하세요
발신 도메인에는 데이터베이스 플래그 이상의 것이 필요합니다. 제공업체의 소유권 확인을 완료하고 필요한 DKIM 레코드를 게시하세요. SPF는 SMTP MAIL FROM 또는 HELO ID에 대해 호스트를 승인하고, DKIM은 서명 도메인을 암호화 메시지 서명과 연결합니다. DMARC는 성공한 SPF 또는 DKIM 식별자가 화면에 표시되는 RFC 5322 From 도메인과 정렬되는지 평가하며, 도메인 소유자가 처리 및 보고 정책을 게시할 수 있게 합니다. 도메인에 이미 SPF가 있다면 필요한 메커니즘을 기존 레코드에 병합하세요. RFC 7208은 도메인이 둘 이상의 SPF 레코드가 선택되도록 하는 여러 레코드를 게시해서는 안 된다고 규정합니다. 통제된 메시지와 집계 보고서로 모든 정상 발신자가 정렬되었음을 확인한 후에만 더 엄격한 DMARC 정책을 적용하세요. 인증은 무단 도메인 사용을 줄여 주지만 받은편지함 도달을 보장하지는 않습니다.
메시지 구조를 검증하고 수락하는 입력을 최소화하세요
RFC 5322는 인터넷 메시지를 헤더 필드와 그 뒤에 오는 선택적 본문으로 정의하며, MIME 명세가 기본 텍스트를 넘어 콘텐츠를 확장합니다. API는 전송 형식의 세부 사항 대부분을 숨기면서도 그 규칙은 적용할 수 있습니다. 수신자 배열을 정규화하고, 수신자 수와 인코딩된 전체 크기에 상한을 두고, 텍스트 또는 HTML 본문을 최소 하나는 요구하고, 구문이 메일함의 존재를 증명한다고 착각하지 말고 주소를 검증하세요. 헤더가 되는 필드에서는 캐리지 리턴과 라인 피드 문자를 제거하세요. Message-ID는 직접 생성하거나 제공업체가 생성하게 하세요. 메시지의 새 버전은 정당하게 새 식별자를 받을 수 있으므로, 이를 애플리케이션 작업 ID로 재사용하지 마세요. 문서화된 사용자 정의 헤더만 허용하고, 보호되는 필드의 중복은 거부하고, 누락된 변수가 통제된 애플리케이션 상태에서 실패하도록 제공업체에 제출하기 전에 템플릿을 렌더링하세요.
한 번만 큐에 넣고 안정적인 애플리케이션 식별자를 사용하세요
사용자 요청은 트랜잭션 안에서 내구성 있는 메시지 작업 하나를 만들고, 그 뒤에 워커가 제공업체를 호출해야 합니다. 작업에 안정적인 식별자를 부여하고, 계약에서 지원한다면 요청 지문 또는 호출자가 제공한 멱등성 키를 기록하세요. HTTP는 POST를 기본적으로 멱등하지 않은 것으로 정의하며, 클라이언트가 해당 작업이 사실상 멱등하다는 것을 알거나 원래 요청이 적용되지 않았음을 아는 경우가 아니라면 자동 재시도를 하지 말라고 주의를 줍니다. 이메일에서는 제공업체가 메시지를 접수한 후 워커가 응답을 받기 전에 타임아웃이 발생할 수 있으므로 이 점이 중요합니다. 모호한 실패가 발생하면 새 발송을 만들지 말고 먼저 저장된 작업과 제공업체 상태를 대조하세요. 애플리케이션 상태와 큐 게시가 함께 움직여야 한다면 아웃박스 패턴을 사용하고, 멱등성 경계에 고유성 제약을 두세요.
실패 유형에 맞춰 재시도를 설계하세요
검증, 권한 부여, 스로틀링, 제공업체 거부, 일시적인 전송 실패, 수신자 전송 실패를 구분하세요. 잘못된 입력과 승인되지 않은 From 도메인은 재시도 없이 실패해야 합니다. 제공업체의 속도 제한과 일시적인 서비스 오류는 상한이 있는 지수 백오프, 지터, 시도 횟수 상한, 그리고 워커의 요청 데드라인보다 긴 큐 가시성 타임아웃으로 재시도할 수 있습니다. 모호한 네트워크 타임아웃에는 무조건 새 요청을 보내지 말고 중복을 고려한 대조가 필요합니다. SMTP 자체는 일시적인 4xx 응답과 영구적인 5xx 응답을 구분하지만, 제공업체 API를 사용하는 애플리케이션은 해당 제공업체가 문서화한 오류 의미를 따라야 합니다. 재시도를 모두 소진한 작업은 검토할 수 있는 데드 레터 상태로 옮기고 정제된 사유를 보관하세요. 영구적인 수신자 반송을 API 장애처럼 재시도하지 말고, 스팸 신고를 또 다른 발송 시도로 바꾸지 마세요.
접수를 기록하고 전송 이벤트를 수집하세요
접수 직후 제공업체 메시지 식별자를 저장하고 애플리케이션 메시지 ID에 매핑하세요. 그러면 스팸 신고가 수신자 상세를 가려도 제공업체 이벤트가 올바른 리소스를 업데이트할 수 있습니다. 예를 들어 Amazon SES는 성공적인 발송과 수신자의 메일 서버 전달을 구분하고 전달, 반송, 스팸 신고, 거부, 전달 지연, 렌더링 실패, 열람, 클릭 이벤트를 게시할 수 있습니다. 제공업체의 문서화된 방식으로 웹훅 진위를 검증하고 이벤트 스키마를 확인하며 제공업체 이벤트 식별자 또는 결정적 지문으로 중복을 제거하고 부작용을 반복하지 않고 같은 이벤트의 반복 전달을 허용하세요. 필요한 경우에만 원시 페이로드를 암호화하고 액세스를 제어하며 보존 기간을 제한해 저장하세요. 정규화된 상태는 접수, 서버 전달, 반송, 스팸 신고, 지연, 거부, 발송 제외 결과를 구별해야 합니다.
발송 제외를 발송 시점의 통제로 만드세요
발송 제외 레코드는 대시보드에 표시하는 데 그치지 말고 모든 제공업체 제출 전에 확인해야 합니다. 영구적으로 반송된 주소와 스팸 신고는 보통 발송 제외 처리가 필요하며, 일시적인 전송 지연에는 다른 정책이 필요합니다. 발송 제외의 범위는 신중하게 정하세요. 계정 전체 목록은 공유된 평판을 보호할 수 있지만, 한 테넌트의 수신자 결과가 다른 테넌트를 차단할 수도 있습니다. 테넌트 단위 목록은 이러한 결합을 줄이지만 남용 및 플랫폼 안전 계층이 여전히 필요합니다. 사유, 원인 이벤트, 테넌트, 생성 시각, 통제된 제거 경로를 기록하세요. 스팸 신고나 영구 반송에 대한 발송 제외를 제거하는 것은 결과가 따르는 일이므로, 주소가 유효하고 수신자가 해당 메시지를 기대한다는 증거와 함께 의도적인 검토를 거쳐야 합니다. 원본 수신자 주소를 일반 로그나 실험에 복사하지 마세요. 운영 저장소는 발송 정책을 적용하고, 분석에는 집계된 수치만 사용하면 됩니다.
배치 발송과 민감한 업무 흐름을 보호하세요
배치 엔드포인트는 권한 부여나 검증 오류의 영향을 배가시킵니다. 모든 항목에 동일한 도메인 소유권, 발송 제외, 크기, 콘텐츠 검사를 적용하고, 엄격한 최대 배치 길이를 두고, 다른 테넌트의 데이터를 노출하지 않고 항목별 결과를 반환하세요. 속도 제한은 자격 증명, 워크스페이스, 도메인, 제공업체 수준에서 두어야 하며, 순간적인 급증과 누적 발송량에 대해 별도의 제어가 필요합니다. 요청 하나에 많은 수신자가 포함될 수 있으므로 전역 초당 요청 수 제한 하나만으로는 충분하지 않습니다. 에이전트가 구동하는 도구에서는 영향이 큰 배치를 제출하기 전에 의도적인 확인을 요구하세요. 수신 동의와 운영 규칙이 다르다면 트랜잭션과 마케팅의 권한을 분리하세요. 비정상적인 수신자 증가, 반복되는 거부 도메인, 반송 또는 스팸 신고의 급격한 변화, 빠른 키 생성을 모니터링하세요. 속도 제한은 안전을 뒷받침하지만 인증, 객체 권한 부여, 검증된 수신 동의, 남용 대응을 대체하지는 않습니다.
프로덕션 전에 실패 경로를 테스트하세요
제공업체 시뮬레이터나 통제된 메일함으로 접수, 수신 서버 전달, 하드 바운스, 스팸 신고, 지연, 잘못된 도메인, 폐기된 키, 스로틀링, 제공업체 타임아웃, 중복 웹훅, 큐 재전달을 테스트하세요. 동일한 멱등성 키가 애플리케이션 메시지를 하나만 만드는지, 재생된 이벤트가 중복된 부수 효과를 일으키지 않는지, 한 테넌트가 다른 테넌트의 도메인이나 메시지 ID로 읽거나 보낼 수 없는지 확인하세요. 실제로 수신된 메시지에서 From, Return-Path, DKIM, SPF, DMARC 정렬, 텍스트 및 HTML 렌더링, 해당하는 경우 수신 거부 동작, 링크를 점검하세요. 승인된 제공업체 한도 아래에서 큐를 부하 테스트하고, 백프레셔를 우회하지 말고 검증하세요. 큐 대기 시간, 소진된 재시도, 이벤트 수집 실패, 할당량 여유, 반송 및 스팸 신고 변화, 누락된 제공업체 콜백에 대한 경보를 추가하세요. 출시 체크리스트에는 각 알림과 복구 조치의 담당자를 명시해야 합니다.
SendHQ에 이 패턴을 신중하게 적용하세요
SendHQ는 워크스페이스 단위 bearer 키, 검증된 From 도메인 확인, 단일 및 일괄 메시지 생성, 수신함, 메시지 이벤트, 발송 제외 리소스를 제공합니다. 이 기능은 이 가이드의 아키텍처를 지원합니다. 키는 서버 측에 두고, 메시지 리소스를 생성해 ID를 보관하며, 초기 응답을 최종 전달로 취급하지 말고 이후 이벤트를 읽으세요. 플랫폼과 관계없이 호출자는 의도한 수신자, 합법적이고 예상 가능한 메일, 콘텐츠 정확성, 중요한 발송의 신중한 승인에 책임이 있습니다.
자주 묻는 질문
이메일 API는 웹 요청에서 동기적으로 발송해야 하나요?
보통은 아닙니다. 내구성 있는 애플리케이션 메시지를 만들어 큐에 넣고, 워커가 제공업체를 호출하게 하세요. 이렇게 하면 지연 시간이 격리되고, 상한이 있는 재시도를 지원하며, 모호한 제공업체 결과를 대조하기가 더 쉬워집니다.
요청이 타임아웃될 때 중복 이메일을 어떻게 방지하나요?
안정적인 애플리케이션 작업 ID와 고유성 제약이 있는 멱등성 경계를 사용하세요. 모호한 타임아웃이 발생하면, 새로운 ID로 다른 제공업체 제출을 하기 전에 기존 작업을 먼저 대조하세요.
이메일 API 응답이 성공하면 전달되었다는 뜻인가요?
아니요. 보통은 API 또는 제공업체가 요청을 접수했다는 뜻입니다. 이후 이벤트를 사용해 수신 서버 전달, 반송, 스팸 신고, 지연, 거부, 발송 제외를 최초 접수와 구분하세요.
이메일 API에는 어떤 DNS 레코드가 필요한가요?
정확한 레코드는 제공업체에 따라 다르지만, 프로덕션 발송에는 보통 도메인 검증과 DKIM, 그리고 올바른 SPF 전략과 정상적인 발송 스트림에 맞춰 정렬된 DMARC 정책이 필요합니다.
API 키를 브라우저 코드에 저장해도 되나요?
아니요. 워크스페이스와 제공업체 자격 증명은 서버 측 시크릿 저장소에 보관하고, 가능하면 애플리케이션 API 키는 저장 시 해시하고, 전체 시크릿은 한 번만 표시하고, 신속한 폐기 및 교체 경로를 마련하세요.
이메일 API는 영구 반송을 어떻게 처리해야 하나요?
제공업체 이벤트를 정규화하고, 애플리케이션 메시지에 매핑하고, 의도한 범위에서 해당 수신자에 대한 이후 일반 발송을 발송 제외 처리하세요. 제거는 의도적으로 이루어져야 하며 증거의 뒷받침이 있어야 합니다.
출처
- RFC 9110: HTTP 시맨틱 — Internet Engineering Task Force
- RFC 5321: 간이 메일 전송 프로토콜 — Internet Engineering Task Force
- RFC 5322: 인터넷 메시지 형식 — Internet Engineering Task Force
- RFC 6376: DomainKeys Identified Mail 서명 — Internet Engineering Task Force
- RFC 7208: 발신자 정책 프레임워크 — Internet Engineering Task Force
- RFC 7489: 도메인 기반 메시지 인증, 보고 및 적합성 — Internet Engineering Task Force
- Amazon SES 발송 활동 모니터링 — Amazon Web Services
- Amazon SES 알림 문제 해결 — Amazon Web Services
- OWASP API 보안 Top 10 2023 — OWASP Foundation
- SendHQ OpenAPI 계약 — SendHQ