# Apa Itu SMTP: Cara Kerja Email, SPF, DKIM, dan DMARC

> Apa itu SMTP dan cara kerjanya: dialog EHLO sampai DATA, port 25, 587, dan 465, lookup MX, serta cara SPF, DKIM, dan DMARC menilai email aplikasi Anda.

URL: https://www.matthewswong.com/id/learn/devops-from-zero/how-smtp-works-spf-dkim-dmarc/

DevOps dari nol · Pelajaran 18 dari 25 · Ditinjau pada 18 Oktober 2026 · Oleh Matthews Wong (https://www.matthewswong.com/id/about/)

> SMTP, Simple Mail Transfer Protocol, adalah cara server email saling menyerahkan pesan: EHLO, MAIL FROM berisi envelope sender, RCPT TO, lalu DATA. Aplikasi mengirim pesan lewat port 587 atau 465; antar server, pesan diteruskan lewat port 25 ke MX penerima. Server penerima lalu memeriksa SPF pada domain envelope, signature DKIM, dan keselarasan DMARC dengan header From.

## Setelah pelajaran ini, Anda bisa

- Menelusuri satu pesan dari submission, lookup MX, sampai relay di port 25, dan membaca percakapan EHLO sampai DATA.
- Menyebut domain mana yang diperiksa SPF, DKIM, dan DMARC, dan membaca hasilnya di header Authentication-Results.
- Menjelaskan kenapa aplikasi mengirim dari domainnya sendiri dan menaruh alamat pengunjung di Reply-To, bukan di From.

## Satu email dari form kontak sampai inbox

Aplikasi menyerahkan pesan ke penyedia, yang mencari MX penerima di DNS lalu meneruskannya lewat port 25; server penerima memeriksa SPF pada envelope, signature DKIM, dan keselarasan DMARC dengan From sebelum mengirimkannya ke inbox.

1. **Kenali bagiannya.** Satu pesan dari form kontak, dari awal sampai akhir. Aplikasi menyerahkannya ke penyedia email, DNS menunjukkan jalannya, dan server penerima menjalankan tiga pemeriksaan sebelum inbox.
2. **Serahkan ke penyedia.** Aplikasi tidak pernah membuka port 25 sendiri. Pesan diserahkan ke penyedia: situs ini memanggil API HTTPS, aplikasi lain mengirim lewat SMTP di port 587 atau 465.

   ```
   POST https://api.resend.com/emails
   ```

   *Tebak:* Penyedia kini memegang pesan untuk alamat di gmail.com. Bagaimana ia menemukan server yang menerimanya? (Ia menanyakan record MX gmail.com ke DNS / Ia terhubung ke website di gmail.com / Aplikasi memberi tahu server mana yang dipakai)
3. **Cari record MX.** Penyedia menanyakan record MX domain penerima ke DNS dan mencoba angka preference terkecil lebih dulu. Domain tanpa record MX sama sekali dipakai sebagai implicit MX untuk dirinya sendiri.

   ```
   dig @one.one.one.one MX gmail.com +short
   5 gmail-smtp-in.l.google.com.
   10 alt1.gmail-smtp-in.l.google.com.
   ```
4. **Relay di port 25.** Server penyedia membuka sesi SMTP ke MX di port 25: EHLO, MAIL FROM berisi envelope sender, RCPT TO, lalu DATA yang membawa header From dan body.

   ```
   EHLO
   MAIL FROM   the envelope sender
   RCPT TO     the recipient
   DATA        headers, body, a lone .
   250 OK
   ```

   *Tebak:* Envelope sender ada di send.noreply.matthewswong.com, header From di noreply.matthewswong.com. Domain mana yang diperiksa SPF? (Domain di header From / Domain envelope sender, dari MAIL FROM)
5. **Periksa SPF dan DKIM.** SPF menanyakan ke DNS apakah server ini boleh mengirim atas nama domain MAIL FROM. DKIM mengambil public key di selector._domainkey milik domain penanda tangan lalu memeriksa signature-nya.

   ```
   send.noreply.matthewswong.com
     v=spf1 include:amazonses.com ~all
   resend._domainkey.noreply.matthewswong.com
     p=MIGfMA0G...
   ```
6. **DMARC meminta keselarasan.** DMARC membaca record _dmarc milik domain From. Hasilnya pass hanya jika SPF atau DKIM lolos untuk domain yang selaras dengan From; jika tidak, tag p= meminta none, quarantine, atau reject.

   ```
   From domain       noreply.matthewswong.com
   MAIL FROM domain  send.noreply.matthewswong.com
   relaxed: same organizational domain
   strict:  identical domain
   ```
7. **Kirim beserta hasilnya.** Server mencatat setiap hasil di header Authentication-Results lalu mengantarkan pesan ke inbox. Kegagalan DMARC dengan p=reject bisa dijawab kode 5xx pada DATA, dan pihak pengirim yang wajib melaporkannya.

   ```
   Authentication-Results: mx.example.com;
     spf=pass smtp.mailfrom=example.com;
     dkim=pass header.d=example.com;
     dmarc=pass header.from=example.com
   ```

## Apa itu SMTP, dan port mana untuk apa?

SMTP, Simple Mail Transfer Protocol, memindahkan sebuah mail object dari satu server ke server berikutnya. RFC 5321 membaginya menjadi dua. Envelope berisi alamat pengirim, yaitu tujuan laporan error, dan satu atau lebih alamat penerima. Content adalah bagian header dan body, bagian yang dibaca manusia.

Ada tiga port yang penting. Port 25 dipakai antar server untuk relay. RFC 6409 tetap menaruh relay di sana dan mengkhususkan port 587 untuk submission, tempat aplikasi atau mail client menyerahkan pesan baru, dan server submission secara default wajib menolak MAIL sebelum sesi terautentikasi. Port 465 adalah submission dengan implicit TLS: handshake dimulai begitu koneksi terbuka. RFC 8314 lebih menyarankannya daripada STARTTLS di 587, dan meminta keduanya didukung selama masa transisi.

## Seperti apa percakapan SMTP?

Satu sesi adalah dialog singkat berisi perintah dan balasan tiga digit. Server menyapa dengan 220. Client mengirim EHLO beserta namanya, lalu MAIL FROM:<alamat> berisi envelope sender, satu RCPT TO:<alamat> untuk tiap penerima, lalu DATA. Setelah balasan 354, client mengirim header dan body, lalu menutupnya dengan baris yang hanya berisi satu titik. 250 berarti diterima, dan QUIT menutup sesi dengan 221.

Digit pertama yang dibaca software. 2yz berarti sukses dan 3yz meminta input berikutnya. 4yz adalah kegagalan sementara, jadi permintaan yang sama boleh dicoba lagi nanti; 5yz permanen, dan client sebaiknya tidak mengulanginya.

Di port 587 sesi dimulai tanpa enkripsi, server mencantumkan STARTTLS di daftar extension-nya, lalu client meng-upgrade koneksi. Setelah handshake TLS, SMTP kembali ke awal: client mengirim EHLO lagi, dan daftar extension-nya bisa berbeda. Server submission Gmail menunjukkannya. Pada 2026-10-18, server itu mencantumkan STARTTLS tanpa AUTH sebelum upgrade, dan AUTH baru muncul setelahnya.

## Envelope sender vs header From: mana yang mana?

MAIL FROM menentukan envelope sender, yang juga disebut reverse-path. Laporan error dikirim ke sana, dan server yang melakukan pengiriman akhir menyalinnya ke baris Return-Path di bagian atas pesan. Header From ada di content: RFC 5322 mendefinisikannya sebagai penulis pesan, dan Reply-To sebagai alamat yang disarankan penulis untuk menerima balasan.

Keduanya sering sengaja dibuat berbeda. Secara default Resend memakai subdomain send dari domain Anda sebagai Return-Path, sedangkan From tetap alamat yang Anda pilih. Untuk situs ini subdomainnya send.noreply.matthewswong.com, yang record MX-nya mengarah ke host feedback di amazonses.com, sehingga bounce kembali ke penyedia.

## Bagaimana email menemukan server penerima, dan kenapa tidak dikirim sendiri?

Untuk mengantar ke sebuah alamat, server mencari record MX dari domain setelah tanda @. Tiap MX menyebut satu host dan satu angka preference, dan angka yang lebih kecil dicoba lebih dulu. Kalau domain tidak punya record MX sama sekali, domain itu sendiri dipakai sebagai implicit MX dengan preference 0. Pada 2026-10-18, gmail.com mencantumkan lima host MX, dengan preference dari 5 sampai 40.

Mengirim langsung dari server aplikasi berarti butuh port 25 keluar, dan banyak penyedia cloud memblokirnya. Google Compute Engine memblokir koneksi ke port tujuan 25 di luar VPC Anda dengan alasan risiko penyalahgunaan, tetapi membiarkan 587 dan 465 terbuka. Amazon EC2 secara default memblokir port 25 ke alamat publik dan membuka pembatasan itu bila diminta. Karena itu aplikasi menyerahkan email ke penyedia, lewat SMTP submission atau API HTTPS, dan server penyedia yang melakukan relay di port 25.

## Apa yang diperiksa SPF?

SPF memungkinkan sebuah domain menyatakan host mana yang boleh memakai domain itu di identitas MAIL FROM atau HELO. Record-nya berupa DNS TXT yang diawali v=spf1, dan server penerima menguji server yang terhubung terhadap record itu selama sesi SMTP. DMARC hanya memakai hasil MAIL FROM, jadi untuk DMARC, SPF menyangkut envelope, bukan header From.

Term-nya dibaca dari kiri ke kanan. include:amazonses.com menjalankan pemeriksaan yang sama terhadap record amazonses.com, dan pass di sana dihitung sebagai match di sini. Qualifier pada all di akhir berlaku untuk semua host lain: -all berarti fail, dan ~all berarti softfail, pernyataan lemah bahwa host itu kemungkinan tidak berwenang. send.noreply.matthewswong.com memasang v=spf1 include:amazonses.com ~all, nilai yang diminta panduan DNS Resend untuk subdomain send.

Ada dua batas yang sering menjebak. Sebuah domain harus punya tepat satu record v=spf1, karena dua record membuat hasilnya permerror. Lalu include, a, mx, ptr, exists, dan redirect masing-masing memakan satu DNS lookup, dengan batas 10 per evaluasi; lewat dari itu, hasilnya juga permerror.

## Bagaimana DKIM menandatangani pesan?

DKIM memungkinkan sebuah domain bertanggung jawab atas pesan lewat signature kriptografis di header DKIM-Signature. Tag d= menyebut domain penanda tangan dan s= menyebut selector, lalu server penerima mengambil public key dari record TXT di nama selector, lalu _domainkey, lalu domainnya. Header From wajib termasuk field yang ditandatangani, dan p= yang kosong di record key berarti key itu sudah dicabut.

Selector memungkinkan satu domain menyimpan beberapa key sekaligus. Key yang dipakai Resend untuk domain pengirim situs ini dipasang di resend._domainkey.noreply.matthewswong.com: record TXT berisi p= dan public key dalam base64. Relay umumnya tidak mengubah isi pesan secara berarti, jadi signature biasanya tetap utuh sepanjang perjalanan, termasuk saat melewati forwarder yang tidak tercantum di SPF.

## Apa yang ditambahkan DMARC di atas SPF dan DKIM?

SPF dan DKIM masing-masing menjamin sebuah domain, tetapi belum tentu domain yang dilihat pembaca. DMARC menutup celah itu: pesan dinyatakan pass hanya jika SPF atau DKIM lolos untuk domain yang selaras dengan domain di header From. Relaxed alignment, yang menjadi default, berarti keduanya punya Organizational Domain yang sama; strict berarti keduanya identik. Satu pass yang selaras sudah cukup.

Kebijakannya berupa record TXT di _dmarc milik domain From, diawali v=DMARC1. p=none berarti tidak menyatakan preferensi, quarantine menganggap email yang gagal mencurigakan, dan reject menyatakan kegagalan itu bukan pemakaian domain yang sah; sp= berlaku untuk subdomain. Pada 2026-10-18 yahoo.com memasang p=reject, dan gmail.com memasang p=none dengan sp=quarantine. Keputusan akhir tetap di tangan server penerima, sesuai kebijakan lokalnya.

DMARC kini adalah RFC 9989, terbit Mei 2026, yang menggantikan RFC 7489. Tag pct dihapus dan kini berstatus historic, jadi record yang masih membawa pct=100 memakai tag yang sudah usang. RFC ini juga mencari Organizational Domain lewat DNS tree walk, bukan public suffix list. Panduan pengirim Google meminta setiap pengirim memasang SPF atau DKIM, dan pengirim massal memasang keduanya plus DMARC, dengan From yang selaras.

## Konfigurasi nyata di balik pelajaran ini

`app/api/contact/route.ts:105-108`

```typescript
  const fromEmail =
    process.env.CONTACT_FROM_EMAIL ||
    "Matthews Wong <noreply@noreply.matthewswong.com>";
  const toEmail = process.env.CONTACT_TO_EMAIL || "matthewswong2610@gmail.com";
```

Pengirim default-nya alamat di noreply.matthewswong.com, subdomain pengirim yang record SPF dan DKIM-nya dibaca di bagian coba sendiri, dan environment variable bisa mengganti kedua alamat. Resend menyarankan mengirim dari subdomain, bukan root domain. Penerimanya inbox pemilik situs sendiri, jadi penyedia mengantar pesan ke MX domain itu.

`app/api/contact/route.ts:138-146`

```typescript
  const payload = {
    from: fromEmail,
    to: toEmail,
    replyTo: email,
    template: {
      id: isHiring ? TEMPLATE_HIRING : TEMPLATE_PROJECT,
      variables,
    },
  };
```

from tetap di domain pengirim milik situs, dan alamat pengunjung masuk ke replyTo, yang dikirim SDK sebagai reply_to dan menjadi header Reply-To. Menekan Reply langsung membalas ke pengunjung. Kalau pengunjung ditaruh di from, domain merekalah yang diperiksa DMARC, tidak ada yang ditandatangani situs ini yang bisa selaras dengannya, dan domain yang memasang p=reject meminta server penerima menolak pesannya.

## Yang sering rusak

- **Alamat pengunjung di From gagal DMARC di domain mereka.** Form yang mengirim dengan From milik pengunjung membuat domain merekalah yang diperiksa DMARC. Domain SPF dan DKIM Anda tidak bisa selaras dengannya, jadi domain seperti yahoo.com, yang memasang p=reject pada 2026-10-18, meminta server penerima menolak pesannya. Panduan Google juga melarang meniru header From Gmail, dan Resend menolak alamat from di domain yang belum Anda verifikasi. Kirim dari domain Anda sendiri dan taruh pengunjung di Reply-To.
- **Port 25 diblokir dari server cloud.** Aplikasi yang mengantar langsung ke host MX penerima butuh port 25 keluar, dan di banyak VM cloud koneksinya tidak pernah tersambung. Compute Engine memblokir port tujuan 25 di luar VPC, dan EC2 memblokirnya ke alamat publik sampai Anda meminta pembatasannya dibuka. Serahkan email ke penyedia lewat 587, 465, atau API HTTPS-nya.
- **Dua record SPF, atau lebih dari 10 lookup.** Menambah penyedia kedua dengan memasang record v=spf1 kedua justru merusak SPF untuk keduanya: lebih dari satu record membuat hasilnya permerror. Gabungkan menjadi satu record dengan dua include, dan hitung term yang memakan DNS lookup, karena setiap include ikut membawa lookup milik domain lain dan lebih dari 10 juga permerror.
- **Email yang di-forward gagal SPF.** Saat sebuah mailbox mem-forward pesan Anda, server forwarder yang terhubung ke MX berikutnya, dan record SPF Anda tidak mencantumkannya. Kecuali forwarder menulis ulang MAIL FROM ke domainnya sendiri, SPF tidak bisa pass. Signature DKIM atas isi yang tidak berubah tetap valid, karena itu menandatangani dengan DKIM tetap penting walaupun SPF sudah dipasang.
- **Login ditolak di 587 sebelum STARTTLS.** Client yang melewati STARTTLS di 587 bisa saja tidak pernah melihat AUTH: server submission Gmail hanya menawarkan AUTH setelah upgrade saat dicek pada 2026-10-18, dan RFC 3207 mengizinkan daftar extension berubah setelah TLS. Aktifkan STARTTLS untuk 587, atau pakai 465, yang memulai TLS sebelum perintah pertama.

### Tiga port SMTP, menurut definisi RFC 5321, RFC 6409, dan RFC 8314.

| Port | Dipakai untuk | TLS | Catatan |
| --- | --- | --- | --- |
| 25 | Relay antar server, ke MX penerima | STARTTLS bila ditawarkan; MX publik tidak boleh mewajibkannya | Sering diblokir keluar di VM cloud |
| 587 | Submission dari aplikasi atau mail client | STARTTLS, lalu EHLO lagi | Menolak MAIL sebelum AUTH, secara default |
| 465 | Submission dari aplikasi atau mail client | Implicit TLS sejak byte pertama | Lebih disarankan RFC 8314 daripada STARTTLS |

## Coba sendiri

Semua langkah di sini jalan di laptop dengan dig dan openssl, dan tidak ada yang mengirim email: langkah SMTP berhenti di EHLO dan Anda tidak pernah mengetik password. Sebagian jaringan memblokir 587 dan 465; kalau koneksi menggantung, coba jaringan lain.

1. Cari tahu ke mana gmail.com menerima email. Tiap baris berisi preference dan host; angka terkecil dicoba lebih dulu.

   ```bash
   dig @one.one.one.one MX gmail.com +short
   ```
2. Baca record SPF di domain bounce situs ini, subdomain send yang dipakai Resend sebagai Return-Path.

   ```bash
   dig @one.one.one.one TXT send.noreply.matthewswong.com +short
   ```
3. Ambil public key DKIM untuk selector resend. Nilai p= adalah key yang dipakai server penerima untuk memverifikasi signature.

   ```bash
   dig @one.one.one.one TXT resend._domainkey.noreply.matthewswong.com +short
   ```
4. Bandingkan record DMARC dua penyedia mailbox besar. Baca p=, sp=, dan rua=, dan perhatikan mana yang masih membawa tag pct yang sudah dipensiunkan.

   ```bash
   dig @one.one.one.one TXT _dmarc.yahoo.com +short
   dig @one.one.one.one TXT _dmarc.gmail.com +short
   ```
5. Buka sesi submission dengan STARTTLS. Saat output berhenti, ketik EHLO laptop.example dan cari AUTH di balasannya, lalu ketik QUIT. Jangan login.

   ```bash
   openssl s_client -starttls smtp -connect smtp.gmail.com:587 -crlf -quiet
   ```
6. Lakukan hal yang sama di 465. Di sana TLS langsung dimulai, jadi tidak ada flag -starttls, dan sapaan 220 datang lewat TLS.

   ```bash
   openssl s_client -connect smtp.gmail.com:465 -crlf -quiet
   ```
7. Buka header lengkap pesan yang Anda terima (di Gmail: More, lalu Show original) dan cari baris Authentication-Results: spf=, dkim=, dan dmarc=, masing-masing dengan domain yang diperiksanya.

## Kuis singkat

1. **Alamat mana yang diperiksa SPF saat hasilnya dipakai DMARC?**
   A. Alamat di header From
   B. Envelope sender yang diberikan di MAIL FROM
   C. Alamat di header Reply-To
   Jawaban: B. SPF memberi izin host untuk identitas MAIL FROM dan HELO, dan DMARC hanya memakai hasil MAIL FROM. Header From adalah yang kemudian dibandingkan DMARC dengannya.

2. **Form kontak mengirim dengan From berisi alamat yahoo.com milik pengunjung, lewat penyedia Anda sendiri. Apa hasil yang paling mungkin?**
   A. DMARC gagal, karena domain SPF dan DKIM Anda tidak selaras dengan yahoo.com, dan yahoo.com meminta reject
   B. Terkirim, karena SPF lolos untuk server penyedia Anda
   C. Terkirim, karena server penerima menulis ulang From ke domain Anda
   Jawaban: A. SPF yang lolos untuk domain envelope Anda tidak membuktikan apa pun soal yahoo.com. DMARC butuh pass untuk domain yang selaras dengan From, dan yahoo.com memasang p=reject pada 2026-10-18.

3. **Aplikasi Anda di VM cloud tidak bisa terhubung ke host MX penerima mana pun di port 25, padahal panggilan HTTPS berjalan. Apa penyebab yang paling mungkin?**
   A. Host MX penerima sedang mati
   B. Key DKIM Anda tidak ada di DNS
   C. Penyedia cloud memblokir port 25 keluar
   Jawaban: C. Compute Engine memblokir port tujuan 25 di luar VPC, dan EC2 memblokirnya ke alamat publik secara default. Key DKIM yang hilang membuat pemeriksaan gagal setelah terhubung, bukan koneksinya.

## Pikirkan dulu

- **Apa beda envelope sender dan header From?** Envelope sender adalah alamat MAIL FROM di sesi SMTP; laporan error dikirim ke sana, dan alamat itu disimpan sebagai Return-Path saat pesan diantar. Header From adalah bagian dari content dan menyebut penulisnya. SPF memeriksa yang pertama, DMARC melindungi yang kedua.
- **Sebuah DKIM-Signature membawa d=example.com dan s=mail. Di mana server penerima mencari public key-nya?** Di record TXT pada mail._domainkey.example.com: selector, lalu _domainkey, lalu domain penanda tangan.
- **Kenapa route kontak menaruh alamat pengunjung di replyTo, bukan di from?** From harus berada di domain yang dikirim dan ditandatangani situs, kalau tidak DMARC alignment gagal di domain pengunjung, dan penyedia pun menolak domain from yang belum diverifikasi. Reply-To tetap membuat balasan pemilik situs langsung sampai ke pengunjung.
- **Kapan sebuah pesan lolos DMARC?** Saat SPF atau DKIM lolos untuk domain yang selaras dengan domain From: Organizational Domain yang sama pada relaxed alignment, domain yang identik pada strict. Satu pass yang selaras sudah cukup.

## Pelajari lebih dalam

- [Otomasi Email ERP: Memicu Email Transaksional dari Event Bisnis](https://www.matthewswong.com/id/blog/erp-email-automation/)
- [Cara Mendesain Sistem Notifikasi Scalable (Push, Email, SMS)](https://www.matthewswong.com/id/blog/design-notification-system-architecture/)
- [HTTPS dan TLS Melampaui Certbot: Pengerasan Konfigurasi SSL](https://www.matthewswong.com/id/blog/https-tls-beyond-certbot/)

## Sumber

- [RFC 5321: Simple Mail Transfer Protocol](https://www.rfc-editor.org/rfc/rfc5321)
- [RFC 5322: Internet Message Format (From, Reply-To)](https://www.rfc-editor.org/rfc/rfc5322)
- [RFC 6409: Message Submission for Mail (port 587)](https://www.rfc-editor.org/rfc/rfc6409)
- [RFC 8314: TLS untuk submission dan akses email (port 465)](https://www.rfc-editor.org/rfc/rfc8314)
- [RFC 3207: extension SMTP untuk SMTP aman lewat TLS](https://www.rfc-editor.org/rfc/rfc3207)
- [RFC 7208: Sender Policy Framework (SPF)](https://www.rfc-editor.org/rfc/rfc7208)
- [RFC 6376: DomainKeys Identified Mail (DKIM) Signatures](https://www.rfc-editor.org/rfc/rfc6376)
- [RFC 9989: DMARC (menggantikan RFC 7489)](https://www.rfc-editor.org/rfc/rfc9989)
- [RFC 8601: header Authentication-Results](https://www.rfc-editor.org/rfc/rfc8601)
- [Google: panduan pengirim email](https://support.google.com/a/answer/81126)
- [Google Cloud: mengirim email dari instance (port 25)](https://docs.cloud.google.com/compute/docs/tutorials/sending-mail)
- [AWS: pembatasan email lewat port 25 di Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html)
- [Dokumentasi Resend: Custom Return Path (subdomain send)](https://resend.com/docs/dashboard/domains/custom-return-path)
- [Dokumentasi Resend: menambah domain (kirim dari subdomain)](https://resend.com/docs/add-a-domain)
- [Dokumentasi Resend: Send email (POST /emails, reply_to)](https://resend.com/docs/api-reference/emails/send-email)
- [Dokumentasi Resend: record MX, SPF, dan DKIM yang ditambahkan](https://resend.com/docs/knowledge-base/cloudflare)
- [Dokumentasi Resend: error 403 karena domain tidak cocok](https://resend.com/docs/knowledge-base/403-error-domain-mismatch)
- [Google Workspace: server SMTP Gmail di 465 dan 587](https://knowledge.workspace.google.com/admin/gmail/send-email-from-a-printer-scanner-or-app)
- [Bantuan Gmail: menelusuri email lewat header lengkap](https://support.google.com/mail/answer/29436)

---

- HTML version: https://www.matthewswong.com/id/learn/devops-from-zero/how-smtp-works-spf-dkim-dmarc/
- English: https://www.matthewswong.com/en/learn/devops-from-zero/how-smtp-works-spf-dkim-dmarc/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
