Siteden otomatik mailler gitmiyor şikâyeti, bir sunucu yöneticisinin masasına gelen en sinsi arızadır. Site açılıyor, form gönderiliyor, ekranda yeşil "Mesajınız iletildi" yazısı beliriyor; ama iletişim formu maili gelmiyor, sipariş maili gitmiyor, şifre sıfırlama maili gelmiyor. Hiçbir yerde kırmızı bir hata yok. Genelde bu durum haftalar sonra, "Ben size üç kere yazdım, neden dönmediniz?" diyen bir müşteriyle ortaya çıkıyor ve o ana kadar kaç fırsatın kaybedildiği asla tam olarak bilinemiyor.
Bu yazıda sorunu tahminle değil kanıtla çözeceğiz. Önce mailin sunucudan çıkıp çıkmadığını loglardan göreceğiz, sonra Türkçe kaynakların neredeyse hiç değinmediği asıl nedeni açacağız: PHP'nin mail() fonksiyonuyla gönderilen mesajın zarf gönderici adresi alan adınızla eşleşmediği için SPF kontrolünden geçemez, formdaki "From" alanına ziyaretçinin adresini yazmak da DMARC hizalamasını kırar. İkisi bir araya geldiğinde Gmail ve Outlook mesajı ya sessizce çöpe atar ya da spam'e düşürür. Sonunda kalıcı çözümü — kimlik doğrulamalı SMTP — hem WordPress hem düz PHP tarafında adım adım kuracağız.
Mail Aslında Nereye Gidiyor#
Bir web formu "gönderildi" dediğinde bu, mailin alıcıya ulaştığı anlamına gelmez; yalnızca PHP'nin mesajı sunucudaki yerel posta kuyruğuna teslim ettiği anlamına gelir. Zincir şöyle işler:
- PHP kodu
mail()veya bir kütüphane çağırır. mail(),php.iniiçindekisendmail_pathdeğerini çalıştırır. Paylaşımlı hostingde bu genelde/usr/sbin/sendmail -t -işeklindedir ve arkasında Exim ya da Postfix vardır.- MTA mesajı kuyruğa alır, alıcı alan adının MX kaydına bakar, uzak sunucuya bağlanır.
- Uzak sunucu mesajı kabul eder, reddeder veya kabul edip spam klasörüne koyar.
Formun yeşil kutusu yalnızca 1. ve 2. adımın başarılı olduğunu söyler. Arıza neredeyse her zaman 3. ve 4. adımdadır. Bu yüzden "eklenti çalışmıyor" varsayımıyla eklenti değiştirmek zaman kaybıdır; önce mesajın hangi adımda öldüğünü tespit etmek gerekir.
Önce Kanıt Toplayın: Sunucu Loglarını Okumak#
Tahmin etmeyin, loga bakın. Paylaşımlı hostingde cPanel açıksa Email → Track Delivery ekranı bu işin en hızlı yoludur: alıcı adresini yazıp aratın, her satırda Delivered, Deferred veya Failed göreceksiniz. Failed satırının detayında uzak sunucunun döndürdüğü gerçek metin yazar ve o metin çözümün yarısıdır.
Kök erişiminiz varsa doğrudan MTA logu daha ayrıntılıdır:
# Exim (cPanel sunucularının çoğu)
tail -f /var/log/exim_mainlog | grep -i '[email protected]'
# Postfix (kendi kurduğunuz Ubuntu/Debian sunucular)
tail -f /var/log/mail.log | grep -i '[email protected]'
# systemd tabanlı sistemlerde dosya yoksa
journalctl -u postfix -f
Üç tipik çıktı ve anlamları:
2026-08-11 10:14:02 1rXk2-000abc-9T <= [email protected] U=nobody P=local S=1204
2026-08-11 10:14:03 1rXk2-000abc-9T ** [email protected] R=dnslookup T=remote_smtp:
SMTP error from remote mail server after end of data:
550-5.7.26 Unauthenticated email from ornek.com is not accepted due to
550-5.7.26 domain's DMARC policy.
Buradaki <= satırı mesajın kuyruğa girdiğini, ** satırı ise kalıcı reddi gösterir. Ve dikkat: zarf göndericisi [email protected]. Bu tek satır, yazının geri kalanının sebebidir.
Eğer log dosyasına hiç satır düşmüyorsa mesaj MTA'ya hiç ulaşmamıştır; o zaman sorun PHP tarafındadır ve PHP hata kayıtlarına bakmalısınız. cPanel kullanıyorsanız Metrics bölümündeki hata kayıtları ekranı ile ~/logs/ altındaki dosyalar bu bilgiyi verir.
Sorunun Birinci Kaynağı: PHP mail() ve Zarf Gönderici Adresi#
Her e-posta mesajının iki ayrı "gönderen" bilgisi vardır ve bunları karıştırmak bu arızanın kalbidir:
| Alan | Nerede taşınır | Kim görür | Ne işe yarar |
|---|---|---|---|
| Zarf gönderici (Return-Path / MAIL FROM) | SMTP oturumunda, mesaj gövdesinden önce | Kullanıcı görmez, sunucular görür | SPF kontrolü bu adrese bakar, bounce buraya döner |
| Başlık göndericisi (From:) | Mesaj başlıklarında | Kullanıcı bunu görür | DMARC hizalaması bu adrese bakar |
PHP mail() çağrıldığında zarf göndericiyi siz belirtmezseniz sunucu onu, işlemi çalıştıran sistem kullanıcısından türetir: [email protected], www-data@vps-2481 gibi. Alıcı sunucu SPF kontrolü yaparken sizin ornek.com alan adınızın SPF kaydına değil, o rastgele sunucu adının kaydına bakar. Böyle bir kayıt genelde yoktur; SPF sonucu none ya da permerror çıkar. DMARC ise SPF'in geçmesini ve aynı alan adıyla hizalı olmasını ister. srv12.hosting.local, ornek.com ile hizalı değildir. Sonuç: SPF hizalaması başarısız.
Bunu şu komutla kendi sunucunuzda görebilirsiniz:
php -r 'mail("[email protected]","Zarf testi","govde");'
grep -i "$(date +%Y-%m-%d)" /var/log/exim_mainlog | tail -5
Zarf göndericiyi düzeltmenin klasik yolu beşinci parametredir:
<?php
mail(
'[email protected]',
'Yeni form kaydı',
$govde,
"From: Site Formu <[email protected]>\r\nReply-To: {$ziyaretciMail}\r\n",
'-f [email protected]' // zarf göndericiyi ayarlar
);
Bu düzeltme SPF hizalamasını kurtarır ama işin yalnızca yarısıdır ve paylaşımlı hostinglerin bir kısmında -f parametresi güvenlik nedeniyle yok sayılır. Kalıcı çözüm değildir.
Sorunun İkinci Kaynağı: From Adresine Müşterinin Adresini Yazmak#
Bu, Türkçe kaynaklarda neredeyse hiç uyarılmayan ve en çok can yakan hatadır. Form eklentilerinin varsayılan davranışı şudur: ziyaretçi formu doldurur, eklenti mesajı gönderirken From: alanına ziyaretçinin adresini yazar ki siz "Yanıtla" dediğinizde doğrudan ona dönesiniz. Mantıklı görünür, felakettir.
Çünkü o mail sizin sunucunuzdan çıkar ama üzerinde From: [email protected] yazar. Gmail kendi alan adı adına, kendi sunucusu olmayan bir makineden gönderilmiş bir mesaj görür. Gmail'in DMARC politikası katıdır. Mesaj ya doğrudan reddedilir ya da spam'e gider. Bu, sizin alan adınızın itibarını da yavaş yavaş aşındırır. Aynı sorun @hotmail.com, @yahoo.com ve DMARC politikası olan her kurumsal alan adı için geçerlidir.
Doğru desen tektir ve istisnası yoktur:
From: Site Formu <[email protected]> ← her zaman SİZİN alan adınız
Reply-To: Ahmet Yılmaz <[email protected]> ← ziyaretçinin adresi buraya
Return-Path: [email protected] ← zarf göndericisi de sizin
Böylece "Yanıtla" düğmesi yine müşteriye gider, ama kimlik doğrulama zinciri kırılmaz. Kullandığınız form eklentisinde bu ayar genelde "Gönderen E-posta" ya da "From Email" alanıdır; oraya ziyaretçinin alanını dinamik olarak basan bir kısayol ([your-email] gibi) yazılıysa çıkarın, kendi adresinizi yazın ve ziyaretçinin adresini yalnızca "Reply-To" alanına koyun.
DMARC'ın ne kontrol ettiğini ve hizalamanın nasıl çalıştığını SPF, DKIM ve DMARC yazısında ayrıntılı anlatıyoruz; buradaki iki hata da doğrudan o üç kaydın mantığından doğuyor.
Kalıcı Çözüm: Kimlik Doğrulamalı SMTP#
Kalıcı çözüm, mail() fonksiyonunu tamamen bırakıp mesajı kimlik doğrulamalı bir SMTP oturumu üzerinden göndermektir. Fark şudur: mail() mesajı yerel kuyruğa "kim olduğunu söylemeden" bırakır; SMTP ise sunucuya kullanıcı adı ve parolayla bağlanır, sunucu da mesajı o hesabın kimliğiyle imzalayarak gönderir. Zarf göndericisi hesabın kendisi olur, DKIM imzası otomatik eklenir, SPF hizalanır.
Yapılacaklar sırayla:
- Hosting panelinde gerçek bir e-posta hesabı açın:
[email protected]veya[email protected]. Bunu "no-reply" yapmayın; gerçek bir kutu olsun ki bounce mesajlarını görebilesiniz. - Bu hesaba güçlü, sadece bu iş için kullanılan bir parola verin.
- Gönderim ayarlarını şu şekilde yapılandırın:
| Ayar | Değer | Not |
|---|---|---|
| SMTP sunucusu | mail.ornek.com veya sunucu ana adı | Panelde yazan tam adı kullanın |
| Port | 587 | STARTTLS ile şifreleme |
| Alternatif port | 465 | Doğrudan SSL/TLS |
| Şifreleme | STARTTLS (587) / SSL (465) | 25 numaralı portu kullanmayın |
| Kimlik doğrulama | Açık | Kullanıcı adı tam e-posta adresi |
| Kullanıcı adı | [email protected] | Sadece form yazmak çoğu sunucuda çalışmaz |
Hangi portun hangi durumda kullanılacağı ve 25 numaralı portun neden kapalı olduğu konusunda mail portları hangisi kullanılır yazısına bakabilirsiniz.
- Alan adınızın DNS bölgesinde SPF, DKIM ve DMARC kayıtlarının var olduğunu doğrulayın.
- Test gönderimi yapın ve başlıkları okuyun (aşağıda anlatıyoruz).
Sitesi ve maili aynı paylaşımlı sunucuda duran küçük işletmelerde bu kadarı yeterlidir. Günde binlerce sipariş bildirimi, bülten ya da kampanya maili gönderiyorsanız gönderimi web sunucusundan ayırmak gerekir; o senaryoda ayrı bir gönderim sunucusu ve ayrı IP itibarı devreye girer.
WordPress ve WooCommerce Tarafında Yapılandırma#
WordPress'in wp_mail() fonksiyonu varsayılan olarak PHP mail() kullanır — yani yukarıdaki iki hatanın ikisini de miras alır. WooCommerce sipariş onayı, stok uyarısı, şifre sıfırlama ve müşteri hesap bildirimleri de aynı fonksiyondan geçer. Bu yüzden "sipariş maili gitmiyor" şikâyetlerinin büyük bölümü WooCommerce'in değil, WordPress'in taşıma katmanının sorunudur.
Bir SMTP eklentisi kurup şu alanları doldurun: sunucu adı, port 587, şifreleme STARTTLS, kimlik doğrulama açık, kullanıcı adı tam e-posta adresi, "From" adresi de aynı hesap. Eklenti kurulumunun ayrıntılı adımları için WordPress SMTP e-posta ayarları yazısına bakın.
Eklenti kullanmak istemiyorsanız aynı işi wp-config.php ve küçük bir mu-plugin ile de yapabilirsiniz:
<?php
// wp-content/mu-plugins/smtp.php
add_action('phpmailer_init', function ($mail) {
$mail->isSMTP();
$mail->Host = 'mail.ornek.com';
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Username = '[email protected]';
$mail->Password = defined('SMTP_PASS') ? SMTP_PASS : '';
$mail->setFrom('[email protected]', 'Örnek Mağaza');
$mail->Sender = '[email protected]'; // zarf göndericisi
});
Parolayı koda gömmeyin; wp-config.php içinde define('SMTP_PASS', '...'); şeklinde tanımlayın ve o dosyanın izinlerini sıkın.
WooCommerce'te ayrıca WooCommerce → Ayarlar → E-postalar ekranındaki "Gönderen adresi" alanını da kendi alan adınıza çekin. Eklenti düzeyinde SMTP kurup burayı Gmail adresinde bırakmak, aynı DMARC sorununu geri getirir.
Kendi Yazdığınız PHP Kodunda SMTP Kullanmak#
Özel yazılmış bir iletişim formu ya da sipariş sisteminiz varsa mail() çağrısını PHPMailer gibi bir kütüphaneyle değiştirin. Kritik satırlar setFrom, addReplyTo ve Sender'dır:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'vendor/autoload.php';
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = 'mail.ornek.com';
$mail->SMTPAuth = true;
$mail->Username = '[email protected]';
$mail->Password = getenv('SMTP_PASS');
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->CharSet = 'UTF-8'; // Türkçe karakterler için şart
$mail->setFrom('[email protected]', 'Örnek Mağaza');
$mail->addAddress('[email protected]', 'Satış Ekibi');
$mail->addReplyTo($_POST['email'], $_POST['ad']); // ziyaretçi buraya
$mail->Subject = 'Yeni iletişim formu kaydı';
$mail->Body = $govde;
$mail->send();
} catch (Exception $e) {
error_log('Form maili gönderilemedi: ' . $mail->ErrorInfo);
}
CharSet satırını atlamayın: Türkçe karakterli konu başlıkları bozuk gelen sitelerin çoğunda tek eksik budur. error_log satırı da önemlidir — kullanıcıya "gönderildi" demeden önce dönüş değerini kontrol edin, aksi halde yine sessiz arızaya dönersiniz.
Kod düzeyine hiç girmeden bağlantıyı sınamak isterseniz SMTP test aracımız port ve TLS uyumunu kontrol edip kopyalayıp terminalde çalıştırabileceğiniz komutları üretir.
Gönderim Sonrası Doğrulama ve Test#
Ayarları yaptıktan sonra "bana mail geldi" demek yeterli kanıt değildir; kendi sunucunuza gelen mail her zaman gelir. Gerçek testi dış bir sağlayıcıya yapın ve başlıkları okuyun. Gmail'de mesajı açıp üç nokta menüsünden "Orijinali göster" deyin. Görmek istediğiniz üç satır şudur:
SPF: PASS with IP 185.x.x.x (ornek.com alan adı için)
DKIM: PASS with domain ornek.com
DMARC: PASS
Üçünde de ornek.com yazması gerekir. srv12.hosting.local veya sunucu adı görüyorsanız zarf göndericisi hâlâ düzelmemiş demektir. DKIM FAIL dönüyorsa imza ile DNS'teki genel anahtar uyuşmuyordur; DKIM doğrulaması başarısız yazısı bu durumun nedenlerini tek tek ele alıyor.
Komut satırından hızlı bir kimlik doğrulama denemesi:
openssl s_client -starttls smtp -crlf -connect mail.ornek.com:587
# bağlantı kurulduktan sonra:
EHLO ornek.com
AUTH LOGIN
# kullanıcı adı ve parola base64 olarak istenecektir
535 Incorrect authentication data yanıtı parola ya da kullanıcı adının yanlış olduğunu söyler — en sık sebep kullanıcı adına tam e-posta adresi yerine sadece hesap adının yazılmasıdır. Diğer yanıt kodlarının anlamı için SMTP hata kodları listesine bakabilirsiniz.
Son olarak gerçek bir sipariş/form akışını uçtan uca deneyin: farklı sağlayıcılarda üç adrese (bir Gmail, bir Outlook, bir kurumsal alan adı) test gönderin. Üçünde de gelen kutusuna düşüyorsa iş bitmiştir. Spam'e düşüyorsa sorun artık kimlik doğrulama değil itibar konusudur ve maillerin spam'e düşmesi yazısındaki adımlar devreye girer.
Belirti–Neden Tablosu#
Sahada karşılaştığımız durumların büyük bölümü şu beş satıra sığıyor:
| Belirti | Log/başlıkta görülen | Asıl neden | Çözüm |
|---|---|---|---|
| Hiçbir mail gitmiyor, logda kayıt yok | Log boş | PHP mail() devre dışı veya kod hataya düşüyor | PHP hata kaydını aç, SMTP'ye geç |
| Sadece Gmail/Outlook'a gitmiyor | 550-5.7.26 ... DMARC policy | From: alanında ziyaretçinin adresi var | From kendi alan adınız, ziyaretçi Reply-To |
| Mail gidiyor ama spam'de | SPF none, Return-Path sunucu adı | Zarf göndericisi alan adıyla eşleşmiyor | Kimlik doğrulamalı SMTP |
| Kendi kutuma geliyor, dışarı gitmiyor | Connection refused port 25 | Sağlayıcı giden 25 portunu kapatmış | 587/465 üzerinden SMTP |
| Konu başlığı bozuk geliyor | =?ISO-8859-9? | Karakter seti tanımsız | CharSet = UTF-8 |
Bu tabloda kendi durumunuzu bulamıyorsanız sorun büyük ihtimalle sitenin genelindedir; site tamamen yanıt vermiyorsa site açılmıyor ne yapmalı yazısındaki teşhis sırası daha doğru bir başlangıç olur.
Sıkça Sorulan Sorular#
Formda mesaj gönderildi yazıyor ama mail gelmiyor, bu nasıl olur#
Formun "gönderildi" mesajı, PHP'nin mesajı sunucudaki yerel posta kuyruğuna teslim ettiğini gösterir; alıcıya ulaştığını göstermez. Zincirin geri kalanı — MX araması, uzak sunucuya bağlanma, kabul ya da ret — tamamen sunucu tarafında ve tarayıcıdan bağımsız işler. Bu yüzden ekrandaki yeşil kutu asla teslimat kanıtı sayılmaz. Gerçek durumu ancak MTA logundan veya panelin teslimat takip ekranından görebilirsiniz.
PHP mail fonksiyonu neden artık yeterli değil#
PHP mail() mesajı kimlik doğrulaması yapmadan yerel kuyruğa bırakır, bu yüzden zarf gönderici adresi sunucunun sistem kullanıcısından türer ve sizin alan adınızla eşleşmez. Gmail, Yahoo ve Outlook birkaç yıldır gönderenin kimliğini SPF ve DKIM üzerinden doğrulanmış görmek istiyor; doğrulanmamış mesajları ya reddediyor ya da spam klasörüne alıyor. mail() bu doğrulamayı kendi başına sağlayamaz. Kimlik doğrulamalı SMTP ise mesajı gerçek bir hesabın kimliğiyle gönderdiği için hem SPF hem DKIM otomatik olarak yerine oturur.
Formdan gelen maile Yanıtla dediğimde müşteriye gitmesini istiyorum, ne yapmalıyım#
Ziyaretçinin adresini Reply-To başlığına yazın, From başlığında kendi alan adınızdaki bir adres kalsın. E-posta istemcileri "Yanıtla" düğmesine basıldığında Reply-To varsa onu, yoksa From alanını kullanır; dolayısıyla davranış tam istediğiniz gibi olur. Bu değişiklik kullanıcı deneyiminde hiçbir kayba yol açmadan DMARC hizalamasını kurtarır. Çoğu form eklentisinde bu iki alan ayrı ayrı yapılandırılabilir durumdadır.
Şifre sıfırlama maili neden özellikle gelmiyor#
Şifre sıfırlama mailleri genellikle otomatik üretildikleri, tek bir bağlantı içerdikleri ve alıcıyla önceden yazışma geçmişi bulunmadığı için filtrelerin en sıkı davrandığı mesaj türüdür. Kimlik doğrulaması eksikse bu mesajlar diğerlerinden önce elenir. Ayrıca birçok sitede şifre sıfırlama maili no-reply@ gibi hiç açılmayan bir kutudan gider ve dönen hata mesajları kimse tarafından okunmaz. SMTP'ye geçtikten sonra bu maillerin başlıklarını ayrıca kontrol etmenizi öneririz.
SMTP kurduğum halde mailler hâlâ spama düşüyor#
SMTP kimlik doğrulaması teslimatın gerçekleşmesini sağlar, gelen kutusuna düşmesini garanti etmez; ikincisi itibar meselesidir. Kayıtlarınız doğruysa sırada gönderdiğiniz IP'nin geçmişi, alan adının yaşı, mesaj içeriğindeki bağlantı sayısı ve alıcıların davranışı vardır. Yeni bir alan adı ya da yeni bir IP kullanıyorsanız güven birikmesi zaman alır. Ayrıca ters DNS kaydının tanımlı olması ciddi fark yaratır; bu konu için PTR kaydı yazımıza bakabilirsiniz.
Hosting sağlayıcısı 25 numaralı portu neden kapatıyor#
Giden 25 numaralı port, ele geçirilmiş sitelerin toplu spam göndermek için kullandığı birincil kanaldır, bu yüzden neredeyse tüm sağlayıcılar bu portu paylaşımlı sunucularda dışa kapalı tutar. Kapalı olması sizin için bir engel değil koruma sayılır: meşru gönderim zaten kimlik doğrulamalı 587 veya 465 üzerinden yapılmalıdır. Kodunuzda port 25 tanımlıysa bunu 587 ile değiştirin ve şifrelemeyi açın. Kendi sunucunuzu yönetiyorsanız bile gönderimi 587 üzerinden yapmak, kimlik doğrulaması zorunlu olduğu için daha güvenlidir.
Mail sunucumu site sunucusundan ayırmak gerekir mi#
Günde birkaç yüz bildirim gönderen sıradan bir kurumsal sitede gerekmez; site ve mail aynı sunucuda sorunsuz çalışır. Ancak toplu bülten, kampanya ya da yüksek hacimli sipariş bildirimi gönderiyorsanız ayırmak mantıklıdır, çünkü gönderim hacmi doğrudan IP itibarını etkiler ve tek bir kötü kampanya sitenizin tüm işlem maillerini de riske atar. Ayrı bir gönderim sunucusu kullanmak, bir sorun çıktığında yalnızca pazarlama trafiğinin etkilenmesini sağlar. Bu ayrımı yapmanın ikinci faydası, teslimat sorunlarını teşhis ederken logların birbirine karışmamasıdır.
Kapanış#
Otomatik maillerin gitmemesi bir eklenti arızası değil, kimlik doğrulama sorunudur. Önce logdan mesajın nerede öldüğünü görün, sonra iki klasik hatayı düzeltin: zarf gönderici adresini kendi alan adınıza çekin ve From alanına asla ziyaretçinin adresini yazmayın. Kalıcı çözüm, gönderimi kimlik doğrulamalı SMTP üzerinden yapmak ve SPF, DKIM, DMARC üçlüsünü tam kurmaktır. Kurulumdan sonra üç farklı sağlayıcıya test gönderip başlıklarda üç kez PASS gördüğünüzde iş bitmiştir.
Bu işi kendiniz yönetmek istemiyorsanız, alan adınıza bağlı kurumsal posta kutularını hazır kimlik doğrulama kayıtlarıyla teslim eden kurumsal e-posta çözümümüz sizin adınıza kurar. Yüksek hacimli bildirim ve kampanya gönderiyorsanız gönderimi web sunucusundan ayıran SMTP sunucu paketleri, ters DNS kaydı ve DKIM imzalama hazır gelir. Bülten tarafını da yönetmek isterseniz e-posta pazarlama hizmetimiz liste hijyeni ve teslimat takibini üstlenir; sitenizi baştan sağlam bir altyapıya taşımak istiyorsanız web hosting paketlerimiz mail hesaplarıyla birlikte gelir.