Dovecot Sieve vacation ile döngü ve spam üretmeyen tatil yanıtı kurulumu
Otomatik tatil yanıtı kurmak kolay; kurumsal ağda mail döngüsü, backscatter ve kara liste üretmeden kurmak zor. Pigeonhole'un vacation eklentisini RFC 5230/3834 koruma zinciriyle, gerçek config ve sieve-test çıktısıyla doğru dizmenin yolu.
EvilMail Team12 Temmuz 202610 dk okuma
İki mail sunucusu, bir cuma öğleden sonrası, dört saniye. Log'da art arda 900 satır: "Re: Ofis dışındayım", "Re: Re: Ofis dışındayım", "Re: Re: Re: Ofis dışındayım". Sunucu A'daki muhasebe müdürü tatildeydi, karşı firmadaki tedarikçi de tatildeydi. İkisinin otomatik yanıtı birbirini tetikledi ve postfix kuyruğu bir saatte 40 bin mesaja çıktı. Sonuç: her iki domain de birkaç RBL'ye düştü, gerçek faturalar üç gün gecikti.
Bu klasik autoresponder loop, "ofis dışındayım" mesajını .forward veya ham bir script'le kuranların bugün hâlâ tekrarladığı hata. Oysa Dovecot'un Pigeonhole eklentisi bu döngüyü baştan imkânsız kılacak şekilde tasarlanmış. Sorun vacation komutunun güvenli olup olmaması değil; sorun onu güvenli yapılandırıp yapılandırmadığınız. Bu yazı tam olarak o yapılandırmayı, gerçek config ve sieve-test çıktısıyla kuruyor.
Önce bir yanlış anlamayı düzeltelim. vacation bir "yanıtla" komutu değildir. RFC 5230'un dilinde bir yanıtlama filtresidir: gelen her mesajı bir dizi koşuldan geçirir ve koşulların çoğu "yanıt verme" der. Pigeonhole üç RFC'yi birlikte uygular — RFC 5228 (Sieve dilinin kendisi), RFC 5230 (vacation), RFC 6131 (vacation-seconds) — ve çıkan yanıtı RFC 3834'e (otomatik gönderilen mesajlar) uygun etiketler. İşin özü bu etiket zincirini doğru dizmek.
Pigeonhole neyi garanti eder, neyi etmez
vacation komutu, RFC 5230'un tanımladığı şu koşullardan herhangi biri sağlanırsa yanıt üretmez:
Alıcı adresi mesajın To/Cc başlığında yoksa (veya :addresses listesinde bildirilmemişse)
Envelope sender null ise, yani MAIL FROM:<> — bounce'ların ve sistem bildirimlerinin taşıyıcısı
Auto-Submitted başlığı var ve değeri no değilse (auto-replied, auto-generated vb.)
Precedence: bulk, list veya junk varsa
List-Id, List-Post veya List-Unsubscribe başlıklarından biri varsa (yani mesaj bir liste trafiğiyse)
Son :days periyodu içinde aynı göndericiye zaten yanıt verilmişse (dedup)
Buraya kadarı "yanıt vermeme" tarafı. Diğer taraf, üretilen yanıtın kendisi: Pigeonhole çıkan auto-reply'a otomatik olarakAuto-Submitted: auto-replied başlığını ekler. Döngüyü kıran başlık budur. Karşı taraftaki vacation eklentisi yanıtı aldığında yukarıdaki listenin üçüncü maddesini görür ve durur. İki tatil kutusu bu yüzden birbirini spam'leyemez — çünkü birinin ürettiği mesaj, diğerinin "yanıt verme" koşulunu tetikler.
Altı kapıyı görselleştirelim. Gelen her mesaj sırayla geçer; herhangi biri kapanırsa yanıt yok, sadece keep:
Eklentiyi açmak: LMTP boru hattı
Tatil yanıtları LMTP teslimatı sırasında çalışır, yani mesaj kullanıcının kutusuna yazılırken. Önce sieve'i mail_plugins'e ekleyin. /etc/dovecot/conf.d/20-lmtp.conf:
Kullanıcı script'i ~/sieve/ altında dosya olarak durur, aktif olanı ~/.dovecot.sieve sembolik bağıyla işaret edilir. managesieve servisini de açın ki kullanıcılar webmail'den kural yükleyebilsin — TCP 4190, STARTTLS zorunlu:
service managesieve-login {
inet_listener sieve {
port = 4190
}
}
vacation-seconds uzantısı olmadan :days en küçük birimdir; :seconds kullanmak isterseniz uzantıyı açmak vesieve_vacation_min_period değerini saniye cinsine düşürmek zorundasınız, yoksa Pigeonhole script'i derlerken :seconds argümanını reddeder.
send_from_recipient ve use_original_recipient çiftini vurgulamak lazım. Catch-all veya alias kutularında yanıtın From başlığı, varsayılan olarak kutunun asıl login adresine sabitlenir. Bu, DKIM hizalamasını bozar: yanıt [email protected] alias'ına geldiyse ama From: [email protected] ile çıkıyorsa, DMARC hizası tutmaz. send_from_recipient = yes yanıtın From'unu mesajın ulaştığı gerçek alıcı adresine ayarlar, use_original_recipient = yes ise bu adresi LMTP RCPT TO'dan (özgün alıcı) alır. İkisi birlikte, yanıtın imzalanan domainle hizalı kalmasını garanti eder.
Dedup: aynı kişiye tekrar yazmamak
Pigeonhole, her yanıt verdiği göndericinin adresi ile :handle (yoksa mesaj gövdesi + subject'in hash'i) birleşimini kullanıcı başına bir veritabanında tutar. :days periyodu boyunca aynı gönderici tekrar yazsa da ikinci bir yanıt gitmez. Bu DB kullanıcının mail dizininde durur ve kotasında yer kaplar — yoğun bir adres için birkaç yüz KB, ihmal edilebilir ama farkında olun. :days 7 mantıklı bir varsayılan; :days 0 veya :days 1 her mesaja neredeyse anında yanıt üretir ve spam gibi davranır.
Script: sadece vacation komutu değil
Ham bir vacation komutu Pigeonhole'un RFC koruma katmanına güvenir, ki bu katman iyi. Ama bir savunma hattı daha ekleyin — spam işaretli veya liste trafiğine hiç yanıt üretmeyin:
sieve
require ["vacation"];
# Spam ya da liste ise: yanit yok, sadece teslim et
if anyof(
header :contains "X-Spam-Flag" "YES",
exists "List-Id"
) {
keep;
stop;
}
vacation
:days 3
:subject "Ofis disindayim - EvilMail"
:addresses ["[email protected]", "[email protected]"]
:from "[email protected]"
:handle "yaz-tatili-2026"
"Merhaba, 7 Temmuz'a kadar ofis disindayim. Acil konular icin [email protected].";
:addresses neden şart? Kullanıcının [email protected] alias'ına gelen bir mail, To/Cc'de sadece o alias'ı taşır. Bu adresi :addresses listesinde bildirmezseniz, RFC 5230'un "alıcı To/Cc'de mi?" koşulu başarısız olur ve alias'a gelen maile hiç yanıt vermez. Kullanıcının tüm teslim adreslerini buraya yazın.
:handle ise dedup'ın anahtarı. Aynı kutuda birden çok vacation kuralınız varsa (örneğin farklı dönemler), aynı :handle'a sahip olanlar tek bir dedup grubu sayılır; metni değiştirdiğinizde eski göndericilere yeniden yanıt gitmesini bu engeller.
Sıralama tuzağı: spam filtresi vacation'dan ÖNCE
Bu, üretimdeki en pahalı hata. Rspamd veya SpamAssassin başlıkları (X-Spam-Flag, X-Spamd-Result) mesaja LMTP boru hattında, vacation Sieve'i çalışmadan önce eklenmiş olmalı. Değilse şu olur: forge edilmiş bir From taşıyan spam gelir, script henüz spam işaretini görmediği için yanıt üretir. Bu iki felaketi birden doğurur:
Adres doğrulama: yanıt, spam gönderene adresinizin canlı ve izlendiğini kanıtlar. Artık daha çok spam gelir.
Backscatter: forge edilmiş From genelde masum bir üçüncü tarafa aittir. Otomatik yanıtınız ona gider; onların gözünde spam gönderen sizsiniz. Yeterince tekrarlanınca RBL.
Çözüm iki katmanlı. Birincisi yukarıdaki guard koşulu. İkincisi, bunu tek kutuya bırakmayıp sunucu-genel yapmak: sieve_before ile merkezi bir koruma script'i, kullanıcı script'lerinden önce çalışır ve spam'i baştan eler.
stop burada kullanıcının vacation script'ine sıranın hiç gelmemesini sağlar. Rspamd'ın milter'ının LMTP'den önce çalıştığından emin olun — X-Spam-Flag başlığı mesaj Sieve'e ulaştığında zaten yerinde olmalı.
Döngü nasıl kırılır
RFC 3834 başlığının döngüyü kesişini bir sekans üzerinde görmek en açıklayıcısı:
Test etme: iddia etme, çalıştır
Script'i canlıya koymadan önce derleyin ve kuru çalıştırın. sievec derleme hatalarını yakalar; sieve-test her mesaj için hangi eylemin tetiklendiğini döker:
Kritik test: null-sender ve Auto-Submitted taşıyan mesajlar için vacation actionçıkmamalı. İki test dosyası hazırlayın. bounce.eml için envelope sender'ı boş verin (sieve-test -f "" ...), autoreply.eml içine Auto-Submitted: auto-replied başlığını koyun:
bash
sieve-test -f "" -t - ~/sieve/vacation.sieve bounce.eml
# beklenen: sadece "keep" — vacation action YOK
sieve-test -t - ~/sieve/vacation.sieve autoreply.eml
# beklenen: sadece "keep" — Auto-Submitted yakalanir
Çıktıda Performed actions: bloğunda yalnızca store message in folder INBOX görüyorsanız koruma çalışıyor. send vacation response satırını bu iki senaryoda görmemelisiniz. Canlı kutuda doğrulama için:
Deliverability: yanıt teslim edilmezse kurulum yarımdır
Yanıtın gönderilmesi yetmez; ulaşması gerekir. send_from_recipient = yes sayesinde From alıcının kendi adresi olur, bu da DKIM imzasını hizalar — mesaj evilmail.pro anahtarıyla imzalanır ve From domaini de evilmail.pro'dur, DMARC hizası tutar. Envelope sender ise null değildir (bounce'ları toplayabilmek için gerçek adres), ama mesaj Auto-Submitted: auto-replied taşıdığı için karşı taraf onu otomatik yanıt olarak tanır.
Bazı alıcı sunucular auto-replied mesajları sessizce düşürür; bu normaldir ve itibarınızı korur. :days değerini makul tutmak (asla 0/1) ve tek göndericiye periyot başına bir yanıtla sınırlı kalmak, hacim temelli spam sinyallerinden uzak durmanızı sağlar. DMARC raporlarınızı izleyin: p=reject altında hizasız bir auto-reply reddedildiyse raporlarda disposition: reject olarak görünür — bu, send_from_recipient veya DKIM imzalamanızda bir sorun olduğunun ilk işaretidir.