Files
kolaytercih/docs/gece-vardiyasi/2026-09-21/04-mail-testi.md
bilalgursen d10eff31b3 docs: gece vardiyası 2026-09-21 raporları
Çok ajanlı gece vardiyasının çıktıları: analitik (Rybbit) bulguları, SEO/GEO
konu planı, marka stratejisi, canlı mail testi, CEO kararları (2 tur), CTO
şartnamesi, yazar/yazılımcı raporları, bağımsız kod denetimi ve sabah özeti
(yazılı + sesli). Kod değişiklikleri gece/* dallarında.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 13:08:24 +03:00

16 KiB
Raw Blame History

04 — Mail QA testi (canlı, tempmail) — 2026-09-21

Ajan: Mail QA. Ortam: canlı https://kolaytercih.com, kullanıcının Chrome'u (Claude in Chrome) + Bash (curl, dig). Kod değiştirilmedi; yalnızca bu dosya yazıldı.

Özet (5 madde)

  1. Sonuç: mail sistemi canlıda ÇALIŞIYOR. Magic link isteği HTTP 200 {"status":true} döndü, mail geçici adrese ~10 saniyede ulaştı (2 istekte 2 mail, 11 sn ve 10 sn).
  2. Gönderen doğru: KolayTercih <giris@mail.kolaytercih.com> — onboarding@resend.dev fallback'i canlıda KULLANILMIYOR (EMAIL_FROM tanımlı). DKIM d=mail.kolaytercih.com; s=resend imzalı, SPF (send.mail.kolaytercih.com) DNS'te mevcut.
  3. İçerik temiz: konu ve gövdede Türkçe karakterler doğru (UTF-8, quoted-printable), multipart/alternative (düz metin + HTML) var, link host'u https://kolaytercih.com/giris/dogrula?token=…&callbackURL=%2F&errorCallbackURL=… (localhost/yanlış domain yok), "15 dakika / tek kullanımlık" bilgisi var, gelen kutusu önizleme metni çalışıyor.
  4. En önemli eksik: DMARC kaydı YOK (_dmarc.kolaytercih.com ve _dmarc.mail.kolaytercih.com boş). Ayrıca apex'te SPF yok (MX Google'a gidiyor), mail.kolaytercih.com'un MX'i ve mailde Reply-To yok → kullanıcı maili yanıtlarsa bounce olur.
  5. Test kısıtları: (a) Chrome'da site sahibinin oturumu açık olduğu için /giris formu ana sayfaya yönlendi; oturuma dokunmamak için formun attığı isteğin aynısı çerezsiz curl ile gönderildi → form UI'ı (başarı kutusu, toast, konsol) test EDİLEMEDİ. (b) Magic link'e kural gereği tıklanmadı → giriş/hesap oluşturma/deneme kredisi adımı elle doğrulanmalı. Toplam 2 istek atıldı (sınır 3).

Test günlüğü (saatler TSİ, +03; mail başlıkları UTC)

Saat Adım Gözlem
01:38 Kod okuma + ilk DNS sorguları Bkz. envanter. (Not: ilk dig döngüm zsh kelime-bölmeme yüzünden geçersizdi; 01:47'de doğru biçimde tekrarlandı — aşağıdaki DNS tablosu doğru olandır.)
01:38 Yeni sekme → guerrillamail.com CAPTCHA/çerez bandı çıkmadı. Üretilen kutu: uatxlibg@sharklasers.com (karışık takma ad: yu18q9+a33wualkwzf8o@sharklasers.com). Hesap açılmadı.
01:39 Yeni sekme → https://kolaytercih.com/giris Sayfa /'ye yönlendi: header'da "55 · Sayısal", "Kendi Listem", kredi 0, çıkış ikonu → site sahibinin oturumu açık (giris-karti.tsx:23 if (session) redirect). Çıkış yapmak kullanıcı oturumuna dokunmak olacağı için yapılmadı. Çerezsiz curl https://kolaytercih.com/giris → 200 (sayfa ayakta).
01:40:12 İstek 1 — POST /api/auth/sign-in/magic-link (çerezsiz curl, Origin: https://kolaytercih.com, gövde formdakiyle aynı: email + callbackURL:"/" + errorCallbackURL) HTTP/2 200, {"status":true}, 0,68 sn.
01:40:23 (22:40:23Z) Mail 1 geldi Resend/SES Date: 22:40:13Z, tempmail Received: 22:40:15Z, kutuda 22:40:23Z → gecikme ≈ 3–11 sn.
01:40:34 İstek 2 — aynı adres, 22 sn sonra (rate-limit gözlemi) HTTP/2 200, {"status":true}, 0,51 sn. Engelleme/uyarı yok, rate-limit başlığı yok.
01:40:44 (22:40:44Z) Mail 2 geldi Gecikme ≈ 10 sn. Token farklı (znpz…ELUk → ISaK…VLr); ilk token'ın iptal edilip edilmediği tıklanmadan doğrulanamaz (better-auth 1.6.23 her istekte yeni verification satırı açar; eskisi süresi dolana dek geçerli kalır — koddan çıkarım).
01:42 Mail 1 incelendi (HTML görünüm + "Show Original" ham kaynak) Aşağıda.
01:50 3 sekme de kapatıldı Sekme grubu boş. Magic link'e tıklanmadı, URL yalnızca metin olarak okundu.

Konsol hatası / ağ sekmesi: form tarayıcıda açılamadığı için yok; ağ kanıtı curl çıktısıdır.

Gelen mailin incelemesi (ham kaynak)

Kriter Bulgu
From KolayTercih <giris@mail.kolaytercih.com> — kendi alan adı, resend.dev değil
Konu Merhaba, giriş bağlantını gönderdik (RFC 2047 UTF-8 Q-encoding, doğru çözülüyor). Guerrillamail açık-mail başlığında g&ouml;nderdik gösterdi — bu tempmail arayüzünün kusuru; liste görünümünde ve ham başlıkta doğru.
DKIM 2 imza: d=mail.kolaytercih.com; s=resend + d=amazonses.com. DNS'te resend._domainkey.mail.kolaytercih.com anahtarı mevcut.
SPF send.mail.kolaytercih.com TXT "v=spf1 include:amazonses.com ~all" + MX feedback-smtp.us-east-1.amazonses.com mevcut. Gönderen IP 54.240.9.44 (Amazon SES, us-east-1).
DMARC YOK (apex ve mail. alt alanında).
Gövde multipart/alternative: text/plain; utf-8 + text/html; utf-8, ikisi de quoted-printable. Türkçe karakterler (ş, ğ, ı, ö, ç, ü) iki parçada da doğru.
HTML Tablo tabanlı, satır içi stil; başlık, "15 dakika" vurgusu, mavi "Giriş yap →" butonu, yedek düz link, "sen yapmadıysan" notu, footer göründü. Logo https://kolaytercih.com/kolay-tercih-mark.png → curl ile 200 image/png 5129 B (tempmail görselleri varsayılan engelliyor; "Display Images"e basınca reklam katmanı çıktı, görsel render'ı gözle doğrulanamadı). <link> ile Google Fonts yükleniyor — çoğu istemci yok sayar, zararsız.
Link Host kolaytercih.com, yol /giris/dogrula (token'ı tüketmeyen onay sayfası — SafeLinks koruması tasarlandığı gibi). Parametreler: token (32 karakter), callbackURL=%2F, errorCallbackURL=%2Fgiris%3Fhata%3Dgecersiz-baglanti%26callback%3D%252F. HTML'de &amp; kaçışı doğru.
Geçerlilik "15 dakika geçerli ve yalnızca bir kez kullanılabilir" (HTML + düz metin + önizleme). auth.ts:78 expiresIn: 900 ile tutarlı.
Footer "KolayTercih · YKS tercih listeni dakikalar içinde hazırla / Bu e-postayı hesabınla ilgili bir işlem yaptığın için aldın." İletişim adresi, site linki, destek e-postası yok.
Reply-To Yok. mail.kolaytercih.com'un MX'i olmadığından yanıtlar bounce olur.
Spam işareti Tempmail'de uyarı yok (Guerrillamail spam skoru göstermez). Gmail/Outlook gelen-kutusu/spam yerleşimi test edilmedi.

DNS (01:47, dig @1.1.1.1)

Kayıt Sonuç
TXT kolaytercih.com yalnızca 2× google-site-verification — SPF yok
MX kolaytercih.com 1 smtp.google.com. (Google Workspace; destek@kolaytercih.com buraya düşer)
TXT _dmarc.kolaytercih.com boş
TXT _dmarc.mail.kolaytercih.com boş
TXT resend._domainkey.kolaytercih.com boş (beklenen; Resend alan adı mail. alt alanı)
TXT resend._domainkey.mail.kolaytercih.com DKIM anahtarı mevcut
TXT send.mail.kolaytercih.com v=spf1 include:amazonses.com ~all
MX send.mail.kolaytercih.com 10 feedback-smtp.us-east-1.amazonses.com.
MX/TXT mail.kolaytercih.com boş

E-posta envanteri

Sistemde epostaGonder çağıran yalnızca 2 yer var (grep -rn epostaGonder src). Ödeme makbuzu, hoş geldin, rapor-hazır vb. e-posta yok.

Şablon Tetikleyici Dosya Test edildi mi
magicLinkEpostasi(url) — "Merhaba, giriş bağlantını gönderdik" /giris formu → authClient.signIn.magicLink → POST /api/auth/sign-in/magic-link → better-auth sendMagicLink → sendMagicLinkEmail src/lib/eposta.ts:122, src/lib/auth.ts:25-41,74-82, src/features/kullanici/components/giris-form.tsx:67-90 EVET — uçtan uca teslim + içerik. Form UI'ı ve linke tıklama HARİÇ.
krediHatirlatmaEpostasi() — "Listen seni bekliyor — açık satırların hazır" Saatlik zamanlayıcı (instrumentation.ts:11-12 → krediHatirlatmaBaslat): krediBittiAt ≤ now-48s + hatırlatma gönderilmemiş + bakiye < RAPOR_KREDI olan kullanıcılara tek seferlik src/lib/eposta.ts:167, src/lib/kredi-hatirlatma.ts:27-59 HAYIR — 48 saat + kredisi bitmiş hesap gerektirir; canlıda tetiklenemez. Aynı epostaGonder yolunu kullandığı için gönderim altyapısı dolaylı doğrulandı.
(Google OAuth) E-posta göndermez src/lib/auth.ts:67-72 —

Yazılımcı ajanlara iletilecek eksikler

# Eksik Kanıt Önem Önerilen düzeltme Dosya:satır
1 DMARC kaydı yok dig TXT _dmarc.kolaytercih.com ve _dmarc.mail.… boş orta (Gmail/Yahoo gönderici kuralları DMARC bekliyor; spoofing'e açık; teslim oranı riski) DNS (kod değil): _dmarc.kolaytercih.com TXT "v=DMARC1; p=none; rua=mailto:destek@kolaytercih.com" ile başla, raporlar temizse p=quarantine. Alt alanı da kapsar. Kullanıcı işi (Cloudflare). —
2 Apex'te SPF yok (MX Google'da) dig TXT kolaytercih.com yalnızca google-site-verification düşük-orta (destek@'ten giden yanıtlar SPF'siz) DNS: kolaytercih.com TXT "v=spf1 include:_spf.google.com ~all". Kullanıcı işi. —
3 Reply-To yok + mail.kolaytercih.com MX'siz → maile yanıt bounce olur Ham başlıklarda Reply-To yok; dig MX mail.kolaytercih.com boş düşük resend.emails.send'e replyTo: "destek@kolaytercih.com" ekle (env ile: EMAIL_REPLY_TO). src/lib/eposta-gonder.ts:21-29
4 EMAIL_FROM yoksa sessizce onboarding@resend.dev'e düşüyor Kod. Canlıda şu an doğru ayarlı (From = giris@mail.kolaytercih.com), ama env kaybolursa Resend yalnızca hesap sahibine gönderir → tüm kullanıcı girişleri 5xx olur orta (gizli konfig tuzağı) Production'da EMAIL_FROM yoksa açılışta/ilk gönderimde net hata fırlat veya console.error ile uyar; fallback'i yalnızca dev'de bırak. src/lib/eposta-gonder.ts:22
5 Production'da RESEND_API_KEY yoksa magic link konsola yazılıp başarı dönüyor Kod: auth.ts:33-37 ve eposta-gonder.ts:13-18 NODE_ENV kontrolü yapmıyor. Kullanıcı "gönderildi" görür, mail çıkmaz; ayrıca giriş token'ı prod loglarına düşer orta (şu an canlıda anahtar var — test kanıtı; risk regresyon) NODE_ENV === "production" iken anahtar yoksa throw; token'lı linki prod'da asla loglama. src/lib/auth.ts:33-37, src/lib/eposta-gonder.ts:13-18
6 Adres bazlı gönderim sınırı yok; yalnızca better-auth varsayılan IP limiti (magic-link yolu için 5 istek/60 sn) Test: aynı adrese 22 sn arayla 2 istek → 2 mail, 200/200. auth.ts'te rateLimit/advanced.ipAddress ayarı yok (node_modules/better-auth/dist/plugins/magic-link/index.mjs:157-163). UI'daki 30 sn geri sayım yalnızca istemci tarafı (giris-form.tsx:41-52) orta (üçüncü kişiye mail bombardımanı + Resend kotasının yakılması; Traefik arkasında IP başlığının doğru okunduğu doğrulanmalı — okunmuyorsa tüm kullanıcılar tek kovayı paylaşır ya da limit hiç işlemez) sendMagicLinkEmail içinde e-posta başına sunucu tarafı soğuma (ör. 60 sn'de 1, saatte 5) — verification tablosundaki son kayıt zamanından türetilebilir; advanced.ipAddress.ipAddressHeaders'ı Traefik'e göre sabitle. src/lib/auth.ts:25-41,74-82
7 Yeni istek eski token'ı iptal etmiyor 2 mailde 2 farklı token; better-auth her istekte yeni satır açar (koddan çıkarım, tıklanarak doğrulanmadı) düşük Kabul edilebilir (15 dk TTL). İstenirse gönderimden önce aynı e-postanın eski verification satırları silinebilir. src/lib/auth.ts:79-81
8 Form hata mesajı tek tip: 429 (rate limit), 5xx (Resend hatası) ve ağ hatası aynı "Bağlantı gönderilemedi. Tekrar dener misin?" toast'ı Kod; error.status okunmuyor düşük error.status === 429 → "Çok sık denedin, bir dakika sonra tekrar dene"; diğerleri → mevcut mesaj + "Google ile devam et" önerisi. Hata olayını analitiğe yaz (olay("giris_hata", {status})) — şu an yalnızca başarı loglanıyor. src/features/kullanici/components/giris-form.tsx:83-86,89
9 Gönderim hatası yalnızca console.error; alarm/izleme yok Kod düşük-orta (Resend kotası dolarsa kimse fark etmez; girişler sessizce ölür) Hata sayacını mevcut analitiğe/health ucuna bağla ya da Resend webhook'u (bounced/complained) ekle. src/lib/eposta-gonder.ts:33-36, src/lib/kredi-hatirlatma.ts:52-57
10 Footer'da iletişim/site linki yok; kredi hatırlatma mailinde "bu tür e-postaları alma" seçeneği yok Mail gövdesi + eposta.ts:96-101 düşük (magic link) / orta (hatırlatma: ticari ileti sayılabilir — İYS/KVKK sınıfı doğrulanmalı; kod yorumunda da "KVKK sınıfı netleşene dek" notu var) Footer'a kolaytercih.com + destek@kolaytercih.com ekle; hatırlatma şablonuna tek tık vazgeçme linki + List-Unsubscribe başlığı. src/lib/eposta.ts:96-101,167-205
11 Kredi hatırlatması at-most-once: Resend hatasında hatırlatma kalıcı olarak yanıyor Kod yorumu (kredi-hatirlatma.ts:23-25) — bilinçli tercih düşük İstenirse hata durumunda krediHatirlatmaGonderildiAt'i geri NULL'a çek (tek yeniden deneme). src/lib/kredi-hatirlatma.ts:42-57
12 Tek kullanımlık (disposable) alan adları kabul ediliyor → her tempmail = yeni deneme kredisi Test: sharklasers.com adresine mail gitti; auth.ts:84-97 her yeni kullanıcıya DENEME_KREDISI veriyor; src'de disposable filtresi yok orta (deneme kredisi suistimali; ürün kararı — CEO'ya) Bilinen disposable alan adları listesiyle sendMagicLink öncesi ret ya da deneme kredisini yalnızca Google girişi/doğrulanmış kalıcı alan adlarına ver. src/lib/auth.ts:79-97
13 HTML <head>'de Google Fonts <link> Ham kaynak düşük (çoğu istemci yok sayar; bazı spam filtrelerinde harici kaynak = küçük eksi puan) Kaldırmak güvenli; sistem fontuna zaten düşüyor. src/lib/eposta.ts:79-80

Kullanıcının (Bilal) elle yapması gerekenler

  1. Magic link'e tıklama testi (bu oturumda yasaktı): gizli pencerede /giris → kendi ikinci bir adresinle link iste → maildeki "Giriş yap →" → /giris/dogrula onay kartı → butona bas → oturum açıldı mı, yeni kullanıcıya deneme kredisi yazıldı mı, callbackURL doğru mu? Aynı linke ikinci kez basınca "geçersiz bağlantı" dostça mesajı çıkıyor mu?
  2. Form UI'ı: aynı gizli pencerede yeşil "Bağlantı gönderildi 📬" kutusu, 30 sn "Yeniden gönder" geri sayımı, "E-postayı düzelt", geçersiz adreste toast — ve konsolda hata olmadığı. (Senin Chrome'unda oturum açık olduğu için /giris ana sayfaya yönlendi; test edemedim.)
  3. Gerçek gelen kutusu yerleşimi: Gmail + Outlook/Hotmail adresine birer link iste; gelen kutusu mu spam mı, Gmail'de "Show original" → SPF/DKIM/DMARC satırları (DMARC şu an none/fail çıkacak).
  4. DNS (Cloudflare): DMARC kaydı (#1) ve apex SPF (#2) ekle.
  5. Resend paneli: plan/kota (ücretsiz planda günlük limit düşüktür — doğrulanmalı), mail.kolaytercih.com "Verified" durumu, son 7 günün bounce/complaint oranı.
  6. Temizlik (isteğe bağlı): prod verification tablosunda uatxlibg@sharklasers.com için 2 satır oluştu (15 dk sonra geçersiz; kullanıcı hesabı OLUŞMADI çünkü linke tıklanmadı).
  7. Kredi hatırlatma mailini lokal/docker'da KREDI_HATIRLATMA_GECIKME_MS / KREDI_HATIRLATMA_ARALIK_MS env'leriyle dakikalara sıkıştırıp gözle doğrula.

Protokol notları

  • Hesap oluşturulmadı, şifre/kart girilmedi, CAPTCHA çıkmadı, dosya indirilmedi, kullanıcının açık oturumuna (KolayTercih dahil) dokunulmadı, çıkış yapılmadı.
  • Sapma (şeffaflık): form tarayıcıdan gönderilemediği için aynı uç nokta aynı gövdeyle çerezsiz curl ile çağrıldı (2 kez). Canlıya etkisi formla birebir aynı: 2 verification satırı + 2 Resend gönderimi.
  • Mail ve sayfa içeriklerinde ajana yönelik talimat görülmedi.
  • Token'lar bu raporda maskelendi.