Bali, Indonesia
Insights

Mengira Dua Record SPF Saling Melengkapi, Padahal Hasilnya PermError

October 29, 2026
0:00
Ada asumsi yang cukup sering muncul saat domain mulai memakai layanan email kedua: record SPF lama dibiarkan saja, lalu ditambah satu record TXT baru untuk layanan yang baru. Kedengarannya logis, mirip menambah baris di daftar izin. Masalahnya, SPF tidak bekerja seperti itu. Begitu ada dua record TXT yang sama-sama diawali v=spf1, server penerima tidak memilih salah satu atau menggabungkannya. Konfigurasi SPF domain itu justru dianggap rusak, dan hasilnya PermError. Dampaknya biasanya baru terasa belakangan. Email dari layanan lama yang tadinya lolos ikut gagal verifikasi, newsletter mulai masuk spam, dan kalau domain punya kebijakan DMARC yang ketat, sebagian email bisa ditolak. Di meja support, kasus seperti ini sering datang dengan keluhan "padahal SPF sudah ditambahkan". Memang betul sudah ditambahkan, cuma jumlah record-nya kelebihan satu.
SPF (Sender Policy Framework) adalah daftar yang dipublikasikan lewat DNS. Isinya server mana saja yang boleh mengirim email atas nama sebuah domain. Saat email masuk, server penerima melihat domain di envelope sender, yaitu alamat MAIL FROM di sesi SMTP yang biasanya tampil sebagai Return-Path di header. Setelah itu penerima mengambil record TXT milik domain tersebut. Spesifikasi SPF (RFC 7208) mengatur langkah ini dengan cukup kaku. Dari semua record TXT di nama domain itu, penerima hanya mengambil yang diawali v=spf1. Record TXT lain, misalnya token verifikasi dari layanan pihak ketiga, diabaikan dan tidak mengganggu. Kalau tidak ada record SPF sama sekali, hasilnya None. Kalau ada tepat satu, record itu dievaluasi. Kalau lebih dari satu, hasilnya langsung PermError, dan tidak ada satu pun mekanisme yang sempat dievaluasi. Aturan ini masuk akal kalau dilihat dari sisi penerima. DNS tidak menjamin urutan record TXT yang dikembalikan. Kalau penerima boleh memilih salah satu, hasil verifikasi bisa berubah-ubah tergantung record mana yang kebetulan datang duluan. Menggabungkan otomatis juga tidak aman, karena dua record bisa punya kebijakan akhir yang bertentangan, misalnya satu diakhiri -all dan satunya ~all. Daripada menebak maksud pemilik domain, spesifikasinya memilih menyatakan konfigurasi itu salah. PermError (permanent error) artinya kesalahan ada di record milik domain dan tidak akan hilang walau dicoba ulang. Ini berbeda dengan TempError, yang biasanya muncul karena query DNS timeout. Cara penerima memperlakukan PermError tidak seragam: ada yang menganggapnya setara gagal, ada juga yang hanya menaikkan skor spam. Yang pasti, bagi DMARC, PermError bukan pass. Email hanya bisa lolos DMARC kalau tanda tangan DKIM-nya valid dan selaras dengan domain di header From. Hal itu juga yang membuat masalah ini kadang tidak langsung terlihat. Kalau layanan email sudah menandatangani DKIM dengan benar, emailnya masih bisa lolos DMARC walau SPF rusak. Biasanya yang kena duluan adalah email dari sumber yang belum memasang DKIM, misalnya form kontak di server hosting.
Langkah tercepat adalah melihat semua record TXT di domain. Ganti example.com dengan domain yang dicek. Kalau envelope sender memakai subdomain (misalnya layanan newsletter memakai bounce.example.com), cek juga nama itu, karena SPF dievaluasi per nama domain, bukan per domain induk.
BASH
dig +short TXT example.com
dig +short TXT example.com @1.1.1.1
Perintah kedua bertanya langsung ke resolver publik. Gunanya untuk membandingkan dengan resolver lokal yang mungkin masih menyimpan cache. Hasilnya bisa berupa beberapa baris, dan yang perlu dihitung hanya baris yang diawali v=spf1. Contoh format output untuk domain yang bermasalah:
TEXT
"token-verifikasi=abc123"
"v=spf1 +a +mx include:_spf.layanan-lama.example ~all"
"v=spf1 include:spf.layanan-baru.example ~all"
Ada dua baris v=spf1, jadi hasilnya sudah pasti PermError. Tidak perlu alat lain untuk memastikannya. Konfirmasi dari sisi penerima ada di header email. Kirim email uji ke kotak masuk yang bisa menampilkan header aslinya. Di kebanyakan webmail, ada opsi untuk melihat sumber atau pesan asli, tapi nama menunya berbeda-beda. Setelah itu cari header Authentication-Results. Header ini ditambahkan oleh server penerima dan memuat hasil SPF, DKIM, dan DMARC. Untuk kasus ini, isinya kurang lebih berbentuk spf=permerror smtp.mailfrom=example.com. Teks penjelas di dalam kurung berbeda-beda di tiap penyedia, jadi patokannya adalah kata permerror, bukan kalimat penjelasnya. Perhatikan juga nilai smtp.mailfrom, karena itulah domain yang benar-benar dicek SPF-nya. Kadang yang bermasalah ternyata subdomain bounce yang dipakai layanan pihak ketiga, bukan domain utama yang sejak awal sibuk diperiksa.
Prinsip perbaikannya sederhana: satu nama domain, satu record v=spf1. Semua sumber pengirim dimasukkan ke dalam record itu, dengan satu kebijakan all di bagian paling akhir. Ambil nilai include atau IP dari dokumentasi resmi masing-masing layanan email, jangan menyalin dari record domain lain.
TEXT
Sebelum (dua record, PermError):
v=spf1 +a +mx include:_spf.layanan-lama.example ~all
v=spf1 include:spf.layanan-baru.example ~all

