Python’da Regex Sınır Bekçiliği: E-posta, Telefon ve Şifre Doğrulama

Bir web formuna yanlış yazılmış bir e-posta adresi, hatalı biçimli bir telefon numarası ya da “12345” gibi zayıf bir şifre girildiğinde, bu hatanın veritabanına ulaşmadan önce yakalanması gerekir. Python’ın yerleşik re modülü, tam da bu “girdi kapıda durdurulsun” mantığını birkaç satır kodla kurmanızı sağlar.

Bu Proje Ne Yapıyor?

Bu proje, üç farklı doğrulama (validation) senaryosunu düzenli ifadeler (regular expressions / regex) kullanarak çözen küçük ama öğretici bir motor kuruyor:

  1. E-posta doğrulama — bir metnin geçerli bir e-posta adresi yapısına uyup uymadığını kontrol ediyor.
  2. Türk telefon numarası doğrulama ve normalizasyon+90, 0 ön eki veya boşluklarla yazılmış numaraları tanıyor, hatta numarayı alan kodu ve bloklara ayırarak “temizlenmiş” bir çıktı üretiyor.
  3. Şifre güvenlik denetimi — bir şifrenin büyük harf, küçük harf, rakam ve özel karakter gibi kriterleri karşılayıp karşılamadığını tek tek raporluyor.

Amaç, tek bir dev regex yazıp her şeyi ona sıkıştırmak değil; her problemi kendi doğal sınır koruma (boundary guard) katmanına ayırarak okunabilir ve genişletilebilir bir yapı kurmak. Bu, gerçek dünyadaki form doğrulama, API girdi kontrolü veya veri temizleme (sanitation) katmanlarının küçük bir modeli.

Gerçek bir üretim sisteminde bu tür kontroller genellikle uygulamanın en dış katmanında, yani veriler veritabanına yazılmadan veya bir e-posta gönderme servisine iletilmeden hemen önce çalışır. Kullanıcıdan gelen “kirli” veriyi burada durdurmak, hem güvenlik açıklarının (ör. enjeksiyon saldırıları) önüne geçer hem de ileride “neden bu kayıt bozuk?” diye debug etmek zorunda kalmazsınız. Regex, bu tür sınır kontrolleri için hızlı ve bağımlılıksız bir çözüm sunduğu için hâlâ yaygın olarak tercih ediliyor.

Kodun Anatomisi

Bilgi kutusu: Yazar: Ahmet Aksoy · Tarih: 27.05.2026 · Ortam: Python 3.12, Ubuntu 24.04

Projenin kalbinde re.match() ve re.search() fonksiyonları arasındaki fark yatıyor. re.match() yalnızca dizenin başından eşleşmeye bakar (bu yüzden e-posta ve telefon desenlerinde ^ ve $ ile tüm dizeyi sınırlıyoruz), re.search() ise dizenin herhangi bir yerinde bir örüntü arar — şifre kontrolünde her kriter için ayrı ayrı re.search() kullanılmasının nedeni de bu.

E-posta doğrulama fonksiyonu, klasik bir yapı maskesi kullanıyor:

import re

def validate_email(email: str) -> bool:
    email_pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
    return bool(re.match(email_pattern, email))

# Örnek çıktı:
# ahmet.aksoy@example.com -> VALID
# user@com               -> INVALID (nokta ve TLD eksik)

Telefon doğrulama fonksiyonu ise regex’in sadece “evet/hayır” cevabı vermekle kalmayıp, grup yakalama (capturing groups) ile veri çıkarabildiğini gösteriyor:

def validate_turkish_phone(phone: str) -> bool:
    phone_pattern = r"^(?:\+90|0)?\s?([5]\d{2})\s?(\d{3})\s?(\d{2})\s?(\d{2})$"
    match = re.match(phone_pattern, phone)

    if match:
        area_code, part1, part2, part3 = match.groups()
        print(f"Alan Kodu: ({area_code}) Numara: {part1}-{part2}-{part3}")
        return True
    return False

