Dovecot'ta Paylaşımlı ve Genel IMAP Klasörleri: Namespace ve ACL'yi Sıfırdan Doğru Kurmak
Paylaşımlı IMAP klasörlerinin "çalışmaması"nın neredeyse tamamı üç hataya iner: yanlış separator, eksik INDEXPVT ve unutulmuş acl_shared_dict. Dovecot'ta ekip için tek bir public kutu ile kullanıcıdan-kullanıcıya paylaşımı, doveadm ile denetlenebilir biçimde nasıl kuracağınızı adım adım anlatıyoruz.
EvilMail Team11 Temmuz 202611 dk okuma
Bir kullanıcı Thunderbird'ün klasör listesinde Public/team klasörünü görüyor, ama üstüne tıklayınca istemci "folder does not exist" diye reddediyor. Daha kötüsü: paylaşımlı destek kutusundaki bir maili biri açıp okuyor, on dakika sonra ekipteki herkeste o mail okundu görünüyor. Ya da kullanıcıdan-kullanıcıya paylaşım açıyorsunuz, acl set sıfır hata dönüyor, ama alıcının istemcisinde klasör hiç belirmiyor.
Bu üç arızanın kök nedeni üç ayrı satırdır ve hepsi namespace/ACL katmanındadır: separator uyuşmazlığı, eksik INDEXPVT ve tanımlanmamış `acl_shared_dict`. IMAP paylaşımı bir onay kutusu değil; filesystem, index ve yetki katmanlarının aynı anda hizalanmasıdır. Bu üçünü doğru kurarsanız gerisi mekaniktir. Aşağıda ekip için tek bir public kutu ve kullanıcıdan-kullanıcıya shared paylaşımını Dovecot 2.3/2.4 üzerinde sıfırdan, doveadm ile denetlenebilir biçimde kuruyoruz.
Belirti: klasör görünüyor ama açılmıyor
Üç klasik arızayı ve kök nedenlerini önden koyalım, çünkü hata ayıklamanın yarısı doğru katmana bakmaktır:
İstemci klasörü listeliyor ama "does not exist" veriyor.
Dovecot Paylaşımlı ve Public IMAP Klasörleri: Namespace + ACL Kurulumu — EvilMail Blog
Neredeyse her zaman separator uyuşmazlığıdır. Bir namespace
separator = /
, diğeri
.
ise istemcinin gönderdiği yol Dovecot'un beklediğiyle tutmaz.
Biri okuyunca herkeste okundu görünüyor.\Seen ve diğer bayraklar ortak index'e yazılıyor demektir. Çözüm: INDEXPVT ile per-user index.
Shared namespace bomboş.acl_shared_dict tanımlı değil; Dovecot hangi kullanıcının kime ne paylaştığını hiçbir yere kaydetmiyor, dolayısıyla alıcıda listeleyemiyor.
Bu üç ayarı doğru yaptığınızda geri kalan her şey — dizin izinleri, abonelikler, hak yönetimi — düz bir kontrol listesine döner.
Üç namespace tipi ve gerçekte ne yaptıkları
Dovecot'ta her klasör bir namespace'e aittir ve üç tip vardır. Farkı somutlaştırmadan config yazmak, karanlıkta ateş etmektir.
private — kullanıcının kendi posta kutusu. inbox = yes yalnızca burada ve tüm sistemde tek bir kez bulunur. Fiziksel olarak ~/Maildir altında durur.
public — admin'in bir kez kurduğu, sunucuda tek fiziksel dizinde duran, herkesin gördüğü klasör. Bülten arşivi, ortak destek kutusu, şirket içi duyurular için idealdir. Kimsenin Maildir'ine bağlı değildir; /var/mail/public gibi bağımsız bir yolda yaşar.
shared — A kullanıcısının kendi klasörünü ACL ile B'ye açması. Fiziksel olarak dosyalar A'nın Maildir'inde durur; B'nin istemcisinde bir prefix (Shared/alice/) altında bindirilmiş görünür. Hiçbir dosya kopyalanmaz.
Her namespace bloğunda beş alan işin kalbidir: prefix istemcide görünen yol önekini, separator hiyerarşi ayıracını, location sunucudaki fiziksel yeri ve index/control stratejisini, list klasörün listelenip listelenmeyeceğini, subscriptions ise abonelik takibinin nerede tutulacağını belirler.
ACL eklentisini devreye almak
Bunsuz hiçbir şey paylaşılmaz. mail_plugins satırına acl, IMAP protokolüne imap_acl eklemeniz, sonra acl = vfile kurmanız gerekir. 10-mail.conf ve 20-imap.conf içinde:
acl_shared_dict olmadan kullanıcıdan-kullanıcıya paylaşım çalışmış gibi görünür ama çalışmaz: doveadm acl set başarılı döner, ACL dosyası diske yazılır, fakat Dovecot "kim kime ne paylaştı" bilgisini hiçbir yere kaydetmediği için alıcının shared namespace'i boş kalır. Bu tek satır, en çok zaman kaybettiren tuzaktır. Çok kullanıcılı yoğun sistemlerde dosya kilidi darboğaz yaparsa dict:proxy:... ile SQLite/sözlük sunucusuna geçebilirsiniz; tek sunucuda file: gayet yeterlidir.
Burada iki ayrı ACL mekanizmasını karıştırmayın. Per-mailbox ACL, ilgili Maildir klasörünün kökündeki dovecot-acl dosyasıdır ve yalnızca o klasöre özeldir. Global ACL ise acl = vfile:/etc/dovecot/global-acls:cache_secs=300 ile tanımlanan, tüm eşleşen klasörlere uygulanan merkezi dosyadır. Public klasörler için genelde per-mailbox dovecot-acl, sistem geneli politikalar için global dosya kullanılır.
Değişikliği uygularken ayrım önemlidir: ACL içeriği değiştiğinde doveadm reload yeterlidir; ama namespace ekleyip silerken tam yeniden başlatma şarttır — systemctl restart dovecot. Sonrasında dovecot -n ile efektif konfigürasyonu daima doğrulayın.
Public klasör: ekip için tek ortak kutu
Senaryo: /var/mail/public/team altında tüm ekibin okuyabildiği, sadece adminin yazabildiği bir arşiv. Önce fiziksel dizin ve sahiplik:
Sahiplik vmail (uid/gid 5000:5000) olmalı; aksi halde Dovecot dizine yazamaz ve klasör yaratımı sessizce başarısız olur. Namespace bloğu (10-mail.conf):
namespace public {
type = public
separator = /
prefix = Public/
location = maildir:/var/mail/public:INDEXPVT=~/Maildir/public:CONTROL=~/Maildir/public
subscriptions = yes
list = yes
}
Buradaki iki nokta işin özüdür. INDEXPVT=~/Maildir/public her kullanıcının \Seen/\Flagged durumunu kendi Maildir'inde tutar; ortak dizinde herkes birbirinin okundu işaretini ezmez. CONTROL=~/Maildir/public ise abonelik ve keyword dosyalarını per-user yapar, böylece Ali klasöre abone olurken Veli olmayabilir.
Yani kimliği doğrulanmış herkes okuyabilir (l lookup, r read, s write-seen), sadece admin tam yetkilidir. anyone yerine authenticated kullanmak kimliksiz erişimi kapatır — public klasörlerde neredeyse her zaman istediğiniz budur.
Kullanıcıdan-kullanıcıya shared namespace
Şimdi Ali'nin kendi Projeler klasörünü Veli'ye açabildiği yapı. Namespace bloğu:
namespace shared {
type = shared
separator = /
prefix = Shared/%%u/
location = maildir:%%h/Maildir/:INDEXPVT=~/Maildir/shared/%%u
list = children
subscriptions = no
}
%%u paylaşan kullanıcının adı, %%h onun home dizinidir (çift yüzde, çünkü Dovecot değişkeni bir kez daha genişletilecek). INDEXPVT=~/Maildir/shared/%%u yine per-user index'i garanti eder — burada ~erişen kullanıcıyı, %%u paylaşanı gösterir; yani Veli'nin, Ali'ye ait bayrak durumu Veli'nin kutusunda tutulur.
En sinsi detay list = children. Kimse size bir şey paylaşmadıysa shared namespace boştur; list = yes olsaydı istemci boş bir Shared/ düğümünü çöp gibi gösterirdi. children ile namespace ancak altında gerçek bir paylaşım varsa görünür. Paylaşımı Ali başlatır:
bash
doveadm acl set -u alice Projeler "user=veli" lookup read write insert
Bu komut iki şey yapar: Ali'nin Projeler/dovecot-acl dosyasına Veli için satır ekler ve paylaşımı acl_shared_dict'e kaydeder. İkincisi olmadan Veli'nin istemcisi Shared/alice/Projeler'i asla listeleyemez. Doğru kurulmuşsa Veli bir sonraki LIST'te klasörü görür.
ACL haklarını yönetmek: doveadm acl
Dovecot ACL'i tek harfli haklardan oluşur. Her birini ezberlemek yerine rol olarak düşünün.
Identifier tipleri: owner, user=veli, group=support, authenticated, anyone. - öneki negatif haktır ve reddeder — "herkes yazsın ama stajyer yazmasın" gibi istisnalar bununla kurulur. Günlük komutlar:
bash
# Mevcut hakları oku
doveadm acl get -u alice Projeler
# Tam katkıcı yap
doveadm acl set -u alice Projeler "user=veli" lookup read write insert expunge
# Bir hakkı geri al
doveadm acl delete -u alice Projeler "user=veli"
# "Veli neden yazamıyor?" — efektif hakları çöz
doveadm acl debug -u veli Shared/alice/Projeler
doveadm acl debug en değerli araçtır: hangi ACL dosyasının okunduğunu, hangi identifier'ın eşleştiğini ve sonuçta hangi haklara indiğini satır satır döker. Bir paylaşım "görünmüyor" derken önce bunu çalıştırın.
\Seen tuzağı, abonelikler ve doğrulama
Neden bu kadar INDEXPVT diye ısrar ediyoruz? Çünkü Dovecot varsayılan olarak mesaj bayraklarını (\Seen, \Flagged, \Answered) klasörün ortak index dosyalarına yazar. Ortak bir kutuda bu şu demektir: Ali bir maili okur, index'e \Seen düşer, Veli açtığında mail zaten okunmuş görünür. Bir destek kutusunda bu felakettir — kimse hangi talebe bakılmadığını göremez.
INDEXPVT (private index) bayrak durumunu her kullanıcının kendi Maildir'ine kaydırır. Artık \Seen per-user'dır: Ali'nin okuduğu, Veli'de okunmamış durur. Bazı ekipler tam tersini ister (paylaşımlı gelen kutusunda "biri baktıysa herkese okundu görünsün"); o durumda INDEXPVT'yi kasıtlı olarak çıkarırsınız. Karar sizindir, ama bilinçli olsun — kazara ortak index, en sık şikayet edilen davranıştır.
CONTROL ise abonelikleri per-user yapar. subscriptions = yes olan public namespace'te herkes kendi abonelik listesini tutar; subscriptions = no olan shared namespace'te paylaşım zaten ACL'den geldiği için ayrı abonelik gereksizdir. Doğrulama üç komuta iner:
bash
# Klasör gerçekten var mı, kaç mesaj?
doveadm mailbox status -u veli all 'Shared/alice/Projeler'
# Efektif haklar ne?
doveadm acl debug -u veli Shared/alice/Projeler
# İstemcinin gördüğünü ham IMAP'le teyit et
openssl s_client -connect mail.evilmail.pro:993 -quiet
# giriş sonrası:
a login [email protected] parola
b LIST "" "*"
LIST çıktısında Shared/alice/Projeler veya Public/team satırını görüyorsanız iş bitmiştir; görmüyorsanız sorun istemcide değil sunucudadır.
Kurulum kontrol listesi
mail_plugins içinde acl, IMAP protokolünde imap_acl var mı? (dovecot -n | grep acl)
Tüm namespace'lerde separatoraynı mı? Uyuşmazlık = "does not exist".
Public ve shared location'larında INDEXPVT var mı? Yoksa \Seen tüm ekibi etkiler.
Public dizin sahipliği vmail:vmail (5000:5000), izin 0700 mü?
Shared namespace'te list = children mı? Yoksa boş Shared/ düğümü çöp gösterir.
Namespace ekledikten sonra doveadm reload değil, tamsystemctl restart dovecot yapıldı mı?
doveadm acl debug ile en az bir gerçek kullanıcı üzerinden efektif haklar doğrulandı mı?
Dovecot 2.4'te bazı ayar adları yeni blok sözdizimine taşındı, ama namespace ve ACL semantiği — INDEXPVT, acl_shared_dict, hak harfleri — birebir aynı kaldı. Bu üç katmanı (filesystem, index, yetki) aynı anda hizaladığınız an, paylaşımlı klasörler istemci tarafında sıradan bir klasör kadar sıkıcı ve güvenilir çalışır. Zaten istediğiniz de tam olarak budur.