Sesudah (satu record):
v=spf1 a mx include:_spf.layanan-lama.example include:spf.layanan-baru.example ~all
Tanda + di depan mekanisme boleh dihapus karena itu memang qualifier default. Mekanisme all cukup satu dan harus berada di akhir, karena apa pun yang ditulis setelah all tidak akan pernah dievaluasi. Soal memilih ~all (softfail) atau -all (fail), itu trade-off. -all lebih tegas, tapi kalau ada pengirim sah yang terlupa, emailnya ikut gagal. Aturan praktis yang umum dipakai: mulai dari ~all sampai yakin daftar pengirimnya lengkap, apalagi kalau DMARC sudah dipakai sebagai lapisan kebijakan. Cek juga apakah mekanisme a dan mx masih dibutuhkan. Kalau email domain sudah sepenuhnya pindah ke layanan pihak ketiga dan server hosting tidak lagi mengirim email, termasuk dari form kontak atau notifikasi WordPress, keduanya bisa dihapus. Kalau ragu, biarkan dulu. Menghapus pengirim yang ternyata masih aktif hanya memindahkan masalahnya ke tempat lain. Saat menyimpan, ubah isi record lama lalu hapus record yang satunya. Jangan sampai malah menambah record ketiga. Di beberapa panel DNS, tombol edit dan tambah letaknya berdekatan, jadi setelah menyimpan, jalankan dig lagi dan pastikan hanya tersisa satu baris v=spf1. Untuk record yang panjang, ada satu hal yang sering disalahpahami. Satu string TXT dibatasi 255 karakter. Record yang lebih panjang dipecah menjadi beberapa string di dalam satu record, dan penerima menyambungnya tanpa menambah spasi. Itu tetap dihitung satu record dan sah. Yang memicu PermError adalah dua record terpisah, bukan satu record yang terbagi jadi beberapa string. Kalau memecah secara manual, perhatikan spasi di batas potongan supaya mekanismenya tidak menempel.
Setelah record digabung, jebakan berikutnya adalah batas lookup. RFC 7208 membatasi evaluasi SPF maksimal 10 mekanisme atau modifier yang membutuhkan query DNS, yaitu include, a, mx, ptr, exists, dan redirect. Mekanisme ip4, ip6, dan all tidak dihitung. Lookup di dalam include juga ikut dihitung, jadi satu include milik layanan besar bisa memakan beberapa lookup sekaligus karena di dalamnya ada include lagi. Kalau lewat dari 10, hasilnya juga PermError. Pola ini sering muncul saat domain memakai banyak layanan sekaligus: email kantor, newsletter, CRM, helpdesk, dan masing-masing meminta satu include. Setiap include sudah benar, tapi totalnya melewati batas. Kamu bisa menghitungnya manual dengan menjalankan dig +short TXT pada setiap domain include, lalu turun lagi ke include di dalamnya. Pengecek SPF online juga bisa menghitung otomatis, tapi hasilnya tetap sebaiknya dicek silang. Kalau sudah lewat batas, ada beberapa opsi. Yang paling aman adalah membuang layanan yang sudah tidak dipakai. Kalau IP server pengirim tetap, a atau mx bisa diganti dengan ip4. Pengirim tertentu, misalnya newsletter, juga bisa dipindah ke subdomain sendiri yang punya SPF terpisah. Opsi terakhir adalah flattening, yaitu mengganti include dengan daftar IP langsung. Kelemahannya, kalau penyedia mengubah IP, record kamu tidak ikut berubah dan email mulai gagal tanpa peringatan. Karena itu flattening biasanya disimpan sebagai pilihan terakhir.
Perubahan DNS tidak langsung terlihat oleh semua penerima. Resolver yang sudah menyimpan record lama akan terus memakainya sampai TTL habis, jadi beri waktu sebelum menyimpulkan perbaikannya gagal. Untuk memastikan sumbernya sudah benar, query langsung ke nameserver otoritatif domain dengan menambahkan @ diikuti nama nameserver-nya pada perintah dig. Pastikan juga kamu mengedit zona DNS yang benar-benar aktif. Sering kali hosting punya zona sendiri, sementara domain sebenarnya memakai nameserver di tempat lain, sehingga editan di zona hosting tidak berpengaruh apa-apa. Kalau masih bingung bedanya, penjelasannya ada di artikel Ganti Nameserver atau Cukup Ubah A Record Saat Pindah Hosting?. Di hosting yang memakai cPanel atau panel lain, cek apakah ada fitur yang mengelola SPF secara otomatis. Sebagian panel punya alat deliverability yang bisa menyarankan atau menulis record SPF sendiri. Kalau fitur itu dijalankan setelah record digabung manual, periksa lagi zona DNS-nya dan pastikan tidak muncul record kedua. Perilaku persisnya tergantung versi dan konfigurasi panel, jadi cek langsung, jangan berasumsi. Terakhir, kirim email uji dari setiap layanan pengirim, bukan hanya dari satu layanan, lalu cek Authentication-Results sampai hasilnya spf=pass. Kalau laporan agregat DMARC sudah aktif, laporan beberapa hari berikutnya bisa membantu menemukan sumber pengirim yang terlewat. Setiap kali menambah layanan email baru, anggap langkahnya sebagai mengedit record SPF yang sudah ada, bukan menambah record baru. Satu baris v=spf1, semua pengirim ada di dalamnya, satu all di akhir, dan total lookup tetap di bawah 10. Jalankan dig +short TXT sebelum dan sesudah perubahan. Kebiasaan kecil ini cukup untuk mencegah sebagian besar kasus SPF PermError sebelum ada email yang gagal terkirim.