Burada (?:\+90|0)? bir yakalamayan grup (non-capturing group) — yani “+90 veya 0 ile başlayabilir ama bu kısmı ayrıca bir değişkene almama gerek yok” demenin yolu. Parantez içine alınan dört blok ise match.groups() ile birer birer erişilebilir hale geliyor. Bu teknik, ham bir metinden yapılandırılmış veri çıkarmanın (data extraction) temelini oluşturuyor — log dosyalarından belirli alanları ayıklarken de aynı yaklaşımı görebilirsiniz; bu konuyu daha derinlemesine işlediğimiz Python’da Regex Ustalık Sınıfı: Karmaşık Log Dosyalarını Düzenli Veriye Dönüştürmek yazımıza da göz atabilirsiniz.

Şifre kontrolü ise tek bir karmaşık regex yerine, okunabilirliği önceliklendirerek beş ayrı kontrolü listeye topluyor:

def assess_password_strength(password: str) -> list[str]:
    failed_criteria = []
    if len(password) < 8:
        failed_criteria.append("En az 8 karakter olmalı.")
    if not re.search(r"[A-Z]", password):
        failed_criteria.append("En az bir büyük harf [A-Z] içermeli.")
    if not re.search(r"[a-z]", password):
        failed_criteria.append("En az bir küçük harf [a-z] içermeli.")
    if not re.search(r"\d", password):
        failed_criteria.append("En az bir rakam [0-9] içermeli.")
    if not re.search(r"[@$!%*?&]", password):
        failed_criteria.append("En az bir özel karakter [@$!%*?&] içermeli.")
    return failed_criteria

Bu yaklaşımın en büyük avantajı, kullanıcıya “şifreniz geçersiz” gibi belirsiz bir mesaj yerine, tam olarak hangi kriteri karşılamadığını söyleyebilmesi.

Burada dikkat etmeniz gereken bir tuzak da var: e-posta regex’i, RFC 5322 standardının izin verdiği her varyasyonu (ör. tırnak içindeki özel karakterler, uluslararası alan adı uzantıları) kapsamıyor. Pratikte “yeterince iyi” bir kontrol için bu basitleştirilmiş desen genellikle işe yarar, ama gerçekten kritik bir sistemde (ör. fatura veya KVKK bildirimleri) e-postanın gerçekten var olup olmadığını anlamak için mutlaka bir doğrulama e-postası göndermeniz gerekir — regex sadece “biçim” kontrolü yapar, “gerçeklik” kontrolü yapmaz.

Nasıl Çalıştırılır?

Proje, standart kütüphane dışında hiçbir bağımlılık gerektirmiyor. Python 3.12 kurulu bir Ubuntu (veya herhangi bir Linux/UNIX) sisteminde şu adımları izlemeniz yeterli:

# Proje klasörüne geçin
cd 38_regex_validation

# Programı çalıştırın
python3 main.py

Çalıştırdığınızda terminalde üç ayrı test bloğu göreceksiniz: geçerli/geçersiz e-postaların listelendiği bölüm, telefon numaralarının normalize edilip alan kodlarına ayrıldığı bölüm ve zayıf şifrelerin hangi kriterlerde başarısız olduğunu satır satır gösteren bölüm.

Ne Öğrendik?

  • re.match() dizenin başından, re.search() ise dizenin herhangi bir yerinden eşleşme arar — hangi durumda hangisini kullanacağınızı bilmek regex hatalarının çoğunu önler.
  • ^ ve $ gibi sınır işaretleri (anchors), “kısmi eşleşme” tuzağına düşmemek için kritik — bunları unutursanız user@com123 gibi hatalı bir e-posta bile geçerli sayılabilir.
  • Yakalayan () ve yakalamayan (?:) gruplar arasındaki fark, hem performans hem de kodun okunabilirliği açısından önemli.
  • Karmaşık bir doğrulama kuralını tek bir dev regex yerine, her biri tek bir sorumluluğa sahip küçük kontrollere bölmek, hem hata mesajlarını netleştiriyor hem de kodu bakımı kolay hale getiriyor.

Kaynaklar ve Sonraki Adımlar

Bu projeyi genişletmek isterseniz, e-posta doğrulamasını email-validator gibi RFC uyumlu bir kütüphaneyle karşılaştırabilir ya da şifre kurallarını zxcvbn gibi bir entropi tabanlı güç ölçer ile destekleyebilirsiniz. Python’ın re modülünün resmi belgelerine buradan ulaşabilirsiniz.

Ahmet Aksoy

Not: Bu yazıda incelediğimiz kodu ve benzer projelerin kaynak kodlarını https://github.com/ahmetax/practical-python-examples adresinde bulabilirsiniz.

Bir Yanıt Bırak

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir