Skip to main content

SMTP


SMTP

template/smtp.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css");
</style>
<title>Title</title>
</head>
<body>
{{.Something}}
</body>
</html>
package smtp

import (
"bytes"
"net/smtp"
"text/template"
)

var (
auth smtp.Auth
address string
from string
)

func Init() {
c := config.Config()

auth = smtp.PlainAuth("", c.SMTP.Username, c.SMTP.Password, c.SMTP.Host)
address = c.SMTP.Host + ":" + c.SMTP.Port
from = c.SMTP.Username
}

func Send(to, something string) error {
header := "To: " + to + "\r\n" +
"Subject: 제목\n" +
"MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"

var body bytes.Buffer
t, _ := template.ParseFiles("template/smtp.html")
t.Execute(&body, struct {
Something string
}{
Something: something,
})

return smtp.SendMail(
address,
auth,
from,
[]string{to},
append(header, body.Bytes()...),
)
}
info

SMTP 프로토콜은 RFC 2921에 정의되어 있습니다. SMTP는 라인 단위로 커맨드, 데이터 등을 보내는 데, 라인을 구분하는 기호는 <CRLF>입니다. html로 내용을 보낼 때, 줄바꿈은 <br />을 사용하는 것이 원칙이지만 <LF>를 인식하는 경우도 있는 것 같습니다. 전송 또는 전송 내용에 오류가 있다면 줄바꿈을 바꿔가면서 테스트 해보시기 바랍니다.

Gmail

  • Google 계정 관리 -> 보안 -> Google에 로그인
    • 2 단계 인증
    • 앱 비밀번호
      • 앱 선택: 메일
      • 기기 선택: 기타
  • Realm Settings
    • Email
      • Host: smtp.gmail.com
      • Port: 587
      • From: <email>
      • Enable StartTLS: on
      • Enable Authentication: on
        • Username: <username>
        • Password: <password> # 앱 비밀번호를 입력하세요.

Email authentication

info

이메일의 원문을 보면 인증을 위한 정보가 있습니다.

Sender Policy Framework(SPF)

DNS의 TXT 레코드에 해당 도메인으로 이메일을 보낼 수 있는 서버를 명시하고, 이를 활용하여 메일을 인증하는 방식입니다.

<domain> text = "v=spf1 [guest list] <redirect=<domain>|<qualifier>all>"
  1. 사용자는 메일 송신 서버로 메일을 보냅니다.
  2. 메일 송신 서버는 Delivered-To를 확인하여 메일 수신 서버로 메일을 보냅니다.
  3. 메일 수신 서버는 Return-Path에 등록된 도메인의 (v=spf1으로 시작하는) TXT 레코드에서 메일 송신 서버의 IP를 찾습니다.
  4. 확인이 되면 해당 메일은 등록된 도메인에서 인증한 메일로 간주 됩니다.
  • <qualifier>
    • +: pass
    • -: fail
    • ~: softfail
    • ?: neutral
nslookup -type=txt <domain>

Domain Keys Identified Mail(DKIM)

DNS의 TXT 레코드에 DKIM 퍼블릭 키를 등록하고, 이를 활용하여 메일을 인증하는 방식입니다.

<subdomain>.<domain> text = "v=DKIM1; k=<type>; p=<public key>"
info

<selector>._domainkey와 같은 서브도메인을 주로 사용합니다.

  1. 사용자는 메일 송신 서버로 메일을 보냅니다.
  2. 메일 송신 서버는 사전 등록된 DKIM 프라이빗 키를 사용하여 DKIM-Signature를 생성한 후 메일의 헤더에 추가합니다.
  3. 메일 송신 서버는 Delivered-To를 확인하여 메일 수신 서버로 메일을 보냅니다.
  4. 메일 수신 서버는 DKIM-Signatured=<subdomain>.<domain>을 확인하여 (v=DKIM1으로 시작하는) TXT 레코드에서 퍼블릭키를 찾습니다.
  5. 퍼블릭키로 서명을 복호화 하여 위변조 여부를 판단합니다.
nslookup -type=txt <domain>

Domain-based Message Authentication Reporting and Conformance (DMARC)

SPF, DKIM과 함께 사용되며, 앞선 인증 절차를 통과하지 못한 경우 처리 절차를 DNS TXT 레코드에 서술합니다.

_dmarc.<domain> text = "v=DMARC1; p=reject; adkim=s; aspf=s; rua=mailto:<email>"
  1. 메일 수신 서버에서 SPF, DKIM 인증을 수행합니다.
  2. 인증에 실패한 경우 _dmarc.<domain>을 확인하여 (v=DMARC1으로 시작하는) TXT 레코드에서 처리 절차를 확인합니다.
nslookup -type=txt _dmarc.<domain>