수정 이력(4건, 최종 수정 2026년 09월 03일)
이 글에 적용한 변경 사항의 기록입니다. 보관해 둔 수정 전 버전은 DOI가 부여된 고정 URL에서 읽을 수 있습니다.
- permalink·저자 표기·지식 맵 래퍼·깨진 내부 링크 등 CI가 지적한 표시용 수정을 반영했습니다. 본문의 기술적인 주장은 바꾸지 않았습니다.
- 글 맨 앞에 「이 글의 지식 맵」 절을 추가했습니다. 본문에서 다루는 개념과 그 관계를 요약·그림·상세 페이지 링크로 모은 것입니다. 본문의 주장은 바꾸지 않았습니다.
- 외부 리뷰(1283건)에 대응해 본문을 갱신했습니다. 개별 변경 내용은 아래 이력을 참조하세요.
- 핵심 요약을 결론 3가지로 압축하고, 대상 독자와 전제 환경 표, 용어 미니 사전, 글의 구성을 맨 앞에 추가했습니다. 공유 렌탈 서버에서 계약처에 확인할 항목 표와 RFC 및 Gmail 발신자 가이드라인 참고 링크 절을 새로 넣었습니다.
- 최초 공개
이 글을 인용하기(DOI: 10.5281/zenodo.21635270)
이 글은 Zenodo에 보관되어 있습니다. 항상 최신 버전으로 연결되는 DOI와 지금 보고 있는 버전에 고정된 DOI를 아래에 함께 제시합니다.
Go Komura (2026). 「문의 폼 이메일이 도착하지 않는 원인과 해결 방법」. 합동회사 코무라소프트. https://doi.org/10.5281/zenodo.21635270 https://comcomponent.com/ko/blog/contact-form-email-delivery-troubleshooting/
- DOI(최신 버전)
- 10.5281/zenodo.21635270
- DOI(이 버전)
- 10.5281/zenodo.21635271
1. 요약
문의 폼 알림 메일이 “발송은 성공했는데 도착하지 않는” 경우, 원인은 대개 메일 발송 코드가 아니라 발신자 설계에 있습니다. 결론은 세 가지입니다.
From:은 자사 사이트 도메인으로 고정하고, 폼 이용자의 주소는Reply-To:에 넣습니다. 눈에 보이는 발신자와 실제로 인증되는 도메인을 맞추기 위해서입니다.- SPF와 DKIM을 둘 다 갖춥니다. forwarding은 SPF를 깨기 쉽고, SPF에만 의존하면 정상적인 메일도 떨어집니다.
- DMARC는
p=none관측부터 시작해quarantine/reject로 단계적으로 올립니다. 처음부터reject로 두면 자사의 정상 메일까지 멈춥니다.
이유와 근거는 2장 이후에서 다룹니다. 지금 발생한 미도착의 원인을 먼저 가르고 싶다면 4장의 진단 절차부터 읽어도 됩니다.
대상 독자와 전제 환경
이 글은 자사 사이트의 문의 폼에서 보내는 알림 메일이 도착하지 않는 문제를 다루는 분을 위한 것입니다.
| 항목 | 내용 |
|---|---|
| 대상 독자 | Web 사이트 담당자, 폼을 구현한 개발자, 사내 메일 운영을 보는 정보시스템 담당자 |
| 환경에 의존하지 않는 부분 | 2장~5장(발신자 사고방식, 실패 시나리오, 헤더 읽는 법, From 설계). 발송 기반이 무엇이든 같은 이야기입니다 |
| 환경을 전제로 하는 부분 | 6장의 설정 예. PHP와 Linux 계열 발송 기반(Postfix / Exim / OpenDKIM), 그리고 SendGrid·SES·Mailgun을 소재로 합니다 |
| 다루지 않는 것 | 개별 CMS나 폼 플러그인의 설정 화면, Exchange Online / Microsoft 365의 조직 내 메일 흐름, 이메일 마케팅의 발송 설계 |
DNS 레코드(SPF / DKIM / DMARC)와 헤더 설계는 Web 서버가 Windows든 Linux든, 발송이 자체 MTA든 외부 서비스든 공통입니다. 구현 언어가 달라도 바꿔 읽으면 되는 것은 “어디에서 헤더를 조립하는가”와 “어디에서 envelope 발신자를 지정하는가” 두 가지뿐입니다.
이 글에서 쓰는 용어
본문에 설명 없이 나오는 용어를 먼저 정리합니다.
| 용어 | 의미 |
|---|---|
| MTA(Mail Transfer Agent) | 메일을 배송하는 서버 소프트웨어. Postfix나 Exim 외에 SendGrid나 SES 같은 발송 서비스도 이 역할을 맡습니다 |
| MUA(Mail User Agent) | 이용자가 쓰는 메일 소프트웨어. Outlook이나 Gmail 화면 등 |
| envelope | SMTP 주고받기에서 넘기는 배송용 발신자와 수신자(MAIL FROM / RCPT TO). 본문 쪽 헤더 From: To:와는 별개이며, 봉투와 편지지의 관계에 해당합니다 |
| alignment | DMARC 판정에서 From: 헤더의 도메인과 SPF나 DKIM으로 인증된 도메인이 맞는 것 |
| reputation | 발신 IP나 발신 도메인에 대한 수신 측 평가. 나빠지면 스팸 판정이나 거부로 이어집니다 |
| PTR | IP 주소에서 호스트 이름을 조회하는 역방향 DNS 레코드 |
| DSN(Delivery Status Notification) | 배송 결과 알림. 이른바 bounce 메일의 기계 가독 형식이며, RFC 3464가 정의합니다 |
| milter | MTA에 필터 처리를 끼워 넣는 메커니즘. DKIM 서명을 붙이는 OpenDKIM도 이 메커니즘으로 동작합니다 |
이 글의 구성
- 요약(이 장)
- SPF·DKIM·DMARC와 From 헤더의 역할 ── 메커니즘 이해
- 문의 폼에서 자주 발생하는 실패 시나리오
- 진단 절차와 명령 ── 헤더, DNS, SMTP, 실제 발송
- 권장 From 설계 패턴
- 구성별 설정 가이드(외부 SMTP / 공유 호스팅 / PHP)
- 문제 해결 체크리스트
이 글의 지식 맵
이 글은 문의 폼 알림 메일이 도착하지 않는 주된 원인이 발송 코드가 아니라 From 헤더의 설계에 있으며, 보이는 발신자와 인증되는 도메인을 맞추는 일이 DMARC alignment를 좌우한다고 정리합니다. SPF는 엔벨로프 발신자(Return-Path)를, DKIM은 서명 도메인을 검증하고, DMARC는 그 결과와 From: 도메인의 일치를 판정하므로, 이용자 주소를 그대로 From에 쓰는 설계나 메일 포워딩으로 SPF가 깨지는 경우는 DMARC 실패의 전형적인 원인이 됩니다. 공유 호스팅의 로컬 MTA나 PHP의 mail(), SendGrid·SES·Mailgun과 같은 외부 SMTP 서비스에서는 DKIM 셀렉터나 PTR, 커스텀 MAIL FROM 설정이 도달률을 좌우하며, Reply-To로 회신 주소를 확보하면서 From은 자체 도메인으로 고정하는 설계가 권장된다고 합니다.
flowchart LR
accTitle: 문의 폼 메일 도달성의 지식 맵
accDescr: From 헤더의 설계가 SPF·DKIM·DMARC alignment를 통해 메일 도달성을 좌우하고, 포워딩·공유 호스팅·발송 서비스 설정과 어떻게 연결되는지를 보여주는 그림입니다.
contact_form_notification_email["문의 양식 알림 메일"]
dmarc_alignment["DMARC 정렬(alignment)"]
from_header["From 헤더"]
reply_to_header["Reply-To 헤더"]
dmarc["DMARC"]
spf["SPF(Sender Policy Framework)"]
dkim["DKIM(DomainKeys Identified Mail)"]
unaligned_from_design["이용자 주소를 From으로 쓰는 설계"]
dmarc_failure["DMARC 실패(dmarc=fail)"]
mail_forwarding_spf_failure["메일 포워딩으로 인한 SPF 실패"]
return_path["Return-Path(엔벨로프 발신자)"]
php_mail_function["PHP mail() 함수"]
header_injection["메일 헤더 인젝션"]
shared_hosting_mta["공유 호스팅 로컬 MTA"]
ptr_record["PTR 레코드(역방향 조회)"]
sendgrid_domain_authentication["SendGrid Domain Authentication"]
dkim_selector["DKIM 셀렉터"]
ses_custom_mail_from["Amazon SES 사용자 지정 MAIL FROM"]
mailgun_domain_verification["Mailgun의 송신 도메인 검증"]
dmarc_policy_mode["DMARC 정책 모드"]
authentication_results_header["Authentication-Results 헤더"]
sender_header["Sender 헤더"]
from_header -->|"권장되는 대응"| contact_form_notification_email
reply_to_header -->|"권장되는 대응"| contact_form_notification_email
dmarc_alignment -->|"전제로 한다"| from_header
dmarc -->|"이용한다"| spf
dmarc -->|"이용한다"| dkim
dmarc -->|"전제로 한다"| dmarc_alignment
unaligned_from_design -->|"원인이 될 수 있다"| dmarc_failure
mail_forwarding_spf_failure -.->|"원인이 될 수 있다"| dmarc_failure
dkim -->|"완화한다"| dmarc_failure
spf -->|"이용한다"| return_path
return_path -.->|"에서 구성할 수 있다"| php_mail_function
php_mail_function -.->|"원인이 될 수 있다"| header_injection
shared_hosting_mta -.->|"원인이 될 수 있다"| dmarc_failure
ptr_record -->|"권장되는 대응"| shared_hosting_mta
sendgrid_domain_authentication -->|"전제로 한다"| dkim_selector
ses_custom_mail_from -->|"전제로 한다"| return_path
mailgun_domain_verification -->|"전제로 한다"| dkim_selector
dmarc -->|"에서 구성할 수 있다"| dmarc_policy_mode
dmarc_alignment -->|"에서 확인할 수 있다"| authentication_results_header
sender_header -->|"사용은 비권장"| contact_form_notification_email
unaligned_from_design -->|"사용은 비권장"| contact_form_notification_email
dkim -->|"에서 구성할 수 있다"| dkim_selector
그림의 실선은 항상 성립하는 관계, 점선은 조건이 붙는 관계입니다(성립 조건은 상세 페이지의 관계별 설명에 적혀 있습니다). 관계 전체 목록(총 22건, 근거와 확신도 포함)과 주요 개념의 정의는 지식 맵 상세 페이지에 정리되어 있습니다(일본어). 데이터: JSON-LD / Turtle
2. SPF·DKIM·DMARC와 From 헤더의 역할
메일 배송에서는 envelope와 헤더를 나눠 생각해야 합니다. SPF가 주로 검증하는 것은 SMTP 세션 중의 MAIL FROM이며, 이것은 배송상의 발신자입니다. 최종 배송 시점에는 그 반환 경로가 Return-Path로 하나만 남아야 하고, 발신 측 SMTP 시스템은 처음부터 Return-Path 헤더를 가진 메시지를 만들어서는 안 됩니다. 한편 From:은 본문 헤더 쪽에서 “누구에게서 온 메일로 보이는가”를 나타내고, Reply-To:는 답장 주소, Sender:는 실제로 발송한 주체를 나타냅니다.
RFC 5322는 From:을 메시지의 작성자, Sender:를 실제 발송 주체로 정의합니다. 작성자와 발송 주체가 같다면 Sender:는 쓰지 않아야 하며, 답장 주소를 작성자와 다르게 하려면 Reply-To:를 쓰는 것이 맞습니다. 나아가 RFC 5322는 From:에 작성자의 것이 아닌 주소를 넣어서는 안 된다고 명시합니다. 문의 폼 알림은 보통 사용자 본인이 MUA에서 보내는 것이 아니라 사이트 쪽 시스템이 만드는 알림이므로, 이용자 주소를 From:에 두는 설계는 사양의 취지와도 어긋나기 쉽습니다.
DKIM은 메시지의 일부 헤더와 본문에 서명을 붙이고, 수신 측이 DNS에 있는 공개 키로 검증합니다. 서명 도메인은 DKIM-Signature의 d=로 나타나며, 공개 키는 selector._domainkey.example.com처럼 selector로 조회합니다. DKIM은 “forwarding되어도 비교적 잘 남는” 인증으로 쓰이지만, 본문이나 서명 대상 헤더가 중간에 바뀌면 bh=의 본문 해시나 서명 검증이 실패합니다.
DMARC는 SPF나 DKIM의 성패만이 아니라, 그 인증된 도메인이 From: 도메인과 맞는지를 봅니다. 여기가 핵심입니다. SPF가 통과해도 MAIL FROM=bounces.vendor.net이고 From: contact@example.com이면 SPF의 alignment는 떨어집니다. DKIM이 d=example.com으로 통과하면 DMARC는 pass할 수 있지만, DKIM도 없으면 DMARC는 실패합니다. DMARC에는 adkim / aspf에 의한 strict / relaxed alignment 모드, p=none|quarantine|reject 정책, rua / ruf 리포트 수신 주소가 정의되어 있습니다.
Gmail의 최근 가이드라인은 이 설계 사상을 그대로 운영 요건으로 옮겼습니다. Google은 “From: 헤더를 위장하지 말 것”, “다이렉트 메일에서는 From: 헤더 안 도메인이 SPF 도메인 또는 DKIM 도메인과 일치할 것”을 명시합니다. 문의 폼 알림은 마케팅 메일이 아니지만, 수신 측 필터의 기본 로직은 같으므로 이 생각을 무시하면 전달률이 떨어집니다.
sequenceDiagram
participant User as 폼 이용자
participant App as 웹 애플리케이션
participant SMTP as 발신 MTA / SMTP 서비스
participant DNS as DNS
participant MX as 수신 측 MX
User->>App: 폼 제출
App->>App: From / Reply-To / Sender 결정
App->>SMTP: SMTP 발송 요청
SMTP->>SMTP: DKIM 서명 부여
SMTP->>MX: MAIL FROM / RCPT TO / DATA
MX->>DNS: SPF 조회(MAIL FROM)
MX->>DNS: DKIM 공개 키 조회(selector._domainkey)
MX->>DNS: DMARC 조회(_dmarc + From 도메인)
MX->>MX: Alignment 판정
MX-->>App: 수신·스팸함·거부·bounce
이 흐름에서 중요한 점은 DMARC 판정 기준이 끝까지 From: 도메인 중심이라는 것입니다. 애플리케이션 쪽에서 From:, SMTP 쪽에서 MAIL FROM, DNS 쪽에서 SPF/DKIM/DMARC를 각각 다루기 때문에, 하나만 고쳐서는 미도착이 해결되지 않습니다.
3. 문의 폼에서 자주 발생하는 실패 시나리오
가장 많은 것은 폼 이용자의 주소를 From:에 넣는 경우입니다. 예를 들어 사이트의 SMTP에서 보내면서 From: taro@gmail.com으로 두면, SPF나 DKIM이 통과하는 쪽은 보통 사이트 도메인이고 Gmail 도메인이 아닙니다. 그 결과 From:은 Gmail, 인증된 도메인은 example.com이라는 어긋남이 생기고, DMARC alignment에 실패합니다. Google 스스로도 From: 위장 방지와 From:과 SPF/DKIM 도메인의 일치를 요구합니다.
다음으로 많은 것은 forwarding으로 SPF가 깨지는 경우입니다. 메일 forwarding에서는 최종 수신자가 보는 발신 IP가 “원래 발신 도메인의 SPF에 없는 중계 서버”가 되기 쉽기 때문에, 정상적인 메일도 SPF가 떨어집니다. Google도 “forwarding된 메일은 SPF에 실패하기 쉬우므로 DKIM을 반드시 써야 한다”고 안내합니다. 나아가 중계 측이 본문이나 제목 prefix, footer 추가 등을 하면 DKIM까지 깨집니다.
외부 SMTP 서비스 이용 시 초기 설정 부족도 전형적입니다. SendGrid에서는 Domain Authentication을 설정하지 않으면 발송하지 못하는 경우가 있고, Automated Security를 ON으로 두면 CNAME 기반으로 인증 레코드가 생성되며, 필요하면 Custom Return Path나 Custom DKIM Selector를 설정할 수 있습니다. SES에서는 기본적으로 amazonses.com의 MAIL FROM이 쓰이고 SPF는 암묵적으로 성립하지만, 사이트 도메인과의 SPF alignment를 맞추려면 커스텀 MAIL FROM을 설정해야 합니다. Mailgun에서도 발송 도메인의 SPF/DKIM과 필요한 MX가 없으면 올바른 발송 서명이 성립하지 않습니다.
공유 호스팅의 로컬 MTA는 놓치기 쉬운 함정입니다. 자사 사이트가 인증되어 있어도, 실제로 밖으로 나가는 IP가 공유 IP라 reputation이 나쁘거나, PTR이 없거나, 호스팅 측에 DKIM이 없으면 전달률이 떨어집니다. Google은 발신 IP의 PTR을 요건으로 두고 있으며, 공유 IP의 평가가 나쁘면 5.7.1 계열 오류의 원인이 될 수 있다고 안내합니다.
PHP의 mail()이나 발송 라이브러리 사용법도 실패하기 쉽습니다. PHP 매뉴얼은 mail()에 From 헤더가 필요하다는 점과, 추가 매개변수로 sendmail -f에 의한 envelope 발신자 지정이 가능하다는 점을 설명합니다. 즉 Return-Path: 헤더를 직접 조립하는 것이 아니라 envelope 발신자를 MTA에 넘기는 것이 맞습니다. 여기를 오해하면 SPF 판정에 쓰이는 발신자와 애플리케이션이 가정하는 발신자가 어긋납니다.
마지막으로, Reply-To를 써야 할 자리에서 Sender나 From을 건드리는 경우가 있습니다. 답장 주소만 이용자에게 돌리려면 Reply-To로 충분합니다. Sender는 “작성자와 실제 발송 주체가 다르다”는 점을 명시하고 싶을 때 쓰는 헤더이며, 문의 폼에서 상시 쓰는 것이 아닙니다. 설계 목적이 “답장을 이용자에게 돌리고 싶다”인지, “알림의 책임 주체를 보이고 싶다”인지를 나누면 사고가 줄어듭니다.
4. 진단 절차와 명령
먼저 해야 할 일은 코드를 보기 전에 원본 메일 헤더를 보는 것입니다. Gmail에서는 “메시지 원본 보기”, Outlook에서는 “메시지 상세” 또는 “인터넷 헤더”에서 Authentication-Results, Return-Path, From, Reply-To, DKIM-Signature, Received를 확인할 수 있습니다. 여기를 보면 문제가 “보내지지 않은 것”인지 “인증과 정합성이 깨진 것”인지를 꽤 정확하게 가를 수 있습니다.
헤더에서 먼저 볼 지점
최우선은 다음 다섯 가지입니다.
From:의 도메인이 무엇인가Return-Path:의 도메인이 무엇인가Authentication-Results:에서spf=pass/dkim=pass/dmarc=pass가 나오는가dkim=pass일 때header.i=또는d=가 어느 도메인인가dmarc=fail일 때 이유가 인증 실패인지 alignment failure인지
Google의 DMARC 문제 해결 안내에도, 메시지가 다른 인증은 통과해도 헤더가 align되어 있지 않으면 DMARC에 실패한다고 명시되어 있습니다.
DNS를 확인하는 명령
dig는 DNS 문제 해결용 정석 도구이며, BIND 매뉴얼에서도 유연하고 명확한 출력을 가진 DNS 조회 도구로 설명됩니다. nslookup은 비대화형 모드에서도 쓰는, 더 가벼운 확인용 명령입니다. 문의 폼 인증 확인에서는 최소한 SPF, DKIM, DMARC 세 가지를 조회합니다.
# SPF
dig +short TXT example.com
# DKIM
dig +short TXT form2026._domainkey.example.com
# DMARC
dig +short TXT _dmarc.example.com
# Windows 라면
nslookup -type=txt example.com
nslookup -type=txt _dmarc.example.com
nslookup -type=txt form2026._domainkey.example.com
예상되는 출력 예는 다음 형태입니다.
"v=spf1 include:sendgrid.net include:mailgun.org ip4:203.0.113.10 -all"
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ..."
"v=DMARC1; p=none; rua=mailto:dmarc-agg@example.com; ruf=mailto:dmarc-afrf@example.com; adkim=r; aspf=r; fo=1"
여기서 볼 것은 SPF 레코드가 하나로 모여 있는지, DKIM 공개 키를 조회할 수 있는지, DMARC에 p=가 있는지입니다. SPF는 DNS 조회를 일으키는 메커니즘을 합계 10개까지로 제한해야 한다고 RFC 7208이 정하며, 넘으면 permerror의 원인이 됩니다.
SMTP 연결과 TLS 확인
openssl s_client는 OpenSSL의 범용 SSL/TLS 클라이언트이며, SMTP 서버의 STARTTLS나 인증서 체인 확인에 유용합니다. -starttls smtp로 SMTP의 STARTTLS를 시작하고, -showcerts로 서버가 반환한 인증서 목록을 확인할 수 있습니다.
printf 'QUIT\r\n' | openssl s_client \
-connect smtp.example.com:587 \
-starttls smtp \
-servername smtp.example.com \
-showcerts \
-brief
출력 예입니다.
CONNECTION ESTABLISHED
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Verification: OK
250 CHUNKING
이것으로 적어도 SMTP 서버에 연결할 수 있는지, STARTTLS가 켜져 있는지, 인증서 검증에 명백한 이상이 없는지를 볼 수 있습니다. Google은 일정 규모 이상의 발신자에게 TLS를 요구하며, TLS 미사용은 5.7.29의 원인이 될 수 있습니다.
실제 발송 재현 테스트
swaks는 SMTP 테스트 전용 실무 도구로, TLS, 인증, SMTP 확장을 포함한 발송 테스트를 유연하게 재현할 수 있습니다. 문의 폼 미도착 조사에서는 「애플리케이션을 거치지 않고, 같은 SMTP / 같은 From / 같은 Reply-To / 같은 수신자에게」 한 통만 보내 재현하는 것이 유효합니다.
swaks \
--server smtp.example.com \
--port 587 \
--tls \
--auth LOGIN \
--auth-user contact@example.com \
--auth-password '********' \
--from bounce@example.com \
--to yourtest@gmail.com \
--h-From "사이트 알림 <contact@example.com>" \
--h-Reply-To "홍길동 <visitor@gmail.com>" \
--header "Subject: swaks test" \
--body "This is a test"
발송 성공 시의 전형은 다음과 같습니다.
=== Trying smtp.example.com:587...
=== Connected to smtp.example.com.
<- 250-STARTTLS
<- 250-AUTH LOGIN PLAIN
-> STARTTLS
<- 220 Ready to start TLS
...
<- 250 2.0.0 Ok: queued as ABC123DEF
애플리케이션 경유로는 실패하고 swaks에서는 통과한다면, 원인은 라이브러리의 헤더 조립이나 envelope 발신자 설정 쪽에 있을 가능성이 높습니다. 반대로 swaks에서도 같이 떨어지면 DNS·SMTP·수신 측 정책 문제로 좁힐 수 있습니다.
mail-tester로 외부 진단하기
mail-tester는 무작위 테스트용 주소로 메일을 보내게 한 뒤, 그 메시지, 발송 서버, 발송 IP를 분석해 상세 리포트를 돌려주는 서비스입니다. 로컬 MTA나 공유 서버에서 「왠지 도착하지 않는」 경우의 1차 진단에 맞습니다.
사용법은 단순합니다.
- mail-tester에서 발급한 테스트 주소를 받는다
- 문의 폼과 같은 경로로 한 통 보낸다
- 점수와 SPF / DKIM / DMARC / 역방향 조회 / 블랙리스트 / 본문 구성에 대한 지적을 본다
mail-tester 점수만으로 운영 발송을 판단해서는 안 됩니다. 다만 「SPF가 아예 보이지 않는다」, 「DKIM 공개 키를 조회할 수 없다」, 「본문이나 발신자 구성이 부자연스럽다」 같은 문제는 빨리 찾을 수 있습니다.
헤더 분석 샘플
실패 예입니다.
Return-Path: <bounce-123@vendor.example.net>
Authentication-Results: mx.google.com;
spf=pass (google.com: domain of bounce-123@vendor.example.net designates 198.51.100.10 as permitted sender) smtp.mailfrom=vendor.example.net;
dkim=none;
dmarc=fail (p=quarantine sp=quarantine dis=none) header.from=gmail.com
From: 홍길동 <visitor@gmail.com>
Reply-To: 홍길동 <visitor@gmail.com>
Subject: 문의
이 메일은 SPF 자체는 통과해도 From:이 gmail.com이라 DMARC는 실패합니다. 문의 폼에서 이용자 주소를 From:에 넣은 전형적인 깨진 형태입니다.
성공 예는 다음과 같습니다.
Return-Path: <bounce@example.com>
Authentication-Results: mx.google.com;
spf=pass smtp.mailfrom=example.com;
dkim=pass header.i=@example.com header.s=form2026;
dmarc=pass header.from=example.com
From: Example Site <contact@example.com>
Reply-To: 홍길동 <visitor@gmail.com>
Subject: 문의 알림
이 형태라면 이용자에게 답장하기 쉬운 점은 Reply-To:로 확보하면서, 눈에 보이는 발신자와 인증된 발신자가 모두 example.com으로 맞기 때문에 전달률이 크게 안정됩니다.
5. 권장 From 설계 패턴
문의 폼에서 흔들리지 않는 원칙은 「인증에 쓰는 도메인」과 「수신자에게 보이는 From 도메인」을 맞추는 것입니다. 그 위에서 답장 주소만 Reply-To:로 뺍니다. Sender:는 필요할 때만, Return-Path는 envelope로 설정한다는 삼층 구조로 나누면 설계가 안정됩니다.
| 패턴 | 헤더 예 | 맞는 경우 | 장점 | 주의점 |
|---|---|---|---|---|
| 권장 패턴 | From: contact@example.comReply-To: visitor@gmail.comReturn-Path: bounce@example.com |
거의 모든 문의 폼 | DMARC를 맞추기 쉽다/답장하기 쉽다/구현이 단순하다 | Reply-To를 빼먹으면 답장 주소가 사이트 쪽이 된다 |
| 서브도메인 분리 | From: contact@form.example.comReply-To: visitor@gmail.comReturn-Path: bounce.form.example.com |
폼 알림을 본체 메일과 분리하고 싶다 | reputation을 분리하기 쉽다/관리하기 쉽다 | SPF/DKIM/DMARC를 서브도메인 쪽에서도 갖춰야 한다 |
Sender 명시형 |
From: contact@example.comSender: mailer@example.comReply-To: visitor@gmail.com |
발송 주체를 명시하고 싶은 특수 요건 | 운영 책임 주체를 보일 수 있다 | 보통은 불필요하다. 작성자와 발송 주체가 같으면 중복이다 |
| 비권장 패턴 | From: visitor@gmail.comReply-To: visitor@gmail.com |
답장 주소만 눈에 띄게 하고 싶은 구현 | 겉모습만은 자연스럽다 | DMARC 실패의 원인이 되기 쉽다. 문의 알림에서는 피해야 한다 |
이 표의 근거는 RFC 5322의 From / Sender / Reply-To 의미와 RFC 5321의 Return-Path 취급, 그리고 DMARC가 From: 기준으로 정합성을 판정한다는 사양입니다. 폼 알림의 기본값은 1행의 「권장 패턴」으로 충분합니다. From:에 이용자 주소를 두고 싶은 장면에서도, 답장 주소를 Reply-To:에 넣으면 목적은 달성됩니다.
특히 기억할 점은 Return-Path는 「편집하는 헤더」가 아니라 「배송에 쓰는 envelope 발신자의 결과」라는 것입니다. PHP mail()이라면 -f, SMTP 서비스라면 Custom MAIL FROM / Return Path / bounce domain 같은 설정 항목으로 다루는 것이 올바른 구현입니다.
6. 구성별 설정 가이드
여기부터는 현장에서 많은 세 가지 패턴별로 설정 관점을 정리합니다. 전제로, DNS에 넣을 정확한 값은 각 서비스 관리 화면이 내주는 값을 우선하십시오. 아래 레코드 예는 구조를 이해하기 위한 대표 예입니다.
사이트가 외부 SMTP를 쓰는 경우
외부 SMTP의 가장 중요한 점은 자사 도메인 인증을 먼저 끝내는 것입니다. Google도 메일 서비스 제공자를 쓸 때는 그 서비스가 자사 도메인의 SPF와 DKIM을 인증하고 있는지 확인하라고 안내합니다.
권장 구성
From:은contact@example.com또는contact@form.example.comReply-To:는 폼 이용자 주소Return-Path/ MAIL FROM은bounce.example.com등 자신이 관리하는 bounce용 서브도메인- DKIM은
example.com또는 발송용 서브도메인으로 서명 - DMARC는 보이는
From:도메인에 둔다
SendGrid의 전형 설정
SendGrid에서는 Domain Authentication이 전제이며, Automated Security를 ON으로 두면 CNAME 3개가 생성됩니다. OFF인 경우에는 MX 1개와 TXT 2개가 생성되며, Custom Return Path나 Custom DKIM Selector도 설정할 수 있습니다.
; 예: SendGrid(실제 값은 관리 화면에서 생성된 것을 쓴다)
em123.example.com. CNAME u123456.wl.sendgrid.net.
s1._domainkey.example.com. CNAME s1.domainkey.u123456.wl.sendgrid.net.
s2._domainkey.example.com. CNAME s2.domainkey.u123456.wl.sendgrid.net.
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-agg@example.com"
SendGrid에서 빠지기 쉬운 것은 「SMTP 인증만 마치고 도메인 인증은 미설정」인 상태입니다. 이 상태면 발송 자체는 되더라도, 수신 측에서 보면 From:과 인증된 도메인의 관계가 약해집니다. Domain Authentication을 통과시키고, 그 위에서 Custom Return Path를 필요에 따라 설정하는 것이 기본입니다.
SES의 전형 설정
SES는 기본적으로 amazonses.com 서브도메인의 MAIL FROM을 쓰므로 SPF 자체는 암묵적으로 성립합니다. 다만 사이트 도메인과 SPF alignment를 맞추려면 커스텀 MAIL FROM을 씁니다. 이때 SES는 커스텀 MAIL FROM 도메인에 SPF TXT와 MX를 요구하며, MX는 정확히 1개여야 합니다. 또한 Easy DKIM에서는 CNAME 3개를 DNS에 추가합니다.
; 예: SES Easy DKIM
abcde12345._domainkey.example.com. CNAME abcde12345.dkim.amazonses.com.
fghij67890._domainkey.example.com. CNAME fghij67890.dkim.amazonses.com.
klmno54321._domainkey.example.com. CNAME klmno54321.dkim.amazonses.com.
; 예: SES custom MAIL FROM
bounce.example.com. MX 10 feedback-smtp.ap-northeast-1.amazonses.com.
bounce.example.com. TXT "v=spf1 include:amazonses.com -all"
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-agg@example.com"
SES 설계에서 중요한 점은 MAIL FROM용 도메인은 발송용 From: 도메인 자체가 아니라 bounce 전용 서브도메인으로 두는 것입니다. AWS도 MAIL FROM은 실제로 메일을 보내는 도메인 자체가 아닌 서브도메인으로 두라고 안내합니다.
Mailgun의 전형 설정
Mailgun에서는 발송 도메인 검증 시 SPF용 TXT와 DKIM용 TXT가 필요하고, 여기에 MX 2개를 추가합니다. 이미 SPF가 있으면 새 SPF 레코드를 늘리는 것이 아니라 기존 레코드에 include:mailgun.org를 넣습니다. DKIM 키가 여러 개 보이는 경우가 있지만, 지금 쓰는 키가 DNS에 올바르게 올라가 있으면 발송은 가능합니다.
; 예: Mailgun을 서브도메인으로 쓴다
mg.example.com. TXT "v=spf1 include:mailgun.org ~all"
mx._domainkey.mg.example.com. TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ..."
mg.example.com. MX 10 mxa.mailgun.org.
mg.example.com. MX 10 mxb.mailgun.org.
email.mg.example.com. CNAME mailgun.org.
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-agg@example.com"
Mailgun은 서브도메인 운영과 궁합이 좋으므로, mg.example.com 같은 전용 발송 서브도메인을 나누면 폼 알림이나 트랜잭션 알림 관리가 쉬워집니다.
사이트가 공유 호스팅의 로컬 MTA로 보내는 경우
공유 호스팅에서 먼저 볼 것은 자기 애플리케이션이 아니라 호스팅 측 발송 기반의 품질입니다. 발송 IP의 PTR, DKIM 대응, 공유 IP의 평가, 발송 로그 가시성이 약하면 이 구성은 그것만으로도 불리합니다. Google도 발송 IP의 PTR을 중시하며, 공유 IP 평가가 나쁘면 차단 원인이 될 수 있다고 안내합니다.
실무에서는 이 순서로 진행하는 것이 안전합니다.
- 호스팅 회사가 SPF/DKIM/PTR을 관리 화면 또는 지원으로 설정 가능한지 확인한다
From:은 반드시 자사 도메인으로 고정한다- SPF에 호스팅의 발송 IP 또는 허용된 발송 도메인을 넣는다
- DKIM을 호스팅 기능으로 활성화한다. 없으면 외부 SMTP로 전환한다
- 가능하면 MAIL FROM용 bounce 주소를
bounce.example.com처럼 나눈다
공유 렌탈 서버에서는 먼저 계약처에 확인한다
공유 렌탈 서버에서는 발송 기반을 직접 만질 수 있는 범위가 한정됩니다. 손을 대기 전에 관리 화면·매뉴얼·지원 창구에서 다음을 확인하십시오.
| 확인할 것 | 확인할 수 없거나 할 수 없을 때의 의미 |
|---|---|
| 발송 메일에 자사 도메인으로 DKIM 서명을 붙이는 기능이 있는지 | DKIM이 없으면 forwarding으로 SPF가 떨어진 시점에 DMARC도 떨어집니다 |
| SPF 레코드를 직접 편집할 수 있는지(DNS를 다른 회사에서 관리하는 경우 포함) | 발송원을 SPF에 추가하지 못해 spf=fail을 고칠 수 없습니다 |
| 발송에 쓰이는 IP와 그 PTR(역방향 조회)이 어떻게 되어 있는지 | 역방향 조회 미비는 수신 측에서 거부 이유가 됩니다 |
| 공유 IP인지 전용 IP인지 | 공유 IP는 같은 IP를 쓰는 다른 이용자의 발송 품질 영향을 받습니다 |
| 메일 배송 로그를 볼 수 있는지 | 「보냈는지, 거부됐는지」를 가를 수 없습니다 |
envelope 발신자(-f 상당)를 지정할 수 있는지 |
bounce 수신처와 SPF 판정에 쓰이는 발신자를 제어할 수 없습니다 |
이 중 DKIM 서명 가능 여부와 배송 로그 가능 여부가 「이 환경에서 조사와 개선이 되는가」의 갈림입니다. 둘 다 「안 된다」면 폼 알림만 외부 SMTP로 옮기는 것이 빠른 길입니다. 폼 알림은 발송량이 적고 전환 영향 범위도 한정적이라, 첫 이전 대상으로 다루기 쉬운 편입니다.
공유 호스팅에서 직접 DKIM을 만드는 전형 예로, OpenDKIM 계열에서는 opendkim-genkey로 비밀 키와 DNS용 TXT 레코드를 생성할 수 있습니다. DKIM 공개 키를 selector가 붙은 selector._domainkey.example.com에 둔다는 구조는 RFC 6376과 일치합니다.
mkdir -p /etc/opendkim/keys/example.com
opendkim-genkey -D /etc/opendkim/keys/example.com -d example.com -s form2026
chown opendkim:opendkim /etc/opendkim/keys/example.com/form2026.private
chmod 600 /etc/opendkim/keys/example.com/form2026.private
생성 후 이미지는 다음과 같습니다.
form2026._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ..."
# /etc/opendkim/KeyTable
form2026._domainkey.example.com example.com:form2026:/etc/opendkim/keys/example.com/form2026.private
# /etc/opendkim/SigningTable
*@example.com form2026._domainkey.example.com
다만 공유 호스팅에서 PTR이나 outbound relay를 직접 제어하지 못한다면 외부 SMTP로 옮기는 편이 지름길입니다. 문의 폼 알림처럼 소량 발송이어도, 인증이 약한 로컬 MTA는 Gmail이나 기업 메일에 불리합니다.
사이트가 PHP mail() 또는 SMTP 라이브러리를 쓰는 경우
PHP mail()은 편리하지만, 인증과 전달률 관점에서는 「그 앞의 MTA가 무엇인지」에 의존합니다. PHP 매뉴얼은 메일에 From 헤더가 필요하며, sendmail_path 경유 발송에서는 추가 매개변수로 envelope 발신자를 지정할 수 있다고 설명합니다. 반대로 말하면 mail()을 써도 SPF/DKIM/DMARC가 자동으로 갖춰지지는 않습니다.
우선 최소한 이렇게 설계합니다.
From:은contact@example.comReply-To:는 폼 이용자- envelope 발신자는
bounce@example.com - 본문에는 이용자 주소도 명시한다
- 가능하면
mail()이 아니라 인증된 SMTP를 쓴다
mail()의 최소 구성 예
헤더에 이용자 입력을 그대로 넣는 것은 위험합니다. $name이나 $email에 CR/LF가 섞이면 공격자가 Bcc: 같은 추가 헤더를 끼워 넣을 수 있어, 폼이 스팸 중계기가 됩니다. PHP 매뉴얼도 헤더에 쓰는 외부 입력은 반드시 검증/정규화하라고 안내합니다. 아래 예에서는 envelope 발신자 인수(additional_params)를 포함해, 헤더에 넣는 값은 미리 sanitize합니다.
<?php
// 헤더에 써도 되는 값만 반환한다. CR/LF/NUL이 있으면 거부한다.
function sanitize_header_value(string $value): string {
if (preg_match('/[\r\n\0]/', $value)) {
throw new InvalidArgumentException('Invalid characters in header value');
}
return trim($value);
}
// 메일 주소를 RFC에 맞게 검증한다.
function sanitize_email(string $email): string {
$clean = sanitize_header_value($email);
if (!filter_var($clean, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Invalid email address');
}
return $clean;
}
$to = 'ops@example.com';
$subject = sanitize_header_value('문의 알림');
// $name / $email / $message는 폼 입력. $message는 본문용이므로 CR/LF를 허용하는 한편,
// 헤더에 쓰는 $name / $email은 CR/LF를 반드시 걸러 낸다.
$safeName = sanitize_header_value($name);
$safeEmail = sanitize_email($email);
$body = <<<TEXT
Name: {$safeName}
Email: {$safeEmail}
{$message}
TEXT;
$headers = [
'From' => 'Example Site <contact@example.com>',
'Reply-To' => sprintf('%s <%s>', $safeName, $safeEmail),
'Content-Type' => 'text/plain; charset=UTF-8',
];
// additional_params도 셸에 넘어가므로 고정값만 쓰고 동적 입력은 섞지 않는다.
mail($to, $subject, $body, $headers, '-fbounce@example.com');
이 예의 핵심은 두 가지입니다. 하나는 Return-Path:를 헤더로 쓰지 않고, 다섯 번째 인수의 -f로 envelope 발신자를 넘긴다는 점입니다. 다른 하나는 Reply-To: 등 헤더에 넣는 이용자 입력을 CR/LF를 걸러 내는 sanitize 함수에 통과시킨다는 점입니다. sanitize 없이 헤더를 조립하면 공격자가 \r\nBcc: victim@example.com 같은 문자열을 흘려 넣어 추가 헤더를 끼울 수 있으므로, PHP 매뉴얼에서도 외부 입력을 헤더에 쓸 때의 검증은 필수입니다. additional_params도 최종적으로 셸에 넘어가므로 이용자 입력을 섞지 말고 고정값으로 넘기십시오.
SMTP 라이브러리를 쓰는 예
<?php
$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Username = getenv('SMTP_USER');
$mail->Password = getenv('SMTP_PASS');
$mail->setFrom('contact@example.com', 'Example Site');
$mail->addAddress('ops@example.com');
$mail->addReplyTo($email, $name);
// 라이브러리에 따라 Sender / return-path를 따로 설정할 수 있다
$mail->Sender = 'bounce@example.com';
$mail->Subject = '문의 알림';
$mail->Body = $body;
$mail->send();
SMTP 라이브러리의 이점은 헤더 발신자와 envelope 발신자를 나눠 제어하기 쉽다는 것입니다. 문의 폼 용도에서는 From:을 사이트 도메인으로 고정하고 답장 주소만 Reply-To:에 두는 설계에 가장 맞습니다.
SPF·DKIM·DMARC의 구체 예
SPF의 기본 예
example.com. TXT "v=spf1 ip4:203.0.113.10 include:sendgrid.net -all"
SPF에서는 실제로 보내는 발송원을 모두 넣어야 합니다. 서드파티 발신자를 쓰는 경우 Google도 그 발신자를 SPF와 DKIM으로 인증하고 있는지 확인하라고 요구합니다. 또한 SPF는 DNS 조회 횟수 제한이 있으므로 include를 너무 쌓지 않도록 주의해야 합니다.
DKIM의 기본 예
form2026._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ..."
selector는 키 로테이션에 쓰이며, 여러 공개 키를 같은 도메인에 공존시킬 수 있습니다. 운영에서는 default보다 용도나 연월로 구별되는 이름이 나중에 보기 쉽습니다.
DMARC 도입 예
먼저 관측 모드입니다.
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-agg@example.com; ruf=mailto:dmarc-afrf@example.com; adkim=r; aspf=r; fo=1"
다음은 일부를 격리하고 싶을 때입니다.
_dmarc.example.com. TXT "v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc-agg@example.com; adkim=r; aspf=r"
마지막으로 엄격 운영입니다.
_dmarc.example.com. TXT "v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc-agg@example.com; adkim=s; aspf=s"
p=none은 모니터링만, quarantine은 격리 권장, reject는 SMTP 단계에서의 거부 권장을 의미합니다. adkim과 aspf는 strict/relaxed를 전환합니다. 처음부터 reject로 가기보다 none으로 유입량과 정상 발송원을 관측한 뒤 단계적으로 올리는 편이 안전합니다.
또한 rua / ruf를 사외 집계 서비스로 보내는 경우, RFC 7489에서는 제3자 측에 추가 DNS 레코드가 필요합니다. 예를 들어 example.com의 리포트를 thirdparty.example.net으로 보내려면, 수신 측은 example.com._report._dmarc.thirdparty.example.net TXT "v=DMARC1"을 공개해야 합니다.
7. 문제 해결 체크리스트
마지막으로 현장에서 그대로 쓸 수 있는 확인 순서를 정리합니다. 문의 폼 메일 미도착은 위에서부터 순서대로 지워 가는 것이 빠른 길입니다.
먼저 확인할 것
From:이 자사 도메인인가Reply-To:에 이용자 주소를 넣었는가Authentication-Results에spf=pass또는dkim=pass가 있고, 게다가dmarc=pass인가dmarc=fail이면 인증 실패인가 alignment failure인가- SPF가 레코드 하나로 모여 있는가
- SPF 조회 횟수가 너무 많지 않은가
- DKIM 공개 키를 조회할 수 있는가
- DMARC에
p=가 있는가 - 발송 IP의 PTR과 역방향 조회가 타당한가
- 공유 IP를 쓰지 않는가, 또는 reputation이 나빠지지 않았는가
bounce와 로그에서 볼 곳
bounce 메일이 왔다면 message/delivery-status 형식 DSN 안의 Final-Recipient, Status, Action, Diagnostic-Code가 중요합니다. RFC 3464는 이런 기계 가독 배송 실패 정보를 정의합니다. 예를 들어 Diagnostic-Code: smtp; 550 relay not permitted 같은 행이 있으면 애플리케이션 층이 아니라 SMTP 측 거부입니다.
서버 측에서는 적어도 MTA의 배송 로그를 봅니다. Postfix라면 배송 성공·실패, 큐 체류, 릴레이 거부, DNS 해석 실패, DKIM milter 경고가 나옵니다. Exim도 마찬가지입니다. 대표적인 확인 명령을 듭니다.
# 예: Postfix
journalctl -u postfix -n 200 --no-pager
postqueue -p
# 예: Exim
exim -bp
호스팅에 따라 로그 경로나 명령 권한이 다르므로, 「애플리케이션 로그」가 아니라 「메일 배송 로그」를 볼 수 있는지를 먼저 확인하십시오. 여기가 보이지 않는 환경에서는 외부 SMTP로 옮기는 편이 문제 분석이 쉬워집니다.
Gmail과 Outlook에서 보는 법
Gmail에서는 「메시지 원본 보기」, Microsoft의 Outlook에서는 「메시지 상세」나 「인터넷 헤더」에서 원본 헤더를 확인할 수 있습니다. 문의 폼 미도착 조사에서는 스크린샷보다 헤더 전문 텍스트를 저장해 비교하는 것이 유효합니다.
수신 측 오류 구별법
Gmail 계열 오류는 코드에서 원인을 읽기 쉽습니다.
| 오류 예 | 의미 | 주된 대처 |
|---|---|---|
5.7.27 |
SPF 불합격 | SPF 레코드에 발송원을 추가 |
5.7.30 |
DKIM 불합격 | DKIM 키·서명 설정을 수정 |
4.7.32 |
From:과 SPF/DKIM의 조직 도메인 불일치 |
From: 설계를 재검토 |
5.7.25 |
PTR / 역방향 조회 미비 | 발송 IP의 역방향 조회를 갖춘다 |
Google FAQ에도 이런 오류와 대처 방침이 명시되어 있습니다. 문의 폼에서 특히 많은 것은 4.7.32의 alignment 불일치입니다.
마지막 판단 기준
다음 세 조건을 동시에 충족하면 문의 폼 알림 설계는 단단하다고 할 수 있습니다.
From:이example.com하위Reply-To:가 폼 이용자 주소Authentication-Results에dmarc=pass가 나온다
이 세 가지가 갖춰지면 SendGrid·SES·Mailgun·공유 호스팅·SMTP 라이브러리 중 무엇을 쓰더라도 설계로서는 이치가 맞습니다. 반대로 하나라도 빠지면 먼저 From: 설계부터 의심하는 것이 가장 짧습니다.
참고 링크
사양과 각 서비스의 1차 정보입니다. DNS에 넣는 실제 값은 반드시 이용 중인 서비스가 제시하는 값을 우선하십시오.
사양(RFC)
- RFC 5321 - Simple Mail Transfer Protocol ─ envelope,
MAIL FROM,Return-Path취급 - RFC 5322 - Internet Message Format ─
From:Sender:Reply-To:의 의미 - RFC 7208 - Sender Policy Framework (SPF) ─ DNS 조회 횟수 상한을 포함한 SPF 사양
- RFC 6376 - DomainKeys Identified Mail (DKIM) Signatures ─ selector,
d=, 서명 대상 - RFC 7489 - Domain-based Message Authentication, Reporting, and Conformance (DMARC) ─ alignment,
p=, 리포트의 외부 수신처 - RFC 3464 - An Extensible Message Format for Delivery Status Notifications ─ bounce(DSN) 읽는 법
수신 측 가이드라인
- 메일 발신자 가이드라인 - Gmail 도움말 ─ SPF / DKIM / DMARC, PTR,
From:일치 요건 - Gmail의 SMTP 관련 오류와 코드 - Google Workspace 관리자 도움말 ─
5.7.x/4.7.x의 의미와 대처
발송 서비스·구현
- How to Set Up Domain Authentication - SendGrid ─ CNAME 방식, Custom Return Path
- Configuring a custom MAIL FROM domain - Amazon SES ─ MX와 SPF 요건
- Easy DKIM in Amazon SES ─ CNAME 3개
- Domains - Mailgun Documentation ─ 발송 도메인 검증에 필요한 레코드
- PHP: mail - Manual ─ 헤더 취급과
additional_params(-f) - swaks - Swiss Army Knife for SMTP ─ 실제 발송 테스트
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
정보보안 10대 위협 2026 ── 순위를 읽는 법과, 중소기업이 실제로 대비해야 할 것
IPA 「정보보안 10대 위협 2026」에서는 랜섬 공격이 11년 연속 1위, 공급망 공격이 2위, 처음 선정된 「AI 이용을 둘러싼 사이버 리스크」가 3위에 올랐습니다. 조직편 톱 10의 내용과, 중소기업이 어떤 위협을 자기 일로 받아들여 대비...
「몇 초면 만족인가」를 빠뜨리지 않으려면 ── IPA 「비기능 요구 등급」으로 비기능 요구사항을 정리하기
「속도가 느리다」「장애 대응이 예상과 다르다」로 다투는 원인 대부분은 비기능 요구사항을 정하지 않은 데 있습니다. IPA 「비기능 요구 등급」의 6대 항목, 등급표와 모델 시스템 사용법, 현실적인 활용법을 발주 측이 이해하기 쉽게 설명합니다.
홈페이지 발주 담당자도 알아 두면 좋은 점 ── IPA 「안전한 웹사이트 만드는 법」을 체크리스트로 활용하기
회사 홈페이지의 보안은 무엇을 기준으로 확인해야 할까요. IPA 「안전한 웹사이트 만드는 법」이 다루는 11가지 취약점과 대책을, 발주 담당자와 운영 담당자도 이해할 수 있는 말로 설명하고, 발주·검수·운영에서의 활용법을 소개합니다.
중소기업의 보안 대책, 무엇부터 시작할까 ── IPA 「중소기업의 정보보안 대책 가이드라인」 제4.0판 활용법
중소기업 보안 대책은 무엇부터 시작해야 할까요. IPA 「중소기업의 정보보안 대책 가이드라인」 제4.0판을 바탕으로 정보보안 6개 조항, 5분이면 끝나는 자사 진단, SECURITY ACTION까지 단계적으로 설명합니다.
왜 이메일 보안에서 PPAP는 안 되는가. 올바른 방법은?
비밀번호가 걸린 ZIP을 메일로 보내고, 다른 메일로 비밀번호를 보내는 PPAP가 왜 위험한지를 정리하고, TLS / S/MIME / 인증이 있는 다운로드라는 현실적인 대체 수단을 실무 관점에서 정리합니다.
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
웹사이트 제작
문의 폼 설계, 알림 메일의 발신자 운영, Reply-To 설계를 포함한 문의 경로 정리는 홈페이지 제작과 함께 진행하기 쉬운 주제이기 때문입니다.
기술 상담 & 설계 리뷰
SPF / DKIM / DMARC, 외부 SMTP 서비스(SendGrid / SES / Mailgun), 공유 호스팅, PHP mail() 중 무엇을 쓸지는 현재 구성과 요건에 맞춘 설계 리뷰로 정리하기 쉽기 때문입니다.
자주 묻는 질문
이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.
- 문의 폼 이메일이 도착하지 않는 가장 흔한 원인은 무엇인가요?
- SMTP 연결 자체의 문제가 아니라, 눈에 보이는 발신자(From:)와 실제로 인증되는 발신자(SPF의 MAIL FROM / DKIM의 d=)가 맞지 않는 것이 원인입니다. 특히 많은 것은 폼 이용자의 Gmail 주소를 그대로 From:에 넣는 설계입니다. 사이트의 SMTP에서 보내면서 From: taro@gmail.com으로 설정하면, 인증되는 것은 사이트 쪽 도메인인데 From:은 Gmail이라는 불일치가 생겨 DMARC alignment에 실패합니다.
- 문의 폼 알림 메일의 From은 어떻게 설정해야 하나요?
- From:은 자사 도메인으로 고정하고, 폼 이용자의 주소는 Reply-To:에 넣는 것이 기본입니다. 이렇게 하면 답장의 편의성을 확보하면서도, 눈에 보이는 발신자와 인증된 발신자가 도메인 단위로 일치하기 때문에 전달률이 안정됩니다. Sender:는 작성자와 실제 발송 주체가 다를 때만 사용하며, Return-Path는 헤더를 직접 작성하는 것이 아니라 MTA나 메일 서비스 쪽에서 envelope 발신자로 설정합니다.
- 메일 미도착 조사는 먼저 무엇을 해야 하나요?
- 코드를 보기 전에 실제로 도착한 메일의 원본 헤더를 보는 것입니다. Gmail이라면 '메시지 원본 보기'에서 Authentication-Results, Return-Path, From, DKIM-Signature를 확인합니다. 최우선으로 볼 것은 From:의 도메인, Return-Path:의 도메인, 그리고 spf / dkim / dmarc가 pass하고 있는지입니다. dmarc=fail이라면 인증 실패인지 alignment failure인지를 구분합니다. DNS 쪽은 dig나 nslookup으로 SPF·DKIM·DMARC 세 가지 레코드를 조회해 확인합니다.
- DMARC를 처음부터 reject로 설정해도 되나요?
- 처음부터 reject로 설정하기보다, 먼저 p=none의 관측 모드로 유입량과 정상 발송원을 확인한 다음 quarantine, reject로 단계적으로 올리는 것이 안전합니다. p=none은 모니터링만, quarantine은 격리 권장, reject는 SMTP 단계에서의 거부 권장을 의미합니다. 또한 forwarding은 SPF를 쉽게 깨뜨리고, 중계 과정에서 본문이나 헤더가 변경되면 DKIM도 깨지기 때문에 SPF에만 의존하지 말고 DKIM을 반드시 활성화해 두는 것도 중요합니다.