답장 가능한 메일함에서 인증 및 트랜잭션 이메일 발송하기
요약
기존 no-reply 방식의 트랜잭션 이메일이 가진 수신 불가 문제를 해결하기 위해 Nylas Agent Account를 활용하는 방법을 소개합니다. Agent Account를 통해 발송과 수신이 모두 가능한 실제 메일함을 구축하여 사용자의 답장을 시스템이 직접 처리할 수 있게 합니다.
핵심 포인트
- no-reply 주소는 사용자의 답장을 받을 수 없는 블랙홀과 같음
- Nylas Agent Account는 발송과 수신이 모두 가능한 권한 부여 기반 메일함 제공
- 사용자 개입 없이 도메인 내에서 직접 메일함을 생성(mint) 가능
- 수신된 답장에 대해 웹후크를 통해 LLM 에이전트 등의 자동 처리 가능
대부분의 트랜잭션 이메일 (Transactional email) 설정은 "발송" 단계에서 끝납니다. SendGrid나 Postmark를 연결하고, 인증 흐름 (auth flow)을 그곳으로 지정하면, 매직 링크 (magic links), OTP, 영수증, 그리고 "본인이 맞습니까?"와 같은 알림들이 no-reply@yourcompany.com을 통해 발송됩니다. 작동은 합니다. 사용자는 코드를 받고, 흐름은 완료됩니다.
그런 다음 사용자가 **답장 (Reply)**을 누릅니다.
사용자가 OTP 때문에 혼란스러울 수도 있습니다. 영수증에 찍힌 금액에 대해 이의를 제기하고 싶을 수도 있습니다. 혹은 "본인이 맞습니까?"라는 보안 알림에 "아니요, 제가 아닙니다"라고 답장할 수도 있습니다. 사용자가 무엇을 입력했든, 그것은 블랙홀로 떨어졌을 뿐입니다. no-reply@는 설계상 아무도 읽지 않는 주소이며, 대부분의 ESP (Email Service Provider) 설정에서는 실제 메일함조차 아니기 때문에, 답장은 반송되거나 릴레이 (relay) 속으로 사라져 버립니다. 당신이 보낸 메시지는 인간의 응답을 "유도"했지만, 정작 물리적으로 응답을 받을 수 없는 채널 위에 시스템을 구축한 것입니다.
해결책은 동일한 메일을 Nylas Agent Account를 통해 보내는 것입니다. 이는 발송과 수신이 모두 가능한, 권한 부여(grant) 기반의 실제 메일함입니다. 저는 Nylas CLI를 개발하고 있으므로, 아래의 터미널 명령어들은 제가 실제로 사용하는 것들이며, 각 명령어는 실제 네트워크상에서 어떤 일이 일어나는지 확인할 수 있도록 원시 HTTP 호출 (raw HTTP call)과 함께 제공됩니다.
Agent Account란 실제로 무엇인가
이 개념을 이해하는 핵심은 다음과 같습니다: Agent Account는 단순한 권한 부여 (grant)입니다. 이는 grant_id를 가지며, 이 grant_id는 Nylas가 이미 노출하고 있는 모든 권한 범위 엔드포인트 (grant-scoped endpoint) — Messages, Drafts, Threads, Folders, Attachments, Webhooks와 함께 작동합니다. 데이터 평면 (data plane) 측면에서 새로 배울 것은 없습니다. 만약 연결된 Gmail 또는 Microsoft 계정을 대상으로 GET /v3/grants/{grant_id}/messages를 호출해 본 적이 있다면, 이미 이 기능에 대한 전체 API 표면 (API surface)을 알고 있는 것입니다.
연결된 권한 부여 (connected grant)와의 차이점은 "프로비저닝 (provisioning)"에 있습니다. 사용자를 OAuth 과정으로 안내하는 대신, 당신이 등록한 도메인에 provider: "nylas"를 설정하여 직접 메일함을 생성(mint)합니다. 리프레시 토큰 (refresh token)도 필요 없고, 사용자 개입도 필요 없습니다. 계정은 당신의 도메인에서 발송하고 당신의 도메인에서 수신하며, 답장은 당신의 코드가 읽는 편지함으로 들어옵니다.
따라서 이 마이그레이션은 "새로운 이메일 API를 배우는 것"이 아닙니다. "발신자를 교체한 다음, 갑자기 생긴 편지함을 읽기 시작하는 것"입니다.
인증 메일에 대해 단방향 ESP (Email Service Provider)보다 나은 이유
- 답장이 갈 곳이 있습니다. 이것이 핵심입니다. 매직 링크 (magic link), OTP, 또는 영수증에 대한 답장이 실제 편지함에 도착하고
message.created웹후크 (webhook)를 발생시킵니다. 당신의 핸들러(handler) — 또는 LLM 기반 에이전트(agent) — 가 이를 처리할 기회를 얻게 됩니다. - 평판(reputation)을 직접 소유합니다. 메일은 당신의 도메인에서 당신의 DKIM 서명과 함께 발송되며, 당신의 일정에 맞춰 워밍업 (warming) 됩니다. 해당 날짜에 ESP의 공유 풀 (shared pool)을 사용하는 다른 사용자와 IP 평판을 공유하지 않습니다.
- 송신과 수신을 위한 단일 API. 수신을 위한 별도의 시스템이 필요 없습니다. OTP를 보내는 것과 동일한
grant_id가 답장을 목록화합니다. 스레딩 (threading)은 자동으로 이루어집니다. Nylas는 헤더 (headers)를 보존하므로 답장이 원본과 함께 그룹화됩니다. - 테넌트별 (per-tenant) 식별자 생성이 저렴합니다. 고객별 또는 환경별로 별도의 발신자가 필요하신가요? 다른 서브도메인에 또 다른 에이전트 계정 (Agent Account)을 프로비저닝 (provision) 하세요. 이는 새로운 ESP 계약이 아니라 단순한 API 호출일 뿐입니다.
시작하기 전에
두 가지가 필요합니다:
- Nylas API 키. Nylas Dashboard에서 가져오세요. 아래의 모든 호출은
Authorization: Bearer <NYLAS_API_KEY>로 인증되며, 예제에서는 미국 데이터 리전 호스트인https://api.us.nylas.com을 사용합니다 (EU의 경우api.eu.nylas.com으로 교체하세요). - 도메인. DNS 설정 없이 Nylas의
*.nylas.email체험용 서브도메인에서 프로토타입을 제작할 수 있습니다. 운영 환경을 위해서는 자체 도메인을 등록해야 합니다. 그리고 이 부분이 인증 메일에서 가장 중요한 부분입니다. 발신 평판은 직접 구축해야 합니다. 첫날부터 수천 건의 비밀번호 재설정 메일을 보내는 완전히 새로운 도메인은 메일함 제공업체(mailbox providers)에게 스팸 발송과 똑같이 보입니다. 새 도메인은 약 4주에 걸쳐 워밍업 됩니다. 낮은 수치에서 시작하여 점진적으로 늘려가세요. 이에 대한 자세한 내용은 전달 가능성 (deliverability) 섹션에서 다룹니다.
auth.yourcompany.com 또는 notifications.yourcompany.com과 같이 이 트래픽 전용 서브도메인 (subdomain)을 선택하세요. 이를 기본 메일 도메인 (primary mail domain)과 분리하면, 인증 메일의 전달 가능성 (deliverability)이 하락하더라도 팀의 이메일로 그 영향이 번지지 않습니다.
발신자 프로비저닝 (Provision the sender)
등록된 도메인에 에이전트 계정 (Agent Account)을 생성하세요. CLI를 사용하는 방법은 다음과 같습니다:
nylas agent account create support@notifications.yourcompany.com \
--name "Acme Support"
--name 플래그는 표시 이름 (display name)을 설정합니다. 이를 통해 수신자는 단순한 주소 대신 Acme Support <support@notifications.yourcompany.com>를 보게 됩니다. 사용자에게 시각적인 변화가 느껴지지 않도록 기존에 사용하던 ESP (Email Service Provider)와 동일한 이름을 유지하세요. 명령어를 실행하면 새로운 권한 (grant)의 id, 상태 (status), 커넥터 (connector) 상세 정보가 출력됩니다.
동일한 작업을 수행하는 HTTP 호출은 provider: "nylas"를 포함한 POST /v3/connect/custom입니다:
curl --request POST \
--url "https://api.us.nylas.com/v3/connect/custom" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
...
응답에는 data.id가 포함되며, 이것이 바로 grant_id입니다. 이를 저장해 두세요. 아래의 모든 발송 (send), 목록 조회 (list), 읽기 (read) 작업에서 이 ID를 사용합니다. 필요한 필드는 name과 settings.email뿐입니다. (생성 시 --workspace 플래그는 없습니다. API가 계정을 위한 기본 워크스페이스 (workspace)와 정책 (policy)을 자동으로 생성합니다. 나중에 사용자 정의 정책을 사용하려면 nylas workspace update <workspace-id> --policy-id <policy-id>를 통해 연결하세요.)
매직 링크 (magic link) 또는 OTP 발송
기존의 인증 발송 흐름을 에이전트 계정 (Agent Account)을 대상으로 수행하는 방법입니다. CLI를 사용하는 방법은 다음과 같습니다:
nylas email send support@notifications.yourcompany.com \
--to user@example.com \
--subject "Your sign-in code" \
...
첫 번째 위치 인자 (positional argument)는 권한 (grant)인 에이전트 계정의 이메일 주소(또는 grant_id)입니다. HTTP를 통한 동일한 호출은 POST /v3/grants/{grant_id}/messages/send입니다:
curl --request POST \
--url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages/send" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
...
이것이 교체 작업의 전부입니다. 기존 코드에서 sendgrid.send(...)를 호출했다면, 이제는 이것을 호출하게 됩니다. 수신자는 동일한 형태의 발신자로부터 동일한 코드를 받게 되지만, 이번에는 그 이면의 주소가 실제 주소라는 점이 다릅니다.
사본이 계정의 Sent (보낸 편지함) 폴더에 자동으로 저장되므로, 별도의 감사 추적(audit trail) 시스템을 구축하지 않고도 기록을 남길 수 있습니다. 또한 body가 단순 HTML이므로, 기존에 사용하던 템플릿 마크업(templated markup)을 그대로 사용할 수 있습니다.
템플릿에 관한 참고 사항
현재 인증 메일에 템플릿을 사용하고 있다면, 기존 방식을 그대로 유지하세요. 즉, 본인의 코드에서 템플릿을 HTML로 렌더링(render)한 다음, 그 결과를 body로 전달하면 됩니다. 나중에 헤매지 않도록 한 가지 주의할 점을 말씀드리자면, Agent Account 권한(grants)에 대해서는 Nylas의 호스팅 템플릿(hosted templates)이 구현되어 있지 않습니다. 따라서 여기서는 --template-id 흐름을 사용하지 마세요. 서버 측에서 직접 렌더링한 후 완성된 HTML을 보내야 합니다. 실제로 이는 여러분이 이미 사용 중인 템플릿 엔진(Handlebars, JSX-to-string, 일반 보간법(plain interpolation) 등)을 얇게 감싸는(thin wrapper) 작업일 뿐이며, 전송 호출 방식은 위의 방식과 바이트 단위로 동일합니다. 단지 body에 렌더링된 마크업을 담아 보낼 뿐입니다.
답장 경로 처리하기
이것이 바로 단방향 ESP(Email Service Provider)가 제공할 수 없는 나머지 절반입니다. 사용자가 해당 OTP나 영수증에 답장을 보내면, 메시지는 Agent Account의 편지함에 도착하며 표준 message.created 웹훅(webhook)을 발생시킵니다. 이는 다른 권한(grant)에서 수신 메일에 대해 받는 것과 동일한 이벤트입니다.
nylas webhook create \--url https://yourapp.example.com/webhooks/nylas \--triggers message.created
또는 POST /v3/webhooks를 통한 HTTP 방식입니다:
curl --request POST \--url "https://api.us.nylas.com/v3/webhooks" \--header "Authorization: Bearer <NYLAS_API_KEY>"
...
웹훅이 발생하면 페이로드(payload)에 메시지 ID와 권한 ID(grant ID)가 포함되어 있습니다. 앞서 설명한 동일한 두 단계 패턴을 사용하여 편지함을 가져오고 전체 본문을 읽으세요. CLI에서 최근 메시지를 나열해 보겠습니다:
nylas email list support@notifications.yourcompany.com --limit 10
…이는 GET /v3/grants/{grant_id}/messages에 매핑됩니다.
curl --request GET \
--url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?limit=10" \
--header "Authorization: Bearer <NYLAS_API_KEY>"
그런 다음 메시지 ID를 이용해 특정 답장을 읽습니다:
nylas email read <message-id> support@notifications.yourcompany.com
…이는 GET /v3/grants/{grant_id}/messages/{message_id}에 매핑됩니다:
curl --request GET \
--url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages/<MESSAGE_ID>" \
--header "Authorization: Bearer <NYLAS_API_KEY>"
이제 답장이 손실되지 않습니다. 핸들러는
도메인을 인증하세요. DKIM과 SPF는 도메인 설정의 일부로 검증되므로, 검증된 Agent Account 도메인은 이미 DKIM 및 SPF 서명이 되어 있습니다. DKIM은 메시지가 변경되지 않았으며 실제로 귀하로부터 발송되었음을 증명하고, SPF는 Nylas가 귀하를 대신하여 메일을 보낼 수 있도록 권한을 부여합니다.
DMARC를 직접 추가하세요. Nylas는 DMARC를 추적하지만 강제(enforce)하지는 않으므로, 이는 귀하가 직접 게시해야 하는 계층입니다. 단계적으로 배포하세요. 모니터링 전용(monitor-only)으로 시작하여 보고서가 깨끗하게 들어오면 점차 강화하십시오:
v=DMARC1; p=none; rua=mailto:dmarc-reports@yourcompany.com; pct=100
p=none(정상적으로 전달되되 집계 보고서만 수집)으로 시작하여, 보고서가 깨끗해 보이면 p=quarantine(격리)으로 이동하고, 최종적으로 p=reject(거부)로 마무리합니다. 각 단계마다 몇 주 정도의 시간을 할애하세요. Agent Account는 귀하의 도메인 DKIM 키로 서명하고 검증된 도메인에서 발송하기 때문에, 레코드가 활성화되면 정렬(alignment)이 즉시 작동합니다.
도메인을 워밍업(Warm)하세요. 위에서 언급했듯이, 완전히 새로운 도메인은 평판(reputation)이 없으며, 인증 메일은 활성화되는 즉시 대량으로 발송되는 경향이 있습니다. 약 4주에 걸쳐 점진적으로 늘려가세요. 만약 고객당 별도의 도메인을 사용하여 하나의 Agent Account를 프로비저닝(provisioning)한다면, 각 도메인을 개별 일정에 맞춰 워밍업해야 합니다. 평판은 도메인 간에 전이되지 않습니다.
--url "https://api.us.nylas.com/v3/webhooks" \
--header "Authorization: Bearer <NYLAS_API_KEY>" \
...
이러한 요소들을 실제 로직에 연결하세요. 하드 바운스(hard-bounce)가 발생하거나 불만(complaint)이 접수되는 주소로는 메일 발송을 중단하고, 두 수치 중 하나라도 상승하면 아웃바운드(outbound) 속도를 늦추어야 합니다. 자체 텔레메트리(telemetry)를 통해 문제를 포착하는 것이 발송 중단을 초래하는 임계값 아래로 유지하는 방법입니다. SRE(Site Reliability Engineer)로서 제가 좋아하는 부분은, 이것이 다른 모든 파이프라인에 적용되는 것과 동일한 관측 가능성(observability) 원칙이라는 점입니다. 바운스와 불만은 단지 발신자 이름이 붙은 에러율(error rates)일 뿐입니다.
플래그 데이(Flag day) 없이 마이그레이션하기
모든 것을 한꺼번에 전환할 필요는 없으며, 그래서도 안 됩니다. 깔끔한 접근 방식은 병행 운영(side-by-side)을 하면서 메시지 유형별로 마이그레이션하는 것입니다.
기존의 ESP (Email Service Provider) 연결을 유지하세요. Agent Account (에이전트 계정)를 프로비저닝(Provision)합니다. 그다음, 한 번에 하나의 메시지 클래스(message class)씩 이동시키세요. 답장을 가장 많이 원하는 유형부터 시작하는 것이 좋습니다. 제 경험상, 그것은 대개 보안 알림(
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기