Files
kolaytercih/docs/gece-vardiyasi/2026-09-21/04-mail-testi.md
bilalgursen 0ab4dbe88c
All checks were successful
Deploy / deploy (push) Successful in 7m18s
Enhance Traefik configuration for www.kolaytercih.com
Added a new router and middleware for handling www to apex domain redirection, ensuring that Let's Encrypt certificates are obtained for both domains. Updated the docker-compose.yml file to include necessary rules and middleware for proper redirection and TLS handling.

Also, updated the CEO agent description to remove redundant details and clarified the QA engineer's responsibilities regarding testing critical flows and error reporting. Adjusted the CTO agent's section for consistency in expert guidance and clarified the designer's tools to include 'Skill' for better design resource management.
2026-09-21 20:37:12 +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.