Общая папка mailcow, где у каждого сотрудника свои отметки «прочитано»: как это настроить
Общий ящик info@ в mailcow неудобен ровно одним: письмо, открытое одним менеджером, у остальных тоже выглядит прочитанным, и заявки теряются. Решение — не общий ящик, а публичная папка Dovecot с параметром INDEXPVT, который хранит отметку «прочитано» отдельно для каждого пользователя. Показываю на кейсе рекламного агентства «Точка контакта», как это настроить: от namespace в extra.conf до прав doveadm acl — и почему популярный совет включить ACL_ANYONE=allow здесь не нужен.
Кейс «Точки контакта»: общий ящик ссорит менеджеров
Рекламное агентство «Точка контакта», 20 рабочих мест, ведёт заявки клиентов через общий адрес info@ на своём mailcow. Три менеджера подключены к этому ящику через Outlook и веб-интерфейс SOGo. Проблема была в самой природе общего ящика: как только один менеджер открывал письмо, чтобы посмотреть, чьё оно, письмо у остальных двоих тоже помечалось прочитанным. В итоге заявки иногда повисали без ответа — все считали, что её кто-то уже взял в работу, раз она не выделена жирным.
Просили решить конкретно эту проблему, не трогая остальную схему: у каждого сотрудника должна быть своя отметка «прочитано» на одних и тех же письмах в одной и той же папке. Обычная переадресация или общий IMAP-ящик такого не делают в принципе — отметка \Seen в стандартном IMAP хранится один раз на письмо, а не отдельно на пользователя. Чтобы получить нужное поведение, нужна не папка пользователя, а настоящая публичная (public) папка Dovecot с отдельным индексом для приватных флагов.
Первым порывом у клиента было завести отдельные пересылки каждому менеджеру и разбирать заявки в своих личных папках — так тоже можно, но тогда теряется общая картина: непонятно, сколько заявок в очереди прямо сейчас и кто именно взял конкретную. Публичная папка с раздельными флагами решает обе задачи сразу: письма физически в одном месте, видно всем, а персональный статус прочтения не мешает коллегам ориентироваться.
Как устроены публичные namespace в Dovecot и что даёт INDEXPVT
В mailcow общая папка настраивается не через админку, а прямым редактированием data/conf/dovecot/extra.conf — каталог data/conf/dovecot целиком примонтирован в контейнер dovecot-mailcow как /etc/dovecot, и extra.conf подключается к основному конфигу автоматически. Официальный пример из документации mailcow выглядит так:
namespace {
type = public
separator = /
prefix = Public/
location = maildir:/var/vmail/public:INDEXPVT=~/public
subscriptions = yes
mailbox "Develcow" {
auto = subscribe
}
}Ключевой параметр здесь — INDEXPVT=~/public в строке location. Он указывает Dovecot хранить индекс с приватными флагами (в первую очередь \Seen) не в общем индексе папки, а в домашнем каталоге каждого пользователя. Само письмо в публичной папке одно на всех, а вот флаг «прочитано» для него — свой у каждого. Если эта персональная отметка не нужна и вас устраивает общий статус прочтения на всех, INDEXPVT из строки можно просто убрать — так прямо и написано в документации.
subscriptions = yes вместе с блоком mailbox "Develcow" { auto = subscribe } отвечают не за флаги, а за то, чтобы новая публичная папка сразу появилась в списке подписанных у клиентов, а не пряталась в разделе «Все папки», который многие пользователи никогда не открывают.
ACL_ANYONE: почему для публичной папки его трогать не нужно
Здесь легко потратить час не туда. В mailcow.conf есть переменная ACL_ANYONE, по умолчанию disallow (в docker-compose.yml у dovecot-mailcow: ACL_ANYONE=${ACL_ANYONE:-disallow}), а в поиске по «mailcow public folder authenticated» рядом с инструкцией по публичным папкам всплывает страница документации «Enable any ACL settings» с советом прописать ACL_ANYONE=allow и сделать docker compose up -d. Многие так и делают — и открывают больше, чем собирались.
Посмотрим, что эта переменная делает на самом деле. mailcow передаёт её значение в настройку Dovecot acl_anyone, а проверяет её плагин imap-acl — и только тогда, когда идентификатор anyone или authenticated приходит от почтового клиента IMAP-командой SETACL. Проще говоря, это запрет пользователям самим расшаривать свои папки «всем авторизованным» из SOGo или Thunderbird. Комментарий в generate_config.sh говорит то же самое: включать это стоит только на сервере одной организации, иначе пользователь может поделиться данными со слишком широким кругом.
Права, которые выставляет администратор через doveadm acl set или файл dovecot-acl в корне namespace, эта проверка не затрагивает: в исходнике imap-acl-plugin.c Dovecot 2.3 отказ 'authenticated' identifier is disallowed возвращается только на IMAP-команду. Поэтому для публичной папки я оставляю ACL_ANYONE=disallow: папка работает, а сотрудники не могут случайно открыть свой личный ящик всей инсталляции.
Если папка настроена по инструкции, а пользователи её не видят, я проверяю по порядку три вещи: подхватил ли Dovecot namespace, есть ли у пользователя права и подписан ли клиент на папку:
# namespace public подхвачен?
docker compose exec dovecot-mailcow doveconf -n | grep -A6 'type = public'
# какие права реально действуют для пользователя
docker compose exec dovecot-mailcow doveadm acl rights -u user1@example.com "Public/Develcow"Пустой вывод первой команды — extra.conf не прочитан, пустые права во второй — ACL не выдан, а если обе в порядке, дело в подписке: Outlook и мобильные клиенты по умолчанию показывают только подписанные папки. Это тот же класс ошибок, что и в регламенте эксплуатации mailcow, который я веду по всем клиентским инсталляциям: сначала проверяю предварительные условия, потом уже саму команду из документации.
Настройка по шагам: extra.conf, перезапуск, права
После правки data/conf/dovecot/extra.conf перезапускаю именно dovecot-mailcow, а не весь стек — новый namespace должен быть прочитан заново при старте сервиса:
docker compose restart dovecot-mailcowИ последним шагом выдаю права всем авторизованным пользователям на эту конкретную папку — команда из документации mailcow:
docker compose exec dovecot-mailcow doveadm acl set -A "Public/Develcow" "authenticated" lookup read write write-seen write-deleted insert post delete expunge createНабор прав lookup read write write-seen write-deleted insert post delete expunge create — это полный доступ на чтение, изменение флагов (включая тот самый персональный \Seen), запись новых писем и удаление. Если нужен доступ только на чтение без права удалять письма, из списка убираю delete и expunge — Dovecot принимает права по отдельности, а не только весь набор целиком.
Отдельно создавать папку командой не нужно: auto = subscribe в блоке mailbox подразумевает и автосоздание — в Dovecot значение subscribe включает create, так что каталог в /var/vmail/public появится сам. После выдачи прав проверяю, что пользователь папку действительно видит:
docker compose exec dovecot-mailcow doveadm mailbox list -u user1@example.com 'Public/*'Осторожно с «authenticated»: это весь mailcow, а не один домен
Прежде чем раздавать права authenticated, важно понимать масштаб. В обсуждении на GitHub (issue #1677) разработчики mailcow подтвердили: «Any authenticated User» в терминологии Dovecot ACL означает всех пользователей на всей инсталляции mailcow, а не только пользователей одного домена. Если на вашем сервере обслуживается несколько компаний или брендов с разными доменами в одном mailcow (частая ситуация у небольших агентств с дочерними проектами), authenticated откроет публичную папку всем — включая почтовые ящики другого юрлица на том же сервере.
Для «Точки контакта» это было не критично: на их mailcow всего один домен и три сотрудника. Но в мультидоменных инсталляциях я вместо authenticated выдаю права точечно, через doveadm acl set -u, перечисляя конкретных пользователей вместо общего флага. Строка похожа, но действует иначе — и обратите внимание на идентификатор user=… перед списком прав: без него doveadm acl set примет первое право за идентификатор и ничего полезного не сделает. Именно такой синтаксис приводит документация mailcow:
docker compose exec dovecot-mailcow doveadm acl set -u user1@example.com "Public/Develcow" user=user1@example.com lookup read write write-seen
docker compose exec dovecot-mailcow doveadm acl set -u user2@example.com "Public/Develcow" user=user2@example.com lookup read write write-seenТак права привязаны к конкретным почтовым ящикам, и ACL_ANYONE здесь, как и в варианте с authenticated, не участвует. Список пользователей, впрочем, придётся поддерживать руками: если в компании меняются сотрудники, забытый в ACL уволенный менеджер продолжит видеть общую папку, пока кто-то явно не удалит его запись командой doveadm acl delete -u admin@example.com "Public/Develcow" user=fired@example.com. Это тот же класс проблем с забытыми правами, что и в разборе служебных файлов Dovecot — конфигурация, которую один раз настроили и забыли, рано или поздно начинает жить своей жизнью.
Что я настроил у «Точки контакта» и как проверял результат
У «Точки контакта» один домен и все три менеджера должны видеть общую папку, поэтому взял вариант с authenticated, выданным через doveadm acl set -A, — риска утечки в чужой домен там не было. ACL_ANYONE оставил в disallow. После настройки проверял не «на глаз» через клиент, а явной командой, что права реально применились:
docker compose exec dovecot-mailcow doveadm acl get -u user1@example.com "Public/Develcow"Команда показывает список ACL, применимых к конкретному пользователю на конкретной папке — если строка authenticated там есть с ожидаемым набором прав, значит ACL настроен верно. Дальше — уже поведенческая проверка: зашёл под одним менеджером в SOGo, открыл тестовое письмо в Public/Develcow, зашёл под вторым — письмо там было непрочитанным. Ради такой проверки создал третий тестовый аккаунт, а не гонял реальные заявки клиентов, пока не убедился, что флаги действительно разделены. Заодно проверил лимит одновременных IMAP-подключений — при трёх сотрудниках и веб-клиенте, и телефоном, и Outlook на одну и ту же публичную папку легко упереться в ограничение mail_max_userip_connections, если настройка оставлена по умолчанию; у «Точки контакта» запас был, но для агентства побольше я бы проверял это заранее, а не по факту жалобы на «не открывается почта».
Что стоит знать перед тем, как переносить общий ящик в публичную папку
Публичная папка — это не общий ящик info@ в привычном смысле: письма туда не попадают автоматически по факту получения на адрес info@. Нужен sieve-фильтр на ящике info@, который раскладывает входящую почту в Public/Develcow (fileinto, а с расширением copy — fileinto :copy, если копию хочется оставить и во «Входящих»); у владельца ящика при этом должно быть право insert на папку. Алиасом доставить письмо прямо в публичную папку нельзя — Postfix доставляет в ящик, а не в папку, поэтому я всегда делаю через sieve: так проще контролировать, что именно копируется и куда.
Второй момент — резервное копирование. Публичная папка физически лежит в /var/vmail/public внутри тома vmail-vol-1, том же самом, что и обычные почтовые ящики, поэтому штатный backup_and_restore.sh backup vmail захватывает её без дополнительных настроек. А вот отдельные индексы INDEXPVT лежат в домашнем каталоге каждого пользователя — это тоже часть тома vmail-vol-1, так что при восстановлении из бэкапа персональные отметки прочтения восстановятся вместе с письмами, отдельно заботиться об этом не нужно.
Третий момент, который стоит проговорить с заказчиком заранее, — что публичная папка не заменяет распределение заявок между сотрудниками, а только убирает раздражающий побочный эффект общего ящика. Кто именно должен ответить на конкретное письмо, публичная папка сама не решает: если агентству нужна полноценная маршрутизация заявок с очередью и статусами, это уже задача helpdesk-системы поверх почты, а не настройки Dovecot. У «Точки контакта» три человека и десяток заявок в день — для такого объёма публичной папки с раздельными отметками достаточно, но я сразу предупреждаю клиентов, что при росте команды до 8–10 человек имеет смысл смотреть в сторону отдельной системы обработки заявок, а не наращивать список ACL и городить самодельную логику поверх обычной почты.
Частые вопросы
Можно ли в mailcow сделать общую папку, где у каждого своя отметка «прочитано»?
Да, через публичный (public) namespace в Dovecot с параметром INDEXPVT в extra.conf. Письмо одно на всех, а флаг \Seen хранится отдельно для каждого пользователя в его собственном индексе.
Почему настроенная по инструкции публичная папка недоступна пользователям?
Чаще всего не выданы права (проверка — doveadm acl rights -u user «Public/…»), Dovecot не перечитал extra.conf после правки или клиент не подписан на папку. ACL_ANYONE=allow для папки с правами через doveadm не нужен: он разрешает пользователям самим делиться папками с anyone/authenticated по IMAP.
Опасно ли давать права на authenticated в общей mailcow-инсталляции?
Да, если на сервере несколько доменов разных компаний — authenticated означает всех пользователей всей инсталляции mailcow, а не одного домена. В мультидоменных сценариях права лучше выдавать точечно через doveadm acl set -u конкретным адресам.
Нужно ли перезапускать mailcow после правки extra.conf?
Перезапуска всего стека не требуется — достаточно перезапустить контейнер dovecot-mailcow командой docker compose restart dovecot-mailcow, чтобы Dovecot перечитал новый namespace.
Попадёт ли публичная папка в стандартный бэкап mailcow?
Да. Она физически хранится в том же томе vmail-vol-1, что и обычные ящики (каталог /var/vmail/public), поэтому backup_and_restore.sh backup vmail захватывает её без отдельной настройки, вместе с персональными индексами INDEXPVT.
Источники
- Public folders — mailcow: dockerized documentation — Проверено дословно: блок namespace в extra.conf (type=public, prefix=Public/, location с INDEXPVT), команда doveadm acl set -A, путь и содержимое файла dovecot-acl (kxeilprwts). https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-public_folder/
- Enable any ACL settings — mailcow: dockerized documentation — Проверено: страница про ACL_ANYONE=allow — речь о возможности делиться с «any»/«all authenticated users»; для публичной папки с правами через doveadm не требуется. https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-any_acl/
- docker-compose.yml, сервис dovecot-mailcow — Проверено: точное значение переменной по умолчанию ACL_ANYONE=${ACL_ANYONE:-disallow} и монтирование ./data/conf/dovecot:/etc/dovecot в контейнер. https://github.com/mailcow/mailcow-dockerized/blob/master/docker-compose.yml
- Share IMAP Folder inside SOGo with any users from the same Domain — Issue #1677 — Проверено: подтверждение, что «Any authenticated User» в Dovecot ACL mailcow действует на весь инстанс, а не на один домен. https://github.com/mailcow/mailcow-dockerized/issues/1677
- Backup — mailcow: dockerized documentation — Проверено: backup_and_restore.sh backup vmail резервирует том vmail-vol-1 целиком, включая публичные namespace. https://docs.mailcow.email/backup_restore/b_n_r-backup/
- imap-acl plugin — Dovecot 2.3 documentation и исходник imap-acl-plugin.c — Проверено: acl_anyone ограничивает только IMAP-идентификаторы anyone/authenticated (SETACL от клиента, ошибка 'authenticated' identifier is disallowed); doveadm acl и dovecot-acl не затрагивает. https://doc.dovecot.org/2.3/settings/plugin/imap-acl-plugin/



