Dovecot Sieve ile Sunucu Tarafı E-posta Filtreleme: Gelen Postayı Otomatik Klasörlere Ayırın
Thunderbird ve Outlook kuralları tek cihazda, üstelik yalnızca uygulama açıkken çalışır. Filtreyi teslimat anına, Dovecot'un LMTP katmanına taşıyın: Pigeonhole Sieve postayı INBOX'a düşmeden bir kez ayıklar ve sonuç telefonda da webmail'de de aynı olur. Gönderen/konu/başlık ayrımının doğru testinden kural sırasının neden her şeyi belirlediğine kadar, production bir Sieve scriptini baştan sona kuruyoruz.
EvilMail Team9 Temmuz 202611 dk okuma
Şu tanıdık mı: Thunderbird'de yıllar içinde biriktirdiğiniz 40 filtre kuralı var. Bilgisayarı kapatıp telefondan bakıyorsunuz, INBOX yine 300 okunmamış. Bültenler, GitHub bildirimleri, faturalar, hepsi üst üste yığılmış. Çünkü o 40 kural telefonda yok, webmail'de yok, ikinci dizüstünüzde de yok. Sadece o tek Thunderbird kurulumunda, o da yalnızca uygulama açıkken çalışıyor.
İstemci tarafı filtrenin üç yapısal kusuru var ve hiçbiri düzeltilebilir değil:
İstemci açık olmalı. Kural, uygulamanın IMAP'e bağlanıp yeni postayı çekmesiyle tetiklenir. Bilgisayar kapalıysa kural da yok.
Tek cihaz. Kurallar .thunderbird profilinde yaşar. Telefon o profili görmez; her cihaz için kuralları elle senkronlamak zorundasınız.
IMAP tarafında görünmez. Sunucu, filtrenin varlığından habersizdir. Webmail açtığınızda ham INBOX'la yüzleşirsiniz.
Çözüm tek cümle: filtreyi teslimata taşıyın. Posta INBOX'a yazılmadan, herhangi bir istemci onu görmeden önce sunucuda bir kez ayıklansın. Dovecot bunu Pigeonhole Sieve motoruyla yapar ve sonuç bütün cihazlarda birebir aynıdır.
Sieve teslimat anında nerede çalışır
Bir mesajın sunucunuza giriş zinciri şöyle: dışarıdaki MTA, Postfix'in 25. portuna bağlanır, Postfix mesajı kabul eder ve yerel teslimat için LMTP üzerinden Dovecot'a devreder. İşte tam bu noktada, mesaj kullanıcının mailbox'ına yazılmadan hemen önce, Pigeonhole devreye girer ve aktif Sieve scriptini değerlendirir.
"Teslimat anı" ifadesi burada kritik. Kural, mesaj daha diskteki hiçbir klasöre yazılmadan çalışır. fileinto "Bultenler" derseniz, mesaj INBOX'a hiç uğramadan doğrudan Bultenler klasörüne düşer. Bir istemcinin sonradan taşıması değil bu; mesaj baştan orada doğar. Bir kez çalışır, her yerde geçerlidir.
Sieve tek katman da değildir. Üç ayrı script katmanı sırayla değerlendirilir: önce organizasyon geneli sieve_before, sonra kullanıcının kendi ~/.dovecot.sieve scripti, en sonda sieve_after. Bu katmanlama, "tüm kullanıcılar için spam'i Junk'a at" gibi global politikayı kişisel kurallardan ayırmanızı sağlar.
Pigeonhole'u devreye almak
Debian/Ubuntu üzerinde iki paket yeter:
bash
apt install dovecot-sieve dovecot-managesieved
dovecot-sieve Pigeonhole motorunu ve sievec, sieve-test, sieve-filter araçlarını getirir. dovecot-managesieved, kullanıcıların kendi scriptlerini uzaktan düzenlemesini sağlayan ManageSieve servisini ekler (TCP 4190).
Önce teslimat protokollerine plugin'i tanıtın. /etc/dovecot/conf.d/15-lda.conf ve 20-lmtp.conf içinde:
sieve = file:~/sieve;active=~/.dovecot.sieve satırı şunu söyler: kullanıcının scriptleri ~/sieve/ dizininde dosya olarak durur, aktif olan ~/.dovecot.sieve sembolik bağıyla işaretlenir. ManageSieve bu düzeni kendi yönetir; siz elle uğraşmazsınız.
Kritik kavram implicit keep: hiçbir kural eşleşmezse veya hiçbir aksiyon çalışmazsa, Sieve mesajı sessizce INBOX'a bırakır. Yani "eşleşmeyen her şey INBOX'a" davranışını siz yazmak zorunda değilsiniz; varsayılan budur. fileinto çalıştığı anda ise implicit keep iptal olur — mesaj artık INBOX'a değil, belirttiğiniz klasöre gider. Bu incelik ileride çift kopya tuzağının kaynağı olacak.
Temel aksiyonlar:
keep — mesajı INBOX'ta tut (implicit keep'in açık hali)
fileinto "Klasor" — belirtilen klasöre koy
discard — sessizce sil (bounce yok)
redirect "adres" — başka adrese yönlendir
stop — script değerlendirmesini burada kes
require satırı zorunludur, çünkü Sieve'in çekirdeği (RFC 5228) minimaldir. fileinto, mailbox (klasör oluşturma), imap4flags (bayrak işleme), envelope, regex — her biri ayrı bir eklentidir ve kullanmadan önce require ile bildirilmelidir. Bildirmeden fileinto yazarsanız script derlenmez.
Gönderen, konu ve başlığa göre ayırma
İşin ustalık gerektiren kısmı doğru testi seçmek. "Gönderene göre" üç farklı şey demek olabilir:
`envelope "from"` — SMTP zarfındaki MAIL FROM adresi. Forward edilen postada bu, görünen From'dan farklıdır; mailing list'lerde de zarf genelde listenin bounce adresidir. envelope eklentisi require gerektirir.
`header "from"` — ham başlık metni. İsim + adresin tamamı üzerinde eşleşme yaparsınız.
Domain'e göre eşleşmek için address testinin adres bölümleyicilerini kullanın: address :domain "from" sadece github.com kısmını verir, :localpart sadece kullanıcı kısmını, :all tümünü.
List-Id ile bülten yakalamak en sağlam yöntemdir. Konu satırı değişir, gönderen adresi kampanyadan kampanyaya farklılaşır, ama düzgün bir bülten altyapısı her mesaja aynı List-Id: başlığını koyar (RFC 2919). Konuya göre tahmin yürütmek yerine bu değişmez imzayı yakalayın.
Klasör yoksa fileinto :create ile otomatik açın (mailbox eklentisi). Otomatik okundu işaretlemek için imap4flags ile addflag "\\Seen". Eşleşme tipleri: :is (tam), :contains (içerir), :matches (* ve ? joker), :regex (Pigeonhole eklentisi, maliyeti daha yüksek).
subaddress eklentisi sayesinde [email protected] gibi bir adrese gelen postanın + sonrasındaki shop etiketini envelope :detail "to" ile okursunuz. Nereye kaydolduğunuzu takip edebilir, sızan adresleri tespit edebilirsiniz.
Kural sırası: her şeyi belirleyen kısım
Sieve yukarıdan aşağı akar. Yukarıdaki scriptin her fileinto'sunun peşine neden stop koyduğuma dikkat edin. stop olmadan bir mesaj birden fazla if bloğuna uyar ve iki kez dosyalanabilir.
İki yaklaşım var. Birbirini dışlayan kurallarda if / elsif / else zinciri en temizidir; ilk uyan blok çalışır, gerisi hiç değerlendirilmez. Bağımsız if bloklarını art arda dizerseniz her biri ayrı çalışır ve stop koymazsanız aynı mesaj birden çok klasöre kopyalanır.
En sık yapılan hata: fileinto yazıp ardından refleksle keep de eklemek. fileinto zaten implicit keep'i devraldığı için keep gereksizdir; onu eklerseniz mesaj hem hedef klasöre hem INBOX'a düşer. Çift kopya buradan gelir. Kural basit: fileinto kullanıyorsanız keep yazmayın.
:matches joker eşleşmesi :regex'ten ucuzdur. Basit desenler için :matches "*@github.com" yeterliyken düzenli ifadeye uzanmayın; her mesajda çalışacak bu motorda maliyet birikir.
Global scriptler ve spam entegrasyonu
Tüm kullanıcılar için tek bir politikayı sieve_before ile uygularsınız. Klasik örnek, Rspamd veya SpamAssassin'in eklediği başlığa bakıp Junk'a atmak. /etc/dovecot/sieve/global-before.sieve:
Global scriptler dosya olarak durur; performans için sievec ile derleyin:
bash
sievec /etc/dovecot/sieve/global-before.sieve
Bu, yanına .svbin bytecode üretir ve her teslimatta yeniden derlemeyi önler. .sieve dosyasını değiştirdiğinizde .svbin'i yenilemeyi unutmayın, yoksa Dovecot eski derlenmiş halini kullanır.
Not: tatil/otomatik yanıt (vacation, RFC 5230) da aynı motorda yaşar ve aynı require mekaniğiyle çalışır, ama teslimat filtrelemesinden ayrı bir konudur; burada karıştırmayın.
Test ve hata ayıklama
Scripti canlıya sürmeden önce gerçek bir .eml dosyası üzerinde kuru çalıştırın:
bash
sieve-test ~/.dovecot.sieve mesaj.eml
Çıktı, hangi kuralın eşleştiğini ve mesajın nereye gideceğini (fileinto hedefi veya implicit keep) satır satır gösterir. Klasörün gerçekten oluşup oluşmadığını değil, mantığın doğru dallandığını burada görürsünüz.
Derleme hatalarını sievec yakalar. Tipik çıktı:
error: line 7: fileinto is not allowed in this context.
error: line 7: name 'fileinto': not found; forgot to 'require'?
Bu mesaj neredeyse her zaman eksik require demektir. Eklentiyi bildirin, hata gider.
Canlı teslimatı izlemek için /var/log/dovecot.log içindeki sieve: ile başlayan satırlara bakın. Daha ayrıntılı iz için sieve_trace_dir tanımlayıp adım adım değerlendirme dökümü alabilirsiniz. Aktif scripti ve ManageSieve üzerinden yüklenmiş scriptleri doveadm ve managesieve istemcisiyle listeleyebilirsiniz.
Deploy öncesi kontrol listesi
`require` satırları tam mı? Kullandığınız her eklenti (fileinto, mailbox, envelope, imap4flags, subaddress, regex) bildirilmiş olmalı.
`fileinto :create` var mı? Klasör önceden yoksa :create olmadan mesaj INBOX'a düşer; sessizce kaybolmaz ama beklediğiniz yerde olmaz.
Her `fileinto`'dan sonra `stop` doğru mu? Birbirini dışlayan kurallarda çift dosyalamayı stop engeller.
`fileinto` yanında gereksiz `keep` yok, değil mi? Varsa INBOX'ta çift kopya bırakır.
`envelope` mı `address` mı? Forward ve mailing list senaryolarında doğru olanı seçin; görünen From ile SMTP zarfı farklıdır.
Global spam kuralı `sieve_before`'da mı? Kişisel kurallar spam'i INBOX'ta işlemeden önce Junk'a ayrılmalı.
ManageSieve kilitli mi? 4190 portu yalnızca TLS üzerinden ve kimlik doğrulamayla açık olsun.
`sieve-test`'ten geçti mi? Gerçek örnek mesajlarla kuru çalıştırma yapmadan canlıya almayın.
Kapanış notu: bu scripti bir metin dosyası gibi değil, kod gibi görün. ~/.dovecot.sieve ve global scriptlerinizi versiyon kontrolüne alın; bir kural bozulduğunda ne değiştiğini git diff ile görebilmek, üç ay sonra "40 kural neden çalışmıyor" tuzağına düşmemenin en ucuz sigortasıdır.