Мы — долго запрягаем, быстро ездим, и сильно тормозим.
www.lissyara.su —> статьи —> FreeBSD —> почтовые системы —> Exim+dovecot2+dspam

Настройка связки Exim и Dovecot2 c аутентификацией CRAM-MD5 + SQL quota + DSPAM + dovecot-antispam + imapsync

Автор: freeman_tnu.


У меня долгое время трудился почтовый сервер настроенный по этой статье. Но, как говориться, ничто не вечно :) По ряду многих причин было решено организовать новый сервер, в совершенно другом месте и с отличной от старого конфигурацией. От Exim-a не отказались, а агентом доставки почты был выбран Dovecot 2-й версии и причин тому достаточно:

  • поддержка форматов почтовых ящиков mbox и Maildir;
  • высокое быстродействие благодаря индексации содержимого почтовых ящиков;
  • полное соответствие стандартам IMAP;
  • возможность работы с почтовыми языками и их индексами с нескольких компьютеров, что позволяет хранить данные на кластерных файловых системах и NFS;
  • возможность расширения функционала с помощью плагинов;
  • поддержка Sieve;
  • поддержка различных хранилищ аутентификационной информации и режимов аутентификации;
  • Postfix и Exim могут проводить аутентификацию пользователей через Dovecot;
  • простота миграции с большинства других IMAP и POP3 серверов.

    Немаловажным в настройке было хранение зашифрованных паролей в MySQL и поддержка механизма аутентификации CRAM-MD5. В качестве спам-фильтра остановился на DSPAM, благодаря которому одним гениальным германским студентом был написан плагин для интеграции с Dovecot-ом, его основная фишка - обучение/переобучение DSPAM посредством простого перемещения писем из/в imap-папки Spam. Также будут настроенны квоты на размер почтового ящика и отправка уведомлений о пороге квоты пользователю. Ну и последней заметкой статьи будут описаны нюансы ускорения работы с перловым скриптом синхронизации почтовых ящиков imapsync при переходе со старого сервера.

    Все будет устанавливаться на FreeBSD 9.1-RELEASE, предварительно обновив порты. База пользователей MySQL используется  из postfixadmin-2.3.6, установленного из портов.

    Установку и настройку начнем с Dovecot:
    # cd /usr/ports/mail/dovecot2
    # make install clean
    # dovecot --version
    2.1.15

    Параметры сборки оставлены по умолчанию, выбрав только MySQL.

    Для поддержки работы Sieve-фильтров (в том же Roundcube) необходимо установить еще один порт:
    # cd /usr/ports/mail/dovecot2-pigeonhole
    # make install clean

    Устанавливаем dovecot-antispam плагин
    # cd /usr/ports/mail/dovecot2-antispam-plugin/
    # make install clean

    Конфигурационный файл dovecot-а второй версии в отличии от первого разбит на много отдельных конфигов, относящихся к настройке того или иного сервиса, мне это показалось удобным, поэтому наберемся терпения и приступим к их редактированию (все они лежат в одном каталоге /usr/local/etc/dovecot, комментарии будут минимальны, т.к. они хорошо задокументированы в самих файлах, здесь на сайте и на оф. вики). Настоятельно рекомендую не копипастить, т.к. многие закоментированные опции не приведены здесь, отображено только то, что я включил в конфиги, поэтому вдумчиво редактируйте свои конфиги по умолчанию:

    Основной конфигурационный файл /usr/local/etc/dovecot/dovecot.conf
    # Какие протоколы будут работать
    protocols = imap pop3 
    # Список интерфейсов, обрабатывающих подключения
    listen = *
    # Каталог, в котором работает Dovecot
    base_dir = /var/run/dovecot/
    # Приветственное сообщение
    login_greeting = IMAP server ready.
    # Информативность заголовка процесса
    verbose_proctitle = no
    # Завершение всех процессов Dovecot после завершения главного
    shutdown_clients = yes
    dict {
    }
    # Подключаем остальные конфиги из каталога conf.d
    !include conf.d/*.conf
    !include_try local.conf
    

    Файл подключения к базе данных /usr/local/etc/dovecot/dovecot-sql.conf.ext
    # Тип используемой СУБД
    driver = mysql
    # Строка подключения к БД
    connect = host=localhost dbname=exim user=exim password=eximsecretpass
    # Схема хранения паролей
    default_pass_scheme = CRAM-MD5
    # Запрос, возвращающий пароль
    password_query = SELECT `username` as `user`, `password` FROM  \
    `mailbox` WHERE `username` = '%n@%d' AND `active`='1'
    # Запрос, возвращающий инфу о юзере и проверяющий квоту
    user_query = SELECT CONCAT('/var/mail/exim/', `domain`, '/', `maildir`) \
    AS `home`, 26 AS `uid`, 26 AS `gid`, concat('dict:storage=', \
    CAST(ROUND(quota / 1024) AS CHAR), '::proxy::sqlquota') \
    AS quota, CONCAT('*:storage=', CAST(quota AS CHAR), 'B') AS quota_rule \
    FROM `mailbox` WHERE `username` = '%n@%d' AND `active`='1'
    

    Файл словаря SQL квот /usr/local/etc/dovecot/dovecot-dict-sql.conf.ext
    # Строка подключения к БД
    connect = host=localhost dbname=exim user=exim password=eximsecretpass
    # Описание полей и указание таблицы quota2, 
    # именно эта таблица используется для Dovecot 2-й версии
    map {
      pattern = priv/quota/storage
      table = quota2
      username_field = username
      value_field = bytes
    }
    map {
      pattern = priv/quota/messages
      table = quota2
      username_field = username
      value_field = messages
    }
    

    Файл аутентификации /usr/local/etc/dovecot/conf.d/10-auth.conf
    
    # Пока настраивал оставил включенным PLAIN тип аутентификации
    disable_plaintext_auth = no
    # Отключаем кэш аутентифкации
    auth_cache_size = 0
    # Список разрешенных символов в имени пользователя
    auth_username_chars = abcdefghijklmnopqrstuvwxyzAB \
    CDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
    # Преобразование формат имени пользователя в нижний регистр
    auth_username_format = %Lu
    # Максимальное количество работающих процессов аутентификации
    auth_worker_max_count = 30
    # Количество секунд перед повторной аутентификацией
    auth_failure_delay = 2 secs
    # Отказать в аутентификации, если у клиента неверный SSL сертификат
    auth_ssl_require_client_cert = no
    # Не брать имя пользователя из SSL сертификата 
    auth_ssl_username_from_cert = no
    # Список разрешенных методов аутентификации
    auth_mechanisms = plain login cram-md5
    # Включить конфиг аутентификации для SQL пользователей 
    !include auth-sql.conf.ext
    

    Файл /usr/local/etc/dovecot/conf.d/auth-sql.conf.ext
    passdb {
      driver = sql
    
      args = /usr/local/etc/dovecot/dovecot-sql.conf.ext
    }
    
    userdb {
      driver = sql
      args = /usr/local/etc/dovecot/dovecot-sql.conf.ext
    }
    

    Файл настройки логирования /usr/local/etc/dovecot/conf.d/10-logging.conf
    
    # Путь к основному лог файлу
    log_path = /var/log/dovecot/mainlog
    # Логировать неудачные попытки входа
    auth_verbose = yes
    # Не выводить при этом в лог пароли
    auth_verbose_passwords = no
    # На момент настройки лучше включить более подробное логирование
    auth_debug = yes
    mail_debug = yes
    # Возможность добавлять плагины mail_log
    plugin {
    }
    

    Файл путей к ящикам и пространства имен /usr/local/etc/dovecot/conf.d/10-mail.conf
    
    # Расположение почтовых ящиков
    mail_home = maildir:/var/mail/exim/%d/%u/mail
    mail_location = maildir:/var/mail/exim/%d/%u
    # Разделяемое пространство имен для имап каталога INBOX
    namespace inbox {
      inbox = yes
    }
    # Системные пользователь и группа для доступа
    # к почтовым ящикам
    mail_uid = mailnull
    mail_gid = mail
    # Группа для привилегированных операций
    mail_privileged_group = mail
    # Не предоставлять клиентам полный доступ к файловой системе
    mail_full_filesystem_access = no
    # Не использовать системный вызов mmap()
    mmap_disable = no
    # Использовать флаг O_EXCL, когда создаются файлы блокировки (dotlock)
    dotlock_use_excl = yes
    # Использовать системные вызовыfsync() или fdatasync() при необходимости
    mail_fsync = optimized
    # NFS  я не использую
    mail_nfs_storage = no
    # Метод блокировки индексов
    lock_method = fcntl
    # Временная директория входящих сообщений размером более 128Кб
    mail_temp_dir = /var/tmp
    # Допустимые диапазоны UID для пользователей и групп
    first_valid_uid = 26
    first_valid_gid = 26
    # Каталог, в котором лежат плагины Dovecot-а
    mail_plugin_dir = /usr/local/lib/dovecot
    # Список подключаемых плагинов
    mail_plugins = $mail_plugins quota
    # Во время копирования письма создавать жесткую ссылку
    # для увеличения производительности
    maildir_copy_with_hardlinks = yes
    # Хэш функция для генерации имен файлов вложений
    mail_attachment_hash = %{sha1}
    

    Файл сервисов и сокетов /usr/local/etc/dovecot/conf.d/10-master.conf
    
    # Ограничение числа процессов
    default_process_limit = 100
    default_client_limit = 1000
    # Внутренний пользователь для процесса логона
    default_login_user = dovenull
    # Внутренний пользователь для непривилегированных процессов
    default_internal_user = dovecot
    # Секция сервиса имап логона
    service imap-login {
      inet_listener imap {
        port = 143
      }
      inet_listener imaps {
        port = 993
        ssl = yes
      }
    # Количество активный соединений
      service_count = 1
    # Количество процессов, ждущих соединений
      process_min_avail = 3 
    #  Количество памяти на 1 соединение (service_count)
      vsz_limit = 64M
    }
    # Секция сервиса поп3 логона
    service pop3-login {
      inet_listener pop3 {
        port = 110
      }
      inet_listener pop3s {
        port = 995
        ssl = yes
      }
    }
    # Параметры сетевого сокета
    service lmtp {
      unix_listener lmtp {
    #mode = 0666
      }
    
    }
    # Сервис имап
    service imap {
    # память для вложений
      vsz_limit = 256M
    # Макс. количество процесов обрабатывающих имап подключения
      process_limit = 128
    }
    # Сервис поп3
    service pop3 {
      process_limit = 256
    }
    # Сервис аутентификации
    service auth {
      unix_listener auth-userdb {
        mode = 0666
        user = mailnull
        group = mail
      }
        unix_listener auth-client {
        mode = 0600
        user = mailnull
        group = mail
      }
      user = $default_internal_user
    }
    # Сервис воркера
    service auth-worker {
      user = $default_internal_user
    }
    # Сервис обслуживания и оповещения о пользовательской квоте
    service quota-warning {
    # Скрипт, который отсылает письмо о превышении квоты пользователю
    # написан по примеру из оф. вики http://wiki2.dovecot.org/Quota/Configuration
    # его содержимое представлено ниже
      executable = script /usr/local/etc/dovecot/overquoted
      unix_listener quota-warning {
        user = mailnull
        group = mail
        mode = 0777
      }
    }
    # Сокет dict proxy для слежения за квотами
    service dict {
      unix_listener dict {
        mode = 0600
        user = mailnull
        group = mail
      }
    }
    

    Файл настройки SSL /usr/local/etc/dovecot/conf.d/10-ssl.conf
    
    # Включаем поддержку
    ssl = yes
    # SSL сертификаты у меня были готовые
    # Для создания сертификатов можно использовать следующий скрипт
    # http://dovecot.org/doc/mkcert.sh предварительно изменив пути к файлам
    ssl_cert = </usr/local/etc/exim/exim.crt
    ssl_key = </usr/local/etc/exim/exim.pem
    # Не проверять сертификат пользователя
    ssl_verify_client_cert = no
    # Используемые типы шифров
    ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL
    

    Файл мастер сокета аутентификации для доставки корреспонденции /usr/local/etc/dovecot/conf.d/15-lda.conf
    
    # ящик постмастера
    postmaster_address = mailer-daemon@domain.com.ua
    # Доменное имя Вашего сервера
    hostname = mx.domain.com.ua
    # Если превышена квота - отправлять отлуп
    quota_full_tempfail = no
    # Отправлять письма через указанный параметр вместо утилиты sendmail
    submission_host = localhost:25
    # Автоматически создавать несуществующие имап папки
    # при приему на них почты
    lda_mailbox_autocreate = yes
    # автоматически подписываться на них
    lda_mailbox_autosubscribe = yes
    # Сам протокол доставки
    protocol lda {
    # Добавляем плагин фильтров и квот
      mail_plugins = $mail_plugins sieve quota
        log_path =
      info_log_path =
      syslog_facility = mail
    }
    

    Файл протокола IMAP /usr/local/etc/dovecot/conf.d/20-imap.conf
    
    protocol imap {
    # максимальное количество соединений, разрешенных
    # с каждого IP адреса
      mail_max_userip_connections = 5
    # Подключаем плагин имап квоты и dovecot-antispam плагин
      mail_plugins = $mail_plugins imap_quota antispam
    # Формат логов
      imap_logout_format = bytes=%i/%o
    # Время ожидания ответа от клиента
      imap_idle_notify_interval = 2 mins
    }
    

    Файл параметров ManageSieve /usr/local/etc/dovecot/conf.d/20-managesieve.conf
    
    # Включение ManageSieve
    protocols = $protocols sieve
    service managesieve-login {
      inet_listener sieve {
    # Порт, на котором будет запущен сервис
        port = 4190
      }
    # Количество активных соединений
    # подробнее здесь http://wiki2.dovecot.org/LoginProcess
      service_count = 1
    # Память на одно соединение
      vsz_limit = 64M
    }
    service managesieve {
    }
    protocol sieve {
    # максимальное количество соединений, разрешенных
    # с каждого IP адреса
      mail_max_userip_connections = 5
    # Формат логов
      managesieve_logout_format = bytes=%i/%o
    # Указываем фиктивную версию ManageSieve для клиентов, т.к.
    # не все правильно работают с реализацией Sieve от Dovecot
      managesieve_implementation_string = Cyrus timsieved v2.2.13
    # количество попыток компиляций скрипта sieve, который
    # отправляет клиент.
      managesieve_max_compile_errors = 5
    }
    

    Файл протокола POP3 /usr/local/etc/dovecot/conf.d/20-pop3.conf
    
    protocol pop3 {
    # Блокирование ящика на время pop3  сессии
      pop3_lock_session = yes
    # максимальное количество соединений, разрешенных
    # с каждого IP адреса
      mail_max_userip_connections = 5
    }
    

    Файл настройки квот /usr/local/etc/dovecot/conf.d/90-quota.conf
    
    plugin {
    # Когда и сколько слать ворнингов пользователю
      quota_warning = storage=100%% quota-exceeded 100 %u
      quota_warning2 = storage=95%% quota-warning 95 %u
      quota_warning3 = storage=90%% quota-warning 90 %u
      quota_warning4 = storage=85%% quota-warning 85 %u
      quota_warning5 = storage=80%% quota-warning 80 %u
      quota_warning6 = storage=75%% quota-warning 75 %u
      quota_warning7 = storage=70%% quota-warning 70 %u
      quota_warning8 = storage=65%% quota-warning 65 %u
    }
    plugin {
    # Откуда брать инфу о квоте, в нашем случаем из MySQL словаря
            quota = dict:User quota::noenforcing:proxy::sqlquota
    # Правила ограничения по размеру мейлдира
            quota_rule = *:storage=1G
    # Для корзины добавляем + 100 мб сверх квоты
            quota_rule2 = Trash:storage=+100M
    # Игнорируем каталог со спамом (он будет очищаться скриптом,
    # удаляя весь спам старше 30 дней)
            quota_rule3 = Junk:ignore
    }
    # Описываем SQL словарь
    dict {
      sqlquota = mysql:/usr/local/etc/dovecot/dovecot-dict-sql.conf.ext
    }
    

    Файл настройки фильтров Sieve /usr/local/etc/dovecot/conf.d/90-sieve.conf
    
    plugin {
    # Месторасположения файла и каталога с правилами фильтров
      sieve = /var/mail/exim/%d/%u/.dovecot.sieve
      sieve_dir = /var/mail/exim/%d/%u/sieve
    # Макс. размер скрипта фильтрации
      sieve_max_script_size = 1M
    # Макс. количество действий в фильтре
      sieve_max_actions = 32
    # Макс. количество редиректов в фильтре
      sieve_max_redirects = 8
    # Макс. количество скриптов самих фильтров
      sieve_quota_max_scripts = 30
    }
    

    Файл настройки плагинов, в нашем случае настраиваем подключенный dovecot-antispam (также в этом файле можно настроить любой другой подключаемый плагин) /usr/local/etc/dovecot/conf.d/90-plugin.conf
    
    plugin {
    # Указываем наш бэкенд
    antispam_backend = dspam 
    # Задаем параметры обучения hum-а для DSPAM
    antispam_dspam_notspam = --class=innocent
    # Задаем параметры обучения spam-а для DSPAM
    antispam_dspam_spam = --class=spam 
    # Обозначаем каталог спама
    antispam_spam = JUNK;Junk;junk
    # Обозначаем каталог корзины
    antispam_trash = trash;Trash;Deleted Items;Deleted Messages
    antispam_spam_pattern_ignorecase = Junk;Junk.*
    antispam_trash_pattern_ignorecase = Trash;Deleted Items;Deleted Messages
    # Какой хидер и подпись использовать для определения спамового письма
    antispam_dspam_result_header = X-DSPAM-Result
    antispam_signature = X-DSPAM-Signature
    # Что делать с письмом после переобучения:
    # в нашем случаем перемещать в указанный каталог
    antispam_signature_missing = move
    # Путь к бинарнику DSPAM
    antispam_dspam_binary = /usr/local/bin/dspam
    # Параметры обучения
    antispam_dspam_args = --user;%u;--deliver=;--source=error;--signature=%%s
    }
    

    Содержимое скрипта /usr/local/etc/dovecot/overquoted для отправки квот, указанного в конфиге /usr/local/etc/dovecot/conf.d/10-master.conf
    
    #!/usr/local/bin/bash
    PERCENT=$1
    USER=$2
    SUBJECT="=?UTF-8?B?$(echo "$SUBJECT" | base64 -w0)?="
    # Этот текст у себя пишите в одну строку
    cat << EOF | /usr/local/libexec/dovecot/dovecot-lda -d $USER -o \
    "plugin/quota=maildir:User quota:noenforcing"
    
    MIME-Version: 1.0
    From: Administrator <free_m@camion.com.ua>
    Subject: Вы исчерпали квоту почтового ящика на $PERCENT%
    Content-Type: text/plain; charset=UTF-8;format=flowed
    Content-Transfer-Encoding: 8bit
    
    Доступное пространство Вашего ящика исчерпано на $PERCENT%.
    EOF
    

    Ну вот вроде бы и закончили с конфигами Dovecot-а, аж не вериться :) Теперь для автостарта довекота добавляем в rc.conf
    # echo 'dovecot_enable="YES"' >> /etc/rc.conf

    Запускаем и проверяем
    # /usr/local/etc/rc.d/dovecot start
    # sockstat -4 -l | grep dovecot
    root dovecot 42460 15 tcp4 *:4190 *:*
    root dovecot 42460 24 tcp4 *:110 *:*
    root dovecot 42460 25 tcp4 *:995 *:*
    root dovecot 42460 32 tcp4 *:143 *:*
    root dovecot 42460 33 tcp4 *:993 *:*

    Итак, проверим работу dovecot на примере POP3
    # telnet localhost 110
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    +OK IMAP server ready.
    user username@domain.com.ua
    +OK
    pass yoursecretpass
    +OK Logged in.
    stat
    +OK 3006 380337139
    quit
    +OK Logging out.
    Connection closed by foreign host.

    Если что-то пошло не так, смотрим лог tail -f /var/log/dovecot/mainlog и исправляем ошибки.


    Во время настройки DSPAM столкнулся с фичей нехватки прав на бинарник DSPAM и его конфигурационный файл после установки. По умолчанию в файле Makeconf порта DSPAM указаны параметры сборки с владельцем root, когда я первый раз установил порт, то напролося на кучу ошибок в логах Dovecot-a о нехватке прав на запуск DSPAM. Поэтому, чтобы избежать не нужных нам проблем, перед установкой добавьте в /etc/make.conf следующее
    DSPAM_OWNER=mailnull
    DSPAM_GROUP=mail
    DSPAM_HOME_OWNER=mailnull
    DSPAM_HOME_GROUP=mail
    

    Саму установку и настройку DSPAM я делал по этой статье

    Установку и настройку EXIM с пользователями в MySQL описывать не буду, т.к. здесь есть множество статей на эту тему, остановлюсь только на настройке роутеров и транспорта для Dovecot, DSPAM а также аутентификации CRAM-MD5.

    Роутеры проверки спама, необходимо вставить перед роутером локальной доставки Dovecot, это очень важно! Итак правим конфиг екзима /usr/local/etc/exim/configure
    В секции begin routers после роутера system_aliases добавляем следующее:
    # DSPAM ROUTERS
    dspam_spamscan_router:
      driver = accept
      domains                      = +local_domains
      no_verify
      condition = "${if and {{!eq {$received_protocol}{spam-scanned}} \
                    {!eq {$received_protocol}{local}} } {1}{0}}"
      transport = dspam_spamcheck_transport
      require_files = /usr/local/bin/dspam
      address_test = false
      user = mailnull
      group = mail
    
    local_delivery_spam_router:
      driver                       = accept
      domains                      = +local_domains
      condition                    = ${if match{$h_X-DSPAM-Result:}{Spam}}
      transport                    = local_delivery_spam_transport
      no_more
      user = mailnull
      group = mail
    
    # LOCAL DELIVERY
    dovecot_user:
      driver = accept
      condition = ${lookup mysql{SELECT `goto` FROM \
      `alias` WHERE \
      `address`='${quote_mysql:$local_part@$domain}' OR \
      `address`='${quote_mysql:@$domain}'}{yes}{no}}
      transport = dovecot_delivery
    

    В секции begin transports порядок добавления не важен, просто вставляем:
    dovecot_delivery:
      driver = pipe
      command = /usr/local/libexec/dovecot/deliver -d $local_part@$domain
      message_prefix =
      message_suffix =
      delivery_date_add
      envelope_to_add
      return_path_add
      log_output
      user = mailnull
    
    # DSPAM TRANSPORT
    dspam_addspam_transport:
      driver = pipe
      command = "/usr/local/bin/dspam --user \
                    $local_part@$domain --class=spam --source=error"
      return_path_add = false
      return_fail_output = true
      log_output = true
      home_directory = "/var/db/dspam"
      current_directory = "/var/db/dspam"
      user = mailnull
      group = mail
    
    dspam_notspam_transport:
      driver = pipe
      command = "/usr/local/bin/dspam --user \
                    $local_part@$domain --class=innocent \
                    --source=error --deliver=innocent %u"
      return_path_add = false
      return_fail_output = true
      log_output = true
      home_directory = "/var/db/dspam"
      current_directory = "/var/db/dspam"
      user = mailnull
      group = mail
    
    dspam_spamcheck_transport:
      driver = pipe
      command = /usr/local/bin/dspam --deliver=innocent \
                    --user "$local_part@$domain" -- %u
      user = mailnull
      group = mail
      return_path_add = false
      log_output = true
      return_fail_output = true
      headers_remove        = X-DSPAM-Result
    
    local_delivery_spam_transport:
      driver = pipe
    # Команда перемещения писем распознанных как спам в каталог спама
    # у меня этот каталог Junk
      command = /usr/local/libexec/dovecot/deliver -d \
                    $local_part@$domain -m Junk
      message_prefix =
      message_suffix =
      delivery_date_add
      envelope_to_add
      return_path_add
      log_output
      user = mailnull
    

    Аутентификация у меня работает через Dovecot, правим секцию begin authenticators
    dovecot_login:
    driver = dovecot
    public_name = LOGIN
    server_socket = /var/run/dovecot/auth-client
    server_set_id = $auth1
    
    dovecot_plain:
    driver = dovecot
    public_name = PLAIN
    server_socket = /var/run/dovecot/auth-client
    server_set_id = $auth1
    
    dovecot_cram_md5:
    driver = dovecot
    public_name = CRAM-MD5
    server_socket = /var/run/dovecot/auth-client
    server_set_id = $auth1
    

    Настройка Exim закончена.

    Теперь, к примеру, если Вы получили письмо, которое является заведомо спамом, но попало  по ошибке фильтра во входящие, то чтобы переучить спамфильтр и сказать ему, что это письмо спамовое, достаточно просто переместить его в папку Спам(Junk) и после этого в логе соответствующего пользователя появиться запись свидетельствующая о переобучении спам-фильтра
    # tail -f /var/db/dspam/data/username@domain.com.ua/username@domain.com.ua.log

    1369209224 I spammail@pisem.net 519c7988278601581114498 dddddd Delivered <2afbf94cd4594c6f22610d8c18fc63cad334e4c2@mail.qip.ru>

    1369209324 M <None Specified> 519c7988278601581114498 <None Specified> Retrained

    А если письмо снова вернуть во Входящие, то письмо будет считаться не спамом.


    Пользователей в базе я создаю из веб-панели postfixadmin, оттуда пароли автоматически криптуются в CRAM-MD5. Есть одна важная особенность в конфиге postfixadmin, касающаяся именно второй версии Dovecot, это путь к бинарнику создания криптованого пароля для пользователя, в отличии от первой версии Dovecot используется другой бинарник с параметрами. Вот собственно параметры конфига, отвечающие за вышесказанное:
    $CONF['encrypt'] = 'dovecot:CRAM-MD5';
    $CONF['authlib_default_flavor'] = 'md5raw'
    $CONF['dovecotpw'] = "/usr/local/bin/doveadm pw";
    

    Аутентификацию по механизму CRAM-MD5 можно проверить из того же Roundcube, вот кусок лога довекот:
    # tail -f /var/log/dovecot/mainlog
    May 24 13:48:59 auth: Debug: auth client connected (pid=42864)
    May 24 13:48:59 auth: Debug: client in: AUTH 1 CRAM-MD5 service=imap secured session=HWXci3TdfgBOLsbU lip=1.2.3.4 rip=1.2.3.4 lport=993 rport=10878
    May 24 13:48:59 auth: Debug: client passdb out: CONT 1 PDI2NzU0ODY2Mjg3MTE0MjguMTM2OTM5MjUzOUBteHZtLm1hbmZyZWUua2lldi51YT4=
    May 24 13:48:59 auth: Debug: client in: CONT<hidden>
    May 24 13:48:59 auth-worker(42818): Debug: sql(username@domain.com.ua,1.2.3.4): query: SELECT `username` as `user`, `password` FROM `mailbox` WHERE `username` = 'username@domain.com.ua' AND `active`='1'
    May 24 13:48:59 auth: Debug: client passdb out: OK 1 user=username@domain.com.ua
    May 24 13:48:59 auth: Debug: master in: REQUEST 3470262273 42863 1 a88e3cf4ba52caee8dae888e230985b6
    May 24 13:48:59 auth: Debug: master userdb out: USER 3470262273 username@domain.com.ua home=/var/mail/exim/domain.com.ua/username@domain.com.ua/ uid=26 gid=26 quota=dict:storage=100000::proxy::sqlquota quota_rule=*:storage=102400000B
    May 24 13:48:59 auth-worker(42818): Debug: sql(username@domain.com.ua,1.2.3.4): SELECT CONCAT('/var/mail/exim/', `maildir`) AS `home`, 26 AS `uid`, 26 AS `gid`, concat('dict:storage=', CAST(ROUND(quota / 1024) AS CHAR), '::proxy::sqlquota') AS quota, CONCAT('*:storage=', CAST(quota AS CHAR), 'B') AS quota_rule FROM `mailbox` WHERE `username` = 'username@domain.com.ua' AND `active`='1'
    May 24 13:48:59 imap-login: Info: Login: user=<username@domain.com.ua>, method=CRAM-MD5, rip=1.2.3.4, lip=1.2.3.4, mpid=42866, TLS, session=<HWXci3TdfgBOLsbU>

    Как видно из лога все прошло без ошибок.

    Переходя на новый сервер, необходимо переместить все пользовательские ящики, таким образом, чтобы мейлдиры после Courier-а лягли в структуру Dovecot, сразу начал читать оф. вики довекота http://wiki2.dovecot.org/Migration/Courier но процедура оказалась слишком монструозной и длительной. Я решил отказаться от такого метода и вспомнил про перловый скрипт imapsync, как оказалось не напрасно. Нагуглил красивое решение для массовой синхронизации всех почтовых ящиков, выдергивая в цикле логины и пароли пользователей из базы старого сервера (соединяться с базой можна по сети либо импортнуть ее на новый сервер под другим именем). На новом сервере перед синхронизацией все пользователи должны быть созданы предварительно либо скриптом, либо вручную, т.к. пароли в базу будут ложиться в криптованом виде. Я у себя создал вручную, по причине небольшого количества пользователей. Вот сам скрипт:
    #! /usr/bin/perl
    #Параметры MySql
    $dbuser = 'user';
    $dbpass = 'password';
    $db = 'database';
    $dbhost = 'localhost';
    $domain = 'domain.com.ua';
    #Параметры Courier
    $server = '192.168.0.1';
    $domain1 = 'domain.com.ua';
    
    use DBI;
    #Создаем SQL запрос
    #login - логин пользователя без указания домена (например vova)
    #decrypt - пароль почтового ящика в открытом виде
    #domain - почтовый домен пользователя (domain.com.ua)
    #status - признак активности пользователя
    $query = 'SELECT login, decrypt FROM users WHERE \
     domain=\''.$domain.'\' AND status=\'1\'';
    #Подключаемся к базе данных
    $dbh = DBI->connect("DBI:mysql:database=$db;host=$dbhost",$dbuser, \
    $dbpass) || die print "Can't connect";
    #Выполняем SQL запрос
    $sth = $dbh->prepare(qq{$query});
    $sth -> execute;
    # Выполняем синхронизацию
    # делать выборку данных
    # пока ничего не останется
    while (my ($m_user, $m_pass) = $sth->fetchrow_array())
            {
    $user1=$m_user.'@'.$domain1;
    $user2=$m_user.'@'.$domain;
           #Сообщаем, над каким ящиком трудимся в данный момент
            print "Syncronize mail for ".$user2."\n";
    $r_sync=`imapsync --host1 $server --user1 $user1 --password1 $m_pass \
    --host2 $dbhost --user2 $user2 --password2 $m_pass`;
    
    }
    $sth->finish();
    $dbh->disconnect();
    exit;
    

    Тестовая синхронизация двух ящиков суммарным объемом 900мб заняла очень большое время - порядка 2 часов, поэтому почитав фак на страничке разработчика я добавил в строку синхронизации кеширование, отменил подсчет размера папок и изменил временный каталог для кэша в итоге кусок скрипта отвечающий за imapsync выглядит так:

    $r_sync=`imapsync --host1 $server --user1 $user1 --password1 $m_pass --host2 $dbhost --user2 $user2 --password2 $m_pass` --authmech2 CRAM-MD5 --tmpdir /var/tmp --nofoldersizes --usecache;

    Вторичный запуск синхронизации рекомендуется запускать вместо --usecache с параметром --useuid - собственно для использования построенных индексов в кеше:

    $r_sync=`imapsync --host1 $server --user1 $user1 --password1 $m_pass --host2 $dbhost --user2 $user2 --password2 $m_pass` --authmech2 CRAM-MD5 --tmpdir /var/tmp --nofoldersizes --useuid;

    Вот собственно и все, чем я хотел поделиться с общественностью, т.к. сам в свое время не нашел в едином месте материала объединяющего все моменты и нюансы настройки данной связки.

    Используемые материалы:
    http://wiki2.dovecot.org/
    http://www.lissyara.su/
    http://www.info-x.org
    http://extmemory.blogspot.com/2009/10/imapsync.html



    размещено: 2013-05-23,
    последнее обновление: 2014-05-05,
    автор: freeman_tnu


    Олег М., 2013-09-20 в 15:43:59

    Сегодня настраиваю по вашей инструкции сервер, не смотря на то что статья относительно недавняя и версия FreeBSD 9.1 тоже, очень много изменения в обновленных портах, особенно в Dovecot.
    Хочу попросить автора дописать в статье как именно он устанавливал и настраивал неописанные выше порты, для опытных людей в этом нету особого смысла но для новичков вроде меня это важно. Очень удобно когда настраиваешь все по одному источнику, а не собираешь конструктор из кучи инструкций написанных разными людьми и для разных целей, после такого долго приходится искать где ошибка и как ее устранить.
    Заранее спасибо и спасибо за уже написанную статью.

    freeman_tnu, 2013-09-20 в 16:22:19

    Какие именно порты Вас интересуют? т.к. Dovecot был собран с опциями по умолчанию, кроме включения mysql.
    И лучше обсуждать это в форуме

    Олег М., 2013-09-30 в 0:41:21

    Добавь ссылку на полный конфиг Exim (хотя бы без описания) и на базу MySQL

    freeman_tnu, 2013-09-30 в 11:21:44

    У меня конфиг один в один как в этой статье и об этом я тут упомянул. База используется из postfixadmin(создается автоматически при установке админки из веб-странички), о чем я тоже тут писал. Единственное изменение конфига exim это добавление роутеров, транспорта dovecot и аутентификации, смотрите  здесь я описал как и куда их вставлять. Просто я не вижу смысла плодить одинаковые статьи, у Лисяры в статье все описано досконально.

    Олег М., 2013-10-09 в 3:13:02

    Как правильно разрешить отправку почты удаленным пользователям? Провайдер закрывает 25 порт, 465 и 587 открыты.

    freeman_tnu, 2013-10-09 в 11:12:39

    настройте ssl в exim
    http://forum.lissyara.su/viewtopic.php?f=20&t=3577&start=25#p249410

    Олег М., 2013-10-25 в 2:22:20

    freeman_tnu, будь так добр помоги уже довести до ума сервер раз уж я почти все настроил по твоей инструкции,  мне деваться теперь некуда, теперь сервер обслуживает предприятие и довести его до ума я просто обязан. Ты же не бросишь меня на произвол :-) и так по порядку, начну с самого срочного.
    1. DSPAM - строк обучения уже прошел, он принял более 1000 писем и я ему отправил свыше 250 спамовых писем на spam-321@домен.ua. Но он так и не отфильтровывает спам, при проверке выше указанным методом пишет что письмо не является спамом, хотя именно это письмо я ему в спам базу добавил. Во обработки почты в логи ничего не пишет, только когда вручную выполняю проверку.
    Судя по письму он проверку выполняет:
    Received: from mailnull by mail.домен.ua with spam-scanned (Exim 4.80.1 (FreeBSD))
    Вот лог когда в IMAP попытался мышкой перетянуть спам в папку спама:
    [code]
    imap(mail-copy-mailbox@домен.ua): Debug: dspam error: ..2632 prefix=imap(mail-copy-mailbox@домен.ua):
    Oct 25 01:18:25 imap: Error:
    Oct 25 01:18:25 imap: Error:
    Oct 25 01:18:25 imap(mail-copy-mailbox@домен.ua): Debug: dspam error: ..2632 executing /usr/local/bin/dspam failed: 13 (uid=26, gid=26)
    Oct 25 01:18:25 imap: Error:
    Oct 25 01:18:25 imap: Error:
    [/code]

    gyurza2000, 2013-12-11 в 2:17:12

    Статья конечно прикладная и интересная, для меня как, впервые осваивающего DSPAM, и вообще, не профи в UNIXах, но, именно для новичка есть много нюансов.
    Копипастом конфиг себе не закинешь - опечатки, ошибки...вобщем не всё заработает :)

    command = где то написано в кавычках, а где то нет. Как правильно?
    — %u - две чёрточки где то есть, а где то нет. А как правильно?

    Но, в конечном итоге, всё вроде бы заработало. Спаибо огромное :)

    freeman_tnu, 2013-12-11 в 13:24:00

    gyurza2000
    Я же в статье написал ;)
    "Настоятельно рекомендую не копипастить, т.к. многие закоментированные опции не приведены здесь, отображено только то, что я включил в конфиги, поэтому вдумчиво редактируйте свои конфиги по умолчанию:" (с)
    command = с кавычками и без кавычек работает, правильно оба варианта (читаем доку по конфигу экзима)
    - %u смотрите в контексте параметров запуска обучения dspam-а и Вам все станет ясно.

    gyurza2000, 2013-12-11 в 13:41:38

    freeman_tnu,автор, раз уж Вы отвечаете, зайдите пжлст в ветку обсуждения данной статьи, там на 3й стр. описана моя проблема - дублирование входящих писем и отсутствие метки SPAM в письмах, перемещаемых в папку СПАМ. Может подскажите куда копать?

    Aleksey77, 2018-04-17 в 16:09:24

    Настройка квот!!!!
           quota = dict:User quota::noenforcing:proxy::sqlquota

    Параметр noenforcing нужно убирать, из за него квоты работают в режиме мониторинга, то есть реально квота на сервере не работает.



  •  

      Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
      Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

    © lissyara 2006-10-24 08:47 MSK

    Время генерации страницы 0.0737 секунд
    Из них PHP: 45%; SQL: 55%; Число SQL-запросов: 86 шт.
    Исходный размер: 85619; Сжатая: 20333