Ghost에 외부 SMTP 연동하기
먼저 Ghost 운영 목적에 맞는 외부 SMTP 서비스에 가입한다.
대표적으로 Resend, Brevo (구 Sendinblue), SendGrid / Mailgun 등이 있는데, 나는 Resend를 사용해보기로 했다.
- Resend 웹사이트 https://resend.com/ 접속하여 계정을 생성한다.
- 계정 접속 후 좌측 [API keys] 메뉴에서 [Create API Key] 클릭.
- 키 이름을 클릭하고 권한을 Sending access로 설정한다.
re_로 시작하는 API key를 복사한 뒤 개인 공간에 저장해놓는다.
Resend의 SMTP 접속 정보는 계정과 관계없이 모든 사용자에게 다음과 같이 고정되어 있다.
- Host:
smtp.resend.com - Port:
465(SSL 사용 시) 또는587(TLS 사용 시) - Username: 무조건 고정 값인
resend입력 - Password: 앞서 발급받은
re_로 시작하는 API key
또한 메일이 스팸으로 빠지지 않고 정상 전송되려면 발신자 주소의 도메인이 Resend에 등록되어 있어야 한다.
- Resend 대시보드 좌측 메뉴에서 Domains 클릭.
- [Add Domain]을 눌러 보유하고 있는 도메인을 입력.
- 화면에 나오는 DNS 레코드(TXT, CNAME 등)를 본인 도메인 구매처의 DNS 설정에 그대로 등록.
- Resend에서 Verified 상태로 바뀌면, 해당 도메인을 활용해
noreply@yourdomain.com같은 형식의from주소를 사용할 수 있다.
근데 내 Ghost 도메인은 ghost.jwheo.duckdns.org이다.
확인해보니 DuckDNS는 무료 동적 DNS (DDNS) 서비스이기 때문에 개인이 해당 도메인 전체(duckdns.org)의 DNS 레코드(TXT, CNAME 등)를 직접 소유하거나 제어할 수 없다고 한다.
따라서 Resend에서 duckdns.org를 통째로 도메인 인증하는 것은 불가능하다.
해결 방법은 아래 두 가지가 있다.
- Resend 기본 테스트 주소 사용하기
- 무료 커스텀 도메인 또는 개인 도메인 연결하기
방법 2는 메일 주소의 도메인이 깔끔하게 맞아 떨어진다는 장점이 있지만, 도메인을 새로 준비해야한다.
한편 방법 1은 추가 DNS 설정 및 도메인 등록 없이 API key만 넣으면 바로 메일 발송 기능이 동작하지만, 실제 메일을 보내는 용도로는 제약이 있을 수 있다.
나는 Ghost를 외부 타겟으로 운영할 계획이 없으므로, 방법 1로 진행해도 충분해보여 Resend 기본 테스트 주소를 사용해보기로 했다.
방법은 간단한데, Ghost 환경 변수 또는 설정 파일의 mail__from을 아래와 같이 설정하면 된다.
mail__from: "Ghost Blog <onboarding@resend.dev>"다음으로 Dockge에서 Ghost의 compose.yaml을 아래와 같이 수정해준다.
services:
ghost:
image: ghost:5-alpine
container_name: ghost
restart: unless-stopped
ports:
- 2368:2368
environment:
- NODE_ENV=production
- url=https://ghost.jwheo.duckdns.org
- database__client=sqlite3
- database__connection__filename=/var/lib/ghost/content/data/ghost.db
- security__staffDeviceVerification=false
# --- Resend SMTP 설정 추가 ---
- mail__transport=SMTP
- mail__options__host=smtp.resend.com
- mail__options__port=465
- mail__options__secure=true
- mail__options__auth__user=resend
- mail__options__auth__pass=여기에_발급받은_Resend_API_Key입력
- mail__from=Ghost Blog <onboarding@resend.dev>
volumes:
- /home/jwheo/ghost/content:/var/lib/ghost/content
networks:
nanobot-net:
external: true그대로 로그인 테스트를 해봤는데... 여전히 메일 전송에 문제가 있는 것 같다.
자세한 로그 내용은 아래와 같았다.
[2026-09-18 09:19:09] ERROR "POST /members/api/send-magic-link/" 500 2428ms
Failed to send email. Reason: Message failed: 550 The ghost.jwheo.duckdns.org domain is not verified. Please, add and verify your domain on https://resend.com/domains.
"Please see https://ghost.org/docs/config/#mail for instructions on configuring email."
Error ID:
0123c190-b342-11f1-a3f0-d5194ec490df
Error Code:
EMESSAGE
방법 1은 resend.com에서 도메인을 인증받을 필요가 없지 않나?
AI에게 물어보니 아래와 같이 답변을 해줬다.
Ghost의 일부 기능(특히 Members/Subscriptions 기능인 매직 링크나 구독 확인 메일)은 사용자가 입력한 사이트url([https://ghost.jwheo.duckdns.org](https://ghost.jwheo.duckdns.org))을 기반으로 발신자 주소(from)를 강제로 재조합하거나 오버라이드(Override)해버리는 성향이 있습니다.
즉, 설정 파일이나 환경 변수에onboarding@resend.dev를 적어두었더라도, Ghost가 회원 가입/구독 메일을 쏠 때 내부적으로 "아, 이 사이트 도메인이ghost.jwheo.duckdns.org니까 발신자도 이 도메인 기반이어야겠네?" 하고 가로채서 Resend로 던지기 때문에 Resend가 발끈하며 550 에러를 뿜어내는 것입니다.
결국 개인 유료/무료 도메인으로 변경하는 것 외에 다른 방법이 없는 것 같다.