D
P
0

WordPress & PHP

`wp_mail()` Diam-Diam Gagal Kirim, Nol Email Sampai? Managed Host Matikan `mail()` PHP

13 Juli 2026·4 menit baca
`wp_mail()` Diam-Diam Gagal Kirim, Nol Email Sampai? Managed Host Matikan `mail()` PHP

Sebuah situs WordPress yang saya pegang punya form kontak sederhana: pengunjung isi nama, email, pesan, klik kirim, dan handler-nya memanggil wp_mail() untuk mengirim notifikasi ke inbox klien. Di lokal jalan. Di staging jalan. Lalu di produksi, selama beberapa hari, tidak ada satu pun lead yang masuk. Bukan sedikit yang masuk, tapi nol. Form-nya tampak sukses di mata pengunjung, halaman terima kasih muncul, tapi email-nya tidak pernah datang. Lead-lead itu menguap.

Yang bikin ini menyebalkan: tidak ada error sama sekali. Tidak ada PHP fatal, tidak ada notice, tidak ada pesan merah di layar. error_log bersih. Form mengembalikan status sukses ke browser. Dari luar, semuanya terlihat sehat. Satu-satunya bukti bahwa ada yang salah adalah inbox klien yang kosong, dan itu baru ketahuan setelah dia bertanya kenapa tidak ada calon klien yang menghubunginya lewat web.

Gejalanya

Saya mulai dari yang paling gampang diperiksa. Saya kirim tes lewat form sendiri: halaman sukses muncul, email tidak datang. Saya cek folder spam, kosong. Saya cek error_log sekali lagi, benar-benar bersih. Karena wp_mail() mengembalikan boolean, saya tambahkan logging di sekitar pemanggilannya untuk melihat apa yang dia bilang:

$sent = wp_mail( $to, $subject, $body, $headers );
error_log( '[contact] wp_mail returned: ' . var_export( $sent, true ) );

Hasilnya bikin saya bingung sebentar: wp_mail returned: false. Jadi WordPress sendiri tahu pengiriman gagal, tapi dia gagal secara diam, tanpa melempar apa pun ke atas. Return false itu satu-satunya sinyal, dan tidak ada yang menangkapnya. Itulah kenapa form terasa sukses padahal tidak ada email yang keluar.

Menelusuri akar masalah

Return false dari wp_mail() artinya PHPMailer di baliknya gagal menyerahkan pesan ke transport apa pun. Secara default, wp_mail() memakai fungsi mail() native PHP, yang di banyak server memanggil binary sendmail lokal. Jadi pertanyaannya menyempit: apakah mail() di server ini benar-benar bisa mengirim?

Saya bikin skrip probe kecil untuk menguji langsung, melewati seluruh lapisan WordPress:

<?php
$ok = mail( 'test@example.com', 'probe', 'body' );
var_dump( $ok );

Balik bool(false). Di sinilah teka-tekinya terurai. Situs ini di-hosting di sebuah managed host, dan managed host seperti Kinsta memang secara sengaja mematikan fungsi mail() PHP di level server. Alasannya masuk akal dari sisi mereka: mail() yang tidak terautentikasi adalah magnet spam dan sumber masalah deliverability, jadi mereka mewajibkan pengiriman lewat SMTP terautentikasi. Konsekuensinya, transport default wp_mail(), yang mengandalkan sendmail, tidak punya apa-apa untuk diserahi pesan. PHPMailer mencoba, tidak ada tujuan, dan gagal, tanpa mengeluarkan error yang ramah karena dari sisi WordPress ini "cuma" return false.

Jadi ini bukan bug di kode saya. Kode saya benar untuk lingkungan yang punya mail(). Masalahnya adalah asumsi yang saya bawa: bahwa wp_mail() selalu punya transport yang berfungsi. Di managed host, asumsi itu salah.

Perbaikannya

Ada dua hal yang saya perbaiki, dan urutannya penting. Pelajaran terbesar bukan soal SMTP, tapi soal jangan pernah menjadikan email sebagai satu-satunya penyimpanan lead.

Perbaikan pertama, yang paling penting: buat penerimaan lead tidak bergantung pada email sama sekali. Saya ubah handler agar menyimpan setiap submission ke database sebagai custom post type sendiri, memakai wp_insert_post(), sebagai sumber kebenaran yang tahan lama. Kalau email gagal, lead-nya tetap tersimpan aman di database:

$inquiry_id = wp_insert_post( array(
    'post_type'   => 'inquiry',
    'post_status' => 'private',
    'post_title'  => sanitize_text_field( $name ) . ' - ' . current_time( 'Y-m-d H:i' ),
    'meta_input'  => array(
        'email'   => sanitize_email( $email ),
        'message' => sanitize_textarea_field( $message ),
    ),
) );

Perbaikan kedua: pasang transport SMTP yang benar sebagai notifikasi di atas penyimpanan itu, bukan menggantikannya. Cara paling cepat dan andal adalah plugin WP Mail SMTP dengan akun yang terautentikasi. Saya pakai Gmail dengan App Password khusus, bukan password akun asli. Begitu SMTP terpasang, wp_mail() punya transport yang sah dan mulai mengirim lagi, tapi sekarang pengiriman itu cuma lapisan bonus, bukan penopang tunggal:

// wp_insert_post() sudah menyimpan lead-nya. Email hanya notifikasi.
$notified = wp_mail( $to, $subject, $body, $headers );
if ( ! $notified ) {
    error_log( '[contact] notifikasi gagal, tapi inquiry #' . $inquiry_id . ' aman di DB' );
}

Dengan pola ini, walau SMTP suatu saat bermasalah lagi, tidak ada lead yang hilang. Klien bisa buka daftar inquiry di dashboard admin kapan saja, dan email cuma mempercepat dia tahu ada yang masuk.

Checklist

  • Kalau wp_mail() return false tanpa error, curigai transport-nya, bukan kode form kamu.
  • Uji mail() langsung dengan skrip probe kecil; kalau balik false, host kemungkinan memblokirnya.
  • Ingat managed host seperti Kinsta mematikan mail() PHP dan mewajibkan SMTP terautentikasi.
  • Pasang SMTP lewat WP Mail SMTP dengan akun terautentikasi (mis. Gmail App Password), bukan password akun asli.
  • Simpan setiap submission ke database via wp_insert_post() sebagai sumber kebenaran, lalu jadikan email notifikasi di atasnya.
  • Jangan pernah menjadikan email satu-satunya penyimpanan lead. Penyimpanan ganda berarti lead tidak akan menguap meski email gagal.