Почтовый сервер как у провайдера, часть 1: Exim
Exim + Vexim + MySQL + Clamav + SpamAssassin + Greylisting + Whitelisting + Dovecot
Решил я обновить почтовый сервер в провайдере, где работаю. Старый был в принципе тоже ничего, но строился в свое время изрядно впопыхах, без детального изучения документации, плюс пропускал довольно много спама и не обладал некоторыми фичами. В роли нового демона был выбран Exim плюс веб-интерфейс для него Vexim. Exim — хороший и мощный почтовый сервер, способный пропускать через себя огромные потоки писем. Однако, в конфигурации он сложнее, чем, например, Postfix, за что и не любим многими, потому статей по его настройке, особенно с прибамбасами, в сети не так много.
Эксперименты, которые полагается проводить на кошках, решил провести на своем сервере, который держит почту для jared.kiev.ua, собственно, по нему статья и писалась. Сначала думал пойти по простому пути: нашел сайт http://n1ck.name, где товарищ делает связку exim+vexim для Линукса. Может быть для сетапа на чистый линуксовйы сервер оно и есть самое то, но под фрей масса тамошних фич просто не завелась (хотя подкинули идеи). Далее попытался собрать связку по мануалу с сайта Vexim — та же история. В конце концов, после прочтения статьи у Лиссяры (статья хорошая, но нет нужных мне фич, опять же взял идеи), решил построить свой конфиг, с блекджеком и шлюхами тем, что мне надо.
Итак, к делу. В дальнейшем буду исходить из того, что у нас есть сервер под FreeBSD (неважно, jail или нет), на нем поднята связка Apache+PHP+MySQL. Версия MySQL должна быть не ниже 5, иначе некоторые запросы откажутся работать. Заходим в порты и видим, что экзиму наконец написали конфигурационное меню и больше не надо править мейкфайлы:
# cd /usr/ports/mail/exim # make config ┌────────────────────────────────────────────────────────────────────┐ │ Options for exim 4.71 │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │[ ] ALT_CONFIG_PREFIX Allow alternate configuration files │ │ │ │[X] AUTH_CRAM_MD5 Enable CRAM-MD5 authentication mechanisms│ │ │ │[X] AUTH_DOVECOT Enable Dovecot authentication mechanisms │ │ │ │[X] AUTH_PLAINTEXT Enalbe plaintext authentication │ │ │ │[ ] AUTH_RADIUS Enable radius (RFC 2865) authentication │ │ │ │[ ] AUTH_SASL Enable use of Cyrus SASL auth library │ │ │ │[X] AUTH_SPA Enable Secure Password Authentication │ │ │ │[X] CDB Enable CDB-style lookups │ │ │ │[X] CONTENT_SCAN Enable exiscan email content scanner │ │ │ │[X] DAEMON Install scripts to run as a daemon │ │ │ │[ ] DCC Enable DCC at ACL support via dccifd │ │ │ │[ ] DEBUG Build with debugging symbols │ │ │ │[X] DNSDB Enable DNS-style lookups │ │ │ │[X] DSEARCH Enable directory-list lookups │ │ │ │[X] EMBEDDED_PERL Enable embedded Perl interpreter │ │ │ │[ ] EXIMON Build eximon monitor (require XFree86!) │ │ │ │[X] ICONV Enable header charset conversion │ │ │ │[ ] IPV6 Enable IPv6 support │ │ │ │[ ] KAS Build with Kaspersky AntiSpam local scan │ │ │ │[X] LMTP RFC2033 SMTP over command pipe transport │ │ │ │[X] LSEARCH Enable wildcarded-file lookups │ │ │ │[X] MAILDIR Enable Maildir mailbox format │ │ │ │[X] MAILSTORE Enable Mailstore mailbox format │ │ │ │[X] MBX Enable MBX mailbox format │ │ │ │[X] MYSQL Link against libmysqlclient library │ │ │ │[X] NIS Enable NIS-style lookups │ │ │ │[X] OLD_DEMIME Enable old, deprecated demime ACL │ │ │ │[ ] OPENLDAP Link against libldap │ │ │ │[X] PAM Enable PAM authentication mechanisms │ │ │ │[X] PASSWD Enable /etc/passwd lookups │ │ │ │[ ] PGSQL Link against libpq │ │ │ │[ ] READLINE Enable readline(3) library │ │ │ │[ ] SASLAUTHD Enable use of Cyrus SASL auth daemon │ │ │ │[ ] SA_EXIM SA-Exim support │ │ │ │[X] SPF Enable Sender Policy Framework checking │ │ │ │[ ] SQLITE Enable SQLite lookups │ │ │ │[ ] SRS Enable Sender Rewriting Scheme │ │ │ │[ ] SRS_ALT Enable alternative SRS library │ │ │ │[X] SUID Install the exim binary suid root │ │ │ │[X] TCP_WRAPPERS Enable /etc/hosts.allow access control │ │ │ │[X] TLS Link against OpenSSL │ │ │ │[ ] WISHLIST Include the unsupported patches │ │ │ │[ ] XCLIENT Enable XCLIENT command in exim │ │ ├─└────────────────────────────────────────────────────────────────┘─┤ │ [ OK ] Cancel │ └────────────────────────────────────────────────────────────────────┘ # make install clean
Пока экзим ставится, создадим ssl-сертификат:
# mkdir -p /etc/ssl/certs # cd /etc/ssl/certs # openssl req -x509 -newkey rsa:1024 -keyout mail.pem -out mail.pem -days 9999 -nodes Country Name (2 letter code) [CA]: UA State or Province Name (full name) [Quebec]: Kiev Locality Name (eg, city) [Montreal]: Kiev Organization Name (eg, company) [Open Network Architecture]: Internet Provider Organizational Unit Name (eg, section) [Internet Department]: Network Operation Center Common Name (eg, YOUR name) []: jared.kiev.ua Email Address []: [email protected]
Заполняем соответственно нашим данным поля, особое внимание уделяем полю Common Name (eg, YOUR name) [], тут пишем DNS-имя нашего почтового сервера. Теперь у нас появился файл /etc/ssl/certs/mail.pem, выставим на него хозяина и права, заодно создадим пользователя, под которым у нас будет работать вся связка.
# chmod 440 /etc/ssl/certs/mail.pem # chgrp mail /etc/ssl/certs/mail.pem # pw useradd exim -c "Exim" -d /var/spool/mqueue -s /sbin/nologin -g mail # cat /etc/master.passwd | grep exim
Получаем строку вида exim:*:1002:6::0:0:Exim:/var/spool/mqueue:/sbin/nologin, из нее запоминаем User ID и Group ID, в примере они равны 1002 и 6 соответственно.
Теперь подсунем экзиму его конфиги. Ложим их в каталог /usr/local/etc/exim/. Т.к. его родной файл configure большой и неудобный в правке, я его разбил на ряд файлов, которые включаются в алфавитном порядке:
100.main.conf — основная конфигурация сервера: переменные, соединение с БД, логгирование и т.д.
110.greylist.conf — скрипты грейлистинга
200.acl-greylist.conf — ACL для грейлистинга
400.acl-check-rcpt-syntax.conf — ACL-проверки хоста-отправителя
410.acl-check-rcpt-spam.conf — ACL для начисления антиспам-баллов по заголовкам письма
420.acl-check-rcpt-end.conf — конец ACL check_rcpt: задержки, грейлисты, блеклисты
500.acl-check-data.conf — ACL для проверки содержимого письма: аттачи, Spamassassin, антивирус
600.routers.conf — роутеры
610.routers-groups.conf — роутер для поддержки групп пользователей
700.transports.conf — транспорты
800.retry.conf — повторная отправка писем
900.authenticators.conf — аутентификация
configure — основной файл конфигурации, подключает все остальные
dialup_hosts — регулярные выражения с описанием хостов, которые нам не нравятся
system-filter — действия со спамом: пометить/удалить
whitelist-hosts — список хостов, которые не проходят ряд проверок
whitelist-sender — список отправителей, которые не проходят ряд проверок
На первый взгляд, выглядит несколько запутано, но я попробую пояснить логику работы Экзима с таким конфигом. При получении письма происходит следующее:
- проверяется хост-отправитель: синтаксис приветствия, сессии, доменного имени, соответствия имени адресу и т.п. Если обнаружены совсем уже явные ошибки (некорректные символы, попытки выдать себя за другие хосты и т.п.) — письмо не пропускается, иначе письму начисляются спам-баллы в попугаях;
- если хост либо отправитель не внесены в белые списки, срабатывает задержка, потом грейлистинг. Задержка вычисляется по формуле 15с + (кол-во набранных ранее попугаев / 10), грейлистинг просто если не знает такого хоста, добавляет его в серый список и отсылает ошибку «временная проблема». Если хост нормальный релей, он пошлет письмо повторно и попадет в белый список (кстати, нормальные хосты готовы прождать и предыдущую задержку, это спамеры торопятся разослать мегатонны писем и ждать им некогда);
- письмо разбирается на запчасти. Если в нем есть запрещенные расширения файлов в аттаче или вирусы, оно нещадно рубится. Там же письмо отправляется в Spamassassin, количество набранных там баллов умножается на 2 и прибавляется к попугаям;
- Потом письмо отправляется к роутерам, которые решают, что с ним делать: отослать по SMTP, положить в ящик и т.д. и назначают письму соответствующий транспорт. Роутер с группами — вообще интересная штука: группа — это нечто вроде алиаса, но до тех пор пока она не является приватной, писать в нее могут только члены группы;
- Транспорты, понятное дело, выполняют то, чего от них хотят роутеры;
- Отдельно работает системный фильтр: на основании насчитанных спам-попугаев он либо правит тему письма на что-то вроде «*SPAM* [104 points] Ваш сайт на первой странице google.com.ua», либо удаляет его совсем, в зависимости от настроек каждого отдельного почтового ящика;
Вроде по всему основному прошелся, теперь перейдем к самим конфигам.
configure:
###################################################################### # Runtime configuration file for Exim # ###################################################################### # Инклюдим главные настройки .include /usr/local/etc/exim/100.main.conf # Инклюдим настройки грейлистинга .include /usr/local/etc/exim/110.greylist.conf ### конфигурация ACL для входящей почты begin acl # Начало ACL - "рабочий" ACL для грейлистинга .ifdef USE_GREYLIST greylist_acl: .include /usr/local/etc/exim/200.acl-greylist.conf .endif # Проверка правильности HELO acl_check_helo: accept hosts = +relay_from_hosts drop condition = ${if match{$sender_helo_name}{MY_IP}{yes}{no} } message = "Dropped spammer pretending to be us" drop condition = ${if match{$sender_helo_name}{^[0-9]\.[0-9]\.[0-9]\.[0-9]}{yes}{no} } message = "Dropped IP-only or IP-starting helo" accept # Эти правила срабатывают для каждого письма acl_check_rcpt: warn set acl_c_lp = $local_part@$domain # acl_check_rcpt - проверки на синтаксическую правильность .include /usr/local/etc/exim/400.acl-check-rcpt-syntax.conf # acl_check_rcpt - проверки на спам - по хостам и прочему. .include /usr/local/etc/exim/410.acl-check-rcpt-spam.conf # acl_check_rcpt - блэк-листы, задержки и прочее .include /usr/local/etc/exim/420.acl-check-rcpt-end.conf # проверка тела письма acl_check_content: # Инклюдим конфигурацию проверки тела письма .include /usr/local/etc/exim/500.acl-check-data.conf # Что делаем с почтой begin routers # Инклюдим конфигурацию роутреров .include /usr/local/etc/exim/600.routers.conf # начинаются транспорты - как доставляем почту begin transports # Инклюдим транспорты .include /usr/local/etc/exim/700.transports.conf # Конфигурация повторов и перезаписи .include /usr/local/etc/exim/800.retry.conf #begin rewrite # Секция авторизации при отправке писем. begin authenticators # Аутентификация юзеров. .include /usr/local/etc/exim/900.authenticators.conf
100.main.conf, тут настраиваются основные параметры: IP, домены и т.д.:
# Устанавливаем переменные MY_IP = 123.123.123.123 INTERNAL_IP = 192.168.1.10 # Настройки Vexim USE_SPF = true USE_AV = true USE_SPAMD = true USE_GREYLIST = true TLS = true # Белые списки hostlist whitelist_hosts = net-iplsearch;/usr/local/etc/exim/whitelist-hosts addresslist whitelist_sender = wildlsearch;/usr/local/etc/exim/whitelist-sender # По IPv6 мы пока не работаем disable_ipv6=true # Пользователь и группа, от которой будет работать вся связка exim_user = exim exim_group = mail # Тут были настройки рассылок, не пользуем - не сетапим MAILMAN_HOME=/usr/local/mailman MAILMAN_WRAP=MAILMAN_HOME/mail/mailman MAILMAN_USER=exim MAILMAN_GROUP=mail # Вводим данные для подключения к MySQL серверу. # словечко `hide`, вначале, означает, что при # вызове проверки конфига командой # exim -bV config_file эти данные не будут отображаться. # Если без него - то будут показаны... Формат записи: # хост/имя_бд/пользователь/пароль hide mysql_servers = localhost::(/tmp/mysql.sock)/mail/exim/8975f9i7vioyuhg # Интерфейсы, которые слушаем local_interfaces = MY_IP # Имя хоста. Используется в EHLO. # Фигурирует в других пунктах, если они не заданы, типа qualify_domain и прочих.. # Если тут ничего не установлено (строка закомментирована), то используется то, что вернёт функция uname() primary_hostname = jared.kiev.ua # Запросы для выборки информации по доменам VIRTUAL_DOMAINS = SELECT DISTINCT domain FROM domains WHERE type = 'local' AND enabled = '1' AND domain = '${quote_mysql:$domain}' RELAY_DOMAINS = SELECT DISTINCT domain FROM domains WHERE type = 'relay' AND domain = '${quote_mysql:$domain}' ALIAS_DOMAINS = SELECT DISTINCT alias FROM domainalias WHERE alias = '${quote_mysql:$domain}' # Делаем список локальных доменов. Далее этот список будет фигурировать в виде +local_domains # В данном случае домены выбираются из БД MySQL. Также можно их просто перечислить через двоеточие. domainlist local_domains = @ : ${lookup mysql{VIRTUAL_DOMAINS}} : ${lookup mysql{ALIAS_DOMAINS}} domainlist relay_to_domains = ${lookup mysql{RELAY_DOMAINS}} # Список доверенных сетей, откуда почта будет ходить без ряда проверок hostlist relay_from_hosts = localhost : MY_IP : 192.168.100.0/20 : 192.168.80.0/24 # Вводим названия acl`ов для проверки почты. acl_smtp_rcpt = acl_check_rcpt acl_smtp_data = acl_check_content acl_smtp_helo = acl_check_helo # Если в настройках сказано проверять почту на вирусы - подключаем .ifdef USE_AV av_scanner = clamd:/var/run/clamav/clamd.sock .endif # Если в настройках сказано проверять почту на спам - подключаем .ifdef USE_SPAMD spamd_address = /var/run/spamd.sock .endif # Если в настройках сказано работать с поддержкой SSL - подключаем .ifdef TLS # SSL/TLS cert and key tls_certificate = /etc/ssl/certs/mail.pem tls_privatekey = /etc/ssl/certs/mail.pem # Advertise TLS to anyone tls_advertise_hosts = * tls_on_connect_ports=465 .endif # Имя домена добавляемое для локальных отправителей (реальных # юзеров системы) т.е. почта отправляемая от root, будет от # root@домен_указанный_здесь. Если пункт не задан, то используется # имя хоста из `primary_hostname`. qualify_domain = jared.kiev.ua # Имя хоста для ситуации, обратной предыдущей, - это имя домена, добавляемое к почте для # системных юзеров, ну и вообще для почты, пришедшей на адрес типа `root` etc... # Если этоn пункт не задан то используется значение полученное из предыдущего пункта - `qualify_domain` qualify_recipient = jared.kiev.ua # A это как раз кусок вышеописанного анахронизма - про почту в # виде user@[222.222.222.222] - принимать её или нет. По дефолту # (когда строка закомментирована) значение - false. Если захотите # поставить true то надо будет добавить в список доменов # комбинацию @[] - она означает `все локальные адреса` allow_domain_literals = false # запрещаем работу доставки под юзером root - в целях безопасности never_users = root # Проверяем соответствие прямой и обратной зон для всех хостов. # Тока зачем это нужно - даже и незнаю... Спам на этом не режется. # Зато возможны проблемы - если сервер зоны скажет `сервер файлед` # то почту от этого хоста Вы не получите :) #host_lookup = * # По дефолту, экзим отфутболивает все `неквалифицированные` адреса, # состоящие тока из локальной части. Для того чтобы разрешить такие письма # определённых хостов используются эти директивы: # для `неквалифицированных` отправителей #sender_unqualified_hosts = +relay_from_hosts # для `неквалифицированных` получателей #recipient_unqualified_hosts = +relay_from_hosts # Если сообщение было не доставлено, то генерится соощение # об ошибке. Если сообщение об ошибке не удалось доставить # то оно замораживается на указанный в этом пункте срок, # после чего снова попытка доставить его. При очередной # неудаче - сообщение удаляется. ignore_bounce_errors_after = 1d # Замороженные сообщения, находящиеся в очереди, дольше # указанного времени удаляются и генерится сообщение # об ошибке (при условии, что это не было недоставленное # сообщение об ошибке :)) timeout_frozen_after = 7d # список адресов, через запятую, на которые засылаются # сообщения о замороженных сообщениях (о замороженых # уведомлениях о заморозке, сообщения не генерятся. - я # надеюсь эта строка понятна :)) #freeze_tell = [email protected] # Через какое время повторять попытку доставки # замороженного сообщения auto_thaw = 1h # Приветствие сервера smtp_banner = "$primary_hostname, ESMTP EXIM $version_number" # Максимальное число одновременных подключений по # SMTP. Рассчитывать надо исходя из нагрузки на сервер smtp_accept_max = 500 # максимальное число сообщений принимаемое за одно соединение # от удалённого сервера (или пользователя). smtp_accept_max_per_connection = 25 # максимальное число коннектов с одного хоста smtp_accept_max_per_host = 20 # Если у сообщения много адресатов на удалённых хостах, # то запускатеся до указанного числа максимально число # параллельных процессов доставки remote_max_parallel = 15 # при генерации сообщения об ошибке прикладывать # не всё сообщение, а кусок (от начала) указанного # размера (иногда полезно и целиком - в таком случае # просто закомментируйте эту строку) return_size_limit = 70k # разрешаем неположенные символы в HELO (столкнулся # с этим случайно - имя фирмы состояло из двух слов # и какой-то раздолбай домен обозвал my_firme_name # прям с подчёркиваниями... Виндовые клиенты при # соединении радостно рапортовали о себе # `vasya.my_firme_name` ну а экзим их футболил :)) helo_allow_chars = _ # Принудительная синхронизация. Если отправитель # торопится подавать команды, не дождавшись ответа, # то он посылается далеко и надолго :) Немного, # спам режется. smtp_enforce_sync = true # Выбираем, что мы будем логировать # + - писать в логи, # - - Не писать в логи. # +all_parents - все входящие? # +connection_reject - разорваные соединения # +incoming_interface - интерфейс (реально - IP) # +lost_incoming_connections - потеряные входящие # соединения # +received_sender - отправитель # +received_recipients - получатель # +smtp_confirmation - подтверждения SMTP? # +smtp_syntax_error - ошибки синтаксиса SMTP # +smtp_protocol_error - ошибки протокола SMTP # -queue_run - работа очереди (замороженные мессаги) #log_selector = \ # +all \ # -incoming_port \ # -incoming_interface \ # -arguments \ # -smtp_connection \ # -lost_incoming_connection \ # -queue_run log_selector = +subject \ +all_parents \ +lost_incoming_connection \ +received_sender \ +received_recipients \ +smtp_confirmation \ +smtp_syntax_error \ +smtp_protocol_error \ -queue_run # Системный фильтр, тут можно помечать спам и вообще делать с письмами много чего интересного system_filter = /usr/local/etc/exim/system-filter system_filter_pipe_transport = address_pipe system_filter_user = exim system_filter_group = mail
110.greylist.conf:
# Настройки грейлистинга # Изначальная задержка после первой попытки отправить письмо GREYLIST_INITIAL_DELAY = 10 MINUTE # Время жизни серой записи после первой попытки отправить письмо GREYLIST_INITIAL_LIFETIME = 4 HOUR # Время жизни белой записи GREYLIST_WHITE_LIFETIME = 36 DAY # Уже не помню, что оно такое, но было нулем :-)) GREYLIST_BOUNCE_LIFETIME = 0 HOUR # Названия грейлистовых таблиц GREYLIST_TABLE=exim_greylist GREYLIST_LOG_TABLE=exim_greylist_log # Настройки логгирования грейлистов GREYLIST_LOG_ENABLED=no .ifdef USE_GREYLIST # database macros GREYLIST_TEST = SELECT CASE \ WHEN now() > block_expires \ OR relay_ip = '127.0.0.1' \ THEN "accepted"\ ELSE "deferred" \ END AS result, id \ FROM GREYLIST_TABLE \ WHERE (now() < record_expires) \ AND (relay_ip = '${quote_mysql:$sender_host_address}' \ OR (type='MANUAL' \ AND ( relay_ip IS NULL \ OR relay_ip = substring('${quote_mysql:$sender_host_address}',1,length(relay_ip)) \ ) \ ) \ ) \ ORDER BY result DESC LIMIT 1 GREYLIST_ADD = INSERT INTO GREYLIST_TABLE \ (relay_ip, block_expires, \ record_expires, create_time, type) \ VALUES ( '${quote_mysql:$sender_host_address}', \ DATE_ADD(now(), INTERVAL GREYLIST_INITIAL_DELAY), \ DATE_ADD(now(), INTERVAL GREYLIST_INITIAL_LIFETIME), \ now(), \ 'AUTO' \ ) GREYLIST_DEFER_HIT = UPDATE GREYLIST_TABLE \ SET blockcount=blockcount+1 \ WHERE id = $acl_m9 GREYLIST_OK_COUNT = UPDATE GREYLIST_TABLE \ SET passcount=passcount+1 \ WHERE id = $acl_m9 GREYLIST_OK_NEWTIME = UPDATE GREYLIST_TABLE \ SET record_expires = DATE_ADD(now(), INTERVAL GREYLIST_WHITE_LIFETIME) \ WHERE id = $acl_m9 AND type='AUTO' GREYLIST_OK_BOUNCE = UPDATE GREYLIST_TABLE \ SET record_expires = DATE_ADD(now(), INTERVAL GREYLIST_BOUNCE_LIFETIME) \ WHERE id = $acl_m9 AND type='AUTO' GREYLIST_LOG = INSERT INTO GREYLIST_LOG_TABLE \ (listid, timestamp, kind) \ VALUES ($acl_m9, now(), '$acl_m8') GREYLIST_CHECK = SELECT greylist from domains where domain = '$domain' .endif
200.acl-greylist.conf:
# Если для домена значение поля greylist=0, не проверяем вообще deny condition = ${if <{${lookup mysql{GREYLIST_CHECK}}}{1}} # Выставляем внутренние переменные для грейлиста warn set acl_m8 = ${lookup mysql{GREYLIST_TEST}{$value}{result=unknown}} set acl_m9 = ${extract{id}{$acl_m8}{$value}{-1}} set acl_m8 = ${extract{result}{$acl_m8}{$value}{unknown}} # Проверяем, знаем ли такой хост, если нет - вносим в серый список accept condition = ${if eq{$acl_m8}{unknown}{1}} condition = ${lookup mysql{GREYLIST_ADD}{yes}{no}} # Пишем в лог .ifdef GREYLIST_LOG_ENABLED warn condition = ${lookup mysql{GREYLIST_LOG}} .endif # Проверка на повторную отправку до перехода в белый список accept condition = ${if eq{$acl_m8}{deferred}{1}} condition = ${lookup mysql{GREYLIST_DEFER_HIT}{yes}{yes}} warn condition = ${lookup mysql{GREYLIST_OK_COUNT}} # use a warn verb to set a new expire time on automatic records, # but only if the mail was not a bounce, otherwise set to now(). warn !senders = : postmaster@* condition = ${lookup mysql{GREYLIST_OK_NEWTIME}} warn senders = : postmaster@* condition = ${lookup mysql{GREYLIST_OK_BOUNCE}} deny
400.acl-check-rcpt-syntax.conf:
# принимать сообщения которые пришли с локалхоста, не по TCP/IP accept hosts = : # Запрещаем письма содержащие в локальной части # символы @; %; !; /; |. Учтите, если у вас было # `percent_hack_domains` то % надо убрать. # Проверяются локальные домены deny message = Reject: incorrect symbol in address log_message = REJECT: incorrect symbol in address domains = +local_domains local_parts = ^[.] : ^.*[@%!/|] delay = 30s # Проверяем недопустимые символы для нелокальных получателей: deny message = Reject: incorrect symbol in address log_message = REJECT: incorrect symbol in address domains = !+local_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ delay = 30s # Принимаем почту для постмастеров локальных доменов без # проверки отправителя (я закомментировал, т.к. это - # основной источник спама на мой ящик). # accept local_parts = postmaster # domains = +local_domains # Запрещщаем, если невозможно проверить отправителя # (отсутствует в списке локальных пользователей) # У себя я это закоментил, по причине, что некоторые # железяки (принтеры, & etc) и программы (Касперский, DrWEB) # умеют слать почту, в случае проблем но не умеют ставить # нужного отправителя. Такие письма эта проверка не пускает. # require verify = sender # Запрещщаем тех, кто не обменивается приветственными # сообщениями (HELO/EHLO) deny condition = ${if eq{$sender_helo_name}{}{yes}{no}} message = Reject: HELO/EHLO require by SMTP RFC log_message = REJECT: HELO/EHLO require by SMTP RFC delay = 30s # Принимаем сообщения от тех, кто аутентифицировался: accept authenticated = * # Рубаем нах, тех, кто подставляет свой IP в HELO deny condition = ${if isip{$sender_helo_name}{yes}{no}} hosts = !+relay_from_hosts:* message = Reject: We don't allow domain literals, many spam... log_message = REJECT: We don't allow domain literals, many spam... delay = 30s # Рубаем хело с нашим именем deny condition = ${if match_domain{$sender_helo_name} \ {$primary_hostname:+local_domains:+relay_to_domains} \ {true}{false}} message = Reject: Message was delivered by ratware - own log_message = REJECT: remote host used our name in HELO/EHLO. delay = 30s # Рубаем недопустимые символы в helo deny condition = ${if match{$sender_helo_name}{\N_\N}{yes}{no}} message = Reject: Invalid symbols in HELO log_message = REJECT: Invalid symbols in HELO hosts = !127.0.0.1 : !localhost : !+relay_from_hosts : * # Ограничения эксчейнджа - юзер не может начинаться/заканчиваться точкой. deny message = Reject: Invalid address log_message = REJECT: Dot-starting address senders = \N^\.|\.@\N
410.acl-check-rcpt-spam.conf:
# # Вводим переменную acl_m0 - в ней будет счётчик, # # сколько очков спамерских насчиталось... warn set acl_m0 = 0 # Проверяем соответствие HELO и обратной записи DNS для севера: warn condition = ${if !eq{$sender_helo_name}{$sender_host_name}{yes}{no}} hosts = !+relay_from_hosts : * set acl_m0 = ${eval:$acl_m0+20} # Смотрим, нашлась ли обратная запись для этого хоста warn condition = ${if eq{$host_lookup_failed}{1}{yes}{no}} hosts = !+relay_from_hosts : * set acl_m0 = ${eval:$acl_m0+30} # Считем число точек или дефисов в доменном имени. (больше 5 = +40 очков) warn condition = ${if match{$sender_host_name} \ {\N((?>\w+[\.|\-]){5,})\N}{yes}{no}} hosts = !+relay_from_hosts : * set acl_m0 = ${eval:$acl_m0+40} # Проверяем длину обратного почтовго адреса - пследнее время повадились # слать с безумными обратными адресами типа [email protected], # damsel'stailpipe`[email protected] и т.п. warn condition = ${if >{${strlen:$sender_address}}{25}{yes}{no}} hosts = !+relay_from_hosts : * set acl_m0 = ${eval:$acl_m0+10} # Добавляем очков за всякие dialup хосты warn condition = ${lookup{$sender_host_name} \ wildlsearch{/usr/local/etc/exim/dialup_hosts} \ {yes}{no}} hosts = !+relay_from_hosts : * set acl_m0 = ${eval:$acl_m0+60} # Проверяем счётчик получателей в письме - нормальные пользователи редко шлют # сообщения с большим числом получателей, а для крупных почтовых сервисов # всё сбросится по белому листу серверов, что находится дальше warn condition = ${if >{$recipients_count}{6}{yes}{no}} hosts = !+relay_from_hosts : * set acl_m0 = ${eval:$acl_m0+($recipients_count*20)} # Проверяем существование зоны из HELO (на этом правиле огребают очков все # уродцы с HELO типа 'friends' или 'localhost.localdomain') warn condition = ${if !eq{${lookup mysql{SELECT 1 FROM \ `list_top_level_domains` WHERE `zone` = \ LCASE(CONCAT('.', SUBSTRING_INDEX( \ '${quote_mysql:$sender_helo_name}', \ '.', -1)))}}}{1}{yes}{no}} hosts = !+relay_from_hosts : * set acl_m0 = ${eval:$acl_m0+150} # Добавляем очки, если spf не соответствует warn spf = fail hosts = !+relay_from_hosts : * set acl_m0 = ${eval:$acl_m0+60} # Устанавливаем переменную, которая видна между ACL-ями warn set acl_c_spam = $acl_m0
420.acl-check-rcpt-end.conf:
# Пропускаем письма, если хост или отправитель в белом списке warn log_message = WHITELISTED: host hosts = +whitelist_hosts warn log_message = WHITELISTED: sender senders = +whitelist_sender warn set acl_m5 = $local_part@$domain accept hosts = +whitelist_hosts accept senders = +whitelist_sender # Задержка. Режется довольно много не-MTA - спамерских скриптиков. warn set acl_c0 = 15s # Вычисляем задержку на основании насчитанных за спам очков: warn condition = ${if !eq{$acl_m0}{0}{yes}{no}} condition = ${if >{$acl_m0}{150}{yes}{no}} set acl_c0 = ${eval:$acl_m0/10}s warn # ставим задержку в 0 секунд своим хостам hosts = +relay_from_hosts set acl_c0 = 0s warn delay = $acl_c0 # Рубаем тех, кто в блэк-листах. Серваки перебираются # сверху вниз, если не хост не найден на первом, то # запрашивается второй, и т.д. Если не найден ни в одном # из списка - то почта пропускается. deny message = "you in blacklist - $dnslist_domain --> \ $dnslist_text; $dnslist_value" log_message = REJECT: Listed in $dnslist_domain hosts = !+relay_from_hosts dnslists = cbl.abuseat.org : \ dul.dnsbl.sorbs.net : \ sbl-xbl.spamhaus.org delay = 30s # Если включены грейлисты - грейлистим всю почту, кроме постмастерской .ifdef USE_GREYLIST defer !senders = : postmaster@* acl = greylist_acl message = GREYLIST: Greylisted, try later. .endif # проверяем пользователей из файла альясов (системные) accept domains = +local_domains verify = recipient # Разрешаем почту от доменов в списке relay_from_hosts accept hosts = +relay_from_hosts # приниаем почту для эксчейнджевых доменов accept domains = +relay_to_domains # Если неподошло ни одно правило - чувак явно ищет # открытый релей. Пшёл прочь. :) deny message = "Access deny - this not open relay!" log_message = REJECT: We aren't an open relay delay = 30s
500.acl-check-data.conf:
# Проверяем тело письма # Распаковываем контейнеры MIME и режем серьезные ошибки deny message = This message contains a MIME error ($demime_reason) log_message = REJECT: Error in MIME demime = * condition = ${if >{$demime_errorlevel}{2}{1}{0}} # Режем типично вирусные расширения файлов deny message = Bad file extension ($found_extension) log_message = REJECT: Bad attachment demime = scr:vbs:bat:lnk:pif deny message = Possible CMD file attack ($found_extension) log_message = REJECT: Bad attachment demime = cmd deny message = Possible COM file attack ($found_extension) log_message = REJECT: Bad attachment demime = com deny message = Possible Microsoft JScript attack ($found_extension) log_message = REJECT: Bad attachment demime = js deny message = Possible Windows registry attack ($found_extension) log_message = REJECT: Bad attachment demime = reg deny message = Possible compiled Help file-base virus ($found_extension) log_message = REJECT: Bad attachment demime = chm deny message = Possible SpeedDial attack ($found_extension) log_message = REJECT: Bad attachment demime = cnf deny message = Possible Micrsoft HTML archive attack ($found_extension) log_message = REJECT: Bad attachment demime = hta deny message = Possible Microsoft Internet Settings attack ($found_extension) log_message = REJECT: Bad attachment demime = ins deny message = Possible Windows Explorer Command attack ($found_extension) log_message = REJECT: Bad attachment demime = scf deny message = Possible Microsoft Windows Script attack ($found_extension) log_message = REJECT: Bad attachment demime = sct deny message = Possible Microsoft VBScript attack ($found_extension) log_message = REJECT: Bad attachment demime = vbs:vbe deny message = Possible Microsoft Script Host attack ($found_extension) log_message = REJECT: Bad attachment demime = wsc:wsf:wsh deny message = Possible Exchange Shortcut attack ($found_extension) log_message = REJECT: Bad attachment demime = xnk deny message = Possible Microsoft Access Shortcut attack ($found_extension) log_message = REJECT: Bad attachment demime = mad:maf:mag:mam:maq:mar:mas:mat:mav:maw # Сообщения с NUL-символами deny message = This message contains NUL characters log_message = REJECT: NUL characters! condition = ${if >{$body_zerocount}{0}{1}{0}} # Синтаксис заголовков deny message = Incorrect headers syntax log_message = REJECT: Incorrect header syntax hosts = !+relay_from_hosts:* !verify = header_syntax # Проверки на спам .ifdef USE_SPAMD warn set acl_m3 = $acl_c_spam warn set acl_m5 = $acl_c_lp warn message = X-Spam-Report: $spam_report spam = exim:true # spam = nobody:true # Если SpamAssassin вернул больше +1 балла, добавляем кол-во баллов*20 к общему спам-рейтингу warn condition = ${if >{$spam_score_int}{10}{1}{0}} set acl_m3 = ${eval:$acl_c_spam+$spam_score_int*2} # На основании общего кол-ва спам-очков и юзерских настроек определяем, помечать письмо спамом или удалять warn set acl_m4 = ${lookup mysql{select count(users.on_spamassassin) from users,domains where username = '$acl_m5' \ and domains.enabled = '1' and users.enabled = '1' and users.sa_tag>0 \ and users.sa_tag<$acl_m3 and users.domain_id = domains.domain_id}} warn set acl_m6 = ${lookup mysql{select count(users.on_spamassassin) from users,domains where username = '$acl_m5' \ and domains.enabled = '1' and users.enabled = '1' and users.sa_refuse>0 \ and users.sa_refuse<$acl_m3 and users.domain_id = domains.domain_id}} warn condition = ${if >{$acl_m3}{60}{1}{0}} log_message = SPAM: $acl_m3 points warn condition = ${if eq{$acl_m6}{yes}{yes}{no}} log_message = SPAM: $acl_m3 points .endif # Проверяем письмо на вирусы .ifdef USE_AV deny malware = * log_message = MALWARE: $malware_name .endif # Пропускаем остальное accept
600.routers.conf:
dnslookup: driver = dnslookup domains = ! +local_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more ditch_maxmsgsize: driver = redirect allow_fail condition = ${if >{$message_size}{${lookup mysql{select users.maxmsgsize from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.maxmsgsize > 0 \ and users.domain_id=domains.domain_id }{${value}K}fail}} {yes}{no}} data = :fail: This user does not accept messages larger than ${lookup mysql{select users.maxmsgsize from users,domains \ where localpart = '${quote_mysql:$local_part}' and domain = '${quote_mysql:$domain}' \ and users.maxmsgsize > 0 and users.domain_id=domains.domain_id}{${value}}fail}Kb. # local_part_suffix = -* # local_part_suffix_optional # retry_use_local_part ditch_malware: driver = redirect allow_fail data = :blackhole: condition = ${if and { {match {$h_X-ACL-Warn:}{.*malware.*}} \ {eq {${lookup mysql{select users.on_avscan from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.on_avscan = '1' \ and users.domain_id=domains.domain_id}}}{1} }} {yes}{no} } ditch_spam: driver = redirect allow_fail data = :blackhole: condition = ${if >{$spam_score_int}{${lookup mysql{select users.sa_refuse from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.on_spamassassin = '1' \ and users.domain_id=domains.domain_id \ and users.sa_refuse > 0 }{$value}fail}} {yes}{no}} # local_part_suffix = -* # local_part_suffix_optional # retry_use_local_part ditch_hdrmailer: driver = redirect allow_fail data = :blackhole: condition = ${if eq {${lookup mysql{select count(blocklists.block_id) from blocklists,users,domains \ where blocklists.blockhdr = 'X-Mailer' \ and LOCATE( blocklists.blockval, '${quote_mysql:$h_x-mailer:}') > 0 \ and users.localpart = '${quote_mysql:$local_part}' \ and domains.domain = '${quote_mysql:$domain}' \ and domains.domain_id=blocklists.domain_id \ and users.user_id=blocklists.user_id}}}{1} {yes}{no}} # local_part_suffix = -* # local_part_suffix_optional retry_use_local_part ditch_hdrto: driver = redirect allow_fail data = :blackhole: condition = ${if eq {${lookup mysql{select count(blocklists.block_id) from blocklists,users,domains \ where blocklists.blockhdr = 'To' \ and LOCATE(blocklists.blockval, '${quote_mysql:$h_to:}')>0 \ and users.localpart = '${quote_mysql:$local_part}' \ and domains.domain = '${quote_mysql:$domain}' \ and domains.domain_id=blocklists.domain_id \ and users.user_id=blocklists.user_id}}}{1} {yes}{no}} # local_part_suffix = -* # local_part_suffix_optional retry_use_local_part ditch_hdrfrom: driver = redirect allow_fail data = :blackhole: condition = ${if eq {${lookup mysql{select count(blocklists.block_id) from blocklists,users,domains \ where blocklists.blockhdr = 'From' \ and LOCATE( blocklists.blockval, '${quote_mysql:$h_from:}') > 0 \ and users.localpart = '${quote_mysql:$local_part}' \ and domains.domain = '${quote_mysql:$domain}' \ and domains.domain_id=blocklists.domain_id \ and users.user_id=blocklists.user_id}}}{1} {yes}{no}} # local_part_suffix = -* # local_part_suffix_optional retry_use_local_part ditch_hdrsubject: driver = redirect allow_fail data = :blackhole: condition = ${if eq {${lookup mysql{select count(blocklists.block_id) from blocklists,users,domains \ where blocklists.blockhdr = 'Subject' \ and LOCATE( blocklists.blockval, '${quote_mysql:$h_subject:}') > 0 \ and users.localpart = '${quote_mysql:$local_part}' \ and domains.domain = '${quote_mysql:$domain}' \ and domains.domain_id=blocklists.domain_id \ and users.user_id=blocklists.user_id}}}{1} {yes}{no}} # local_part_suffix = -* # local_part_suffix_optional retry_use_local_part virtual_vacation: driver = accept condition = ${if and { {!match {$h_precedence:}{(?i)junk|bulk|list}} \ {eq {${lookup mysql{select users.on_vacation from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.on_vacation = '1' \ and users.domain_id=domains.domain_id}}}{1} }} {yes}{no} } no_verify no_expn unseen transport = virtual_vacation_delivery virtual_forward: driver = redirect check_ancestor unseen = ${if eq {${lookup mysql{select unseen from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.on_forward = '1' \ and users.domain_id=domains.domain_id}}}{1} {yes}{no}} data = ${lookup mysql{select forward from users,domains \ where localpart='${quote_mysql:$local_part}' \ and domain='${quote_mysql:$domain}' \ and users.domain_id=domains.domain_id \ and on_forward = '1'}} # We explicitly make this condition NOT forward mailing list mail! condition = ${if and { {!match {$h_precedence:}{(?i)junk}} \ {eq {${lookup mysql{select users.on_forward from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.on_forward = '1' \ and users.domain_id=domains.domain_id}}}{1} }} {yes}{no} } virtual_domains: driver = redirect allow_fail data = ${lookup mysql{select users.smtp from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and domains.enabled = '1' \ and users.enabled = '1' \ and users.domain_id = domains.domain_id}} # local_part_suffix = -* # local_part_suffix_optional retry_use_local_part file_transport = virtual_delivery reply_transport = address_reply pipe_transport = address_pipe .include /usr/local/etc/exim/610.routers-groups.conf virtual_domains_catchall: driver = redirect allow_fail data = ${lookup mysql{select users.smtp from users,domains where localpart = '*' \ and domain = '${quote_mysql:$domain}' \ and users.domain_id = domains.domain_id}} retry_use_local_part file_transport = virtual_delivery reply_transport = address_reply pipe_transport = address_pipe_catchall virtual_domain_alias: driver = redirect allow_fail data = ${lookup mysql{select concat('${quote_mysql:$local_part}@', domains.domain) \ from domains,domainalias where domainalias.alias = '${quote_mysql:$domain}' \ and domainalias.domain_id = domains.domain_id}} retry_use_local_part
610.routers-groups.conf
# Группа - это список пользователей
#
# Если группа объявлена публичной, кто угодно из интернета может писать ей
# Иначе только члены группы
#
# Если не член непубличной группы пишет в нее, он получит "550 Unknown user"
virtual_dom_groups:
driver = redirect
allow_fail
senders = ${if eq{Y}{${lookup mysql{select g.is_public \
from groups g, domains d \
where d.enabled = '1' and d.domain = '${quote_mysql:$domain}' and \
d.domain_id = g.domain_id and g.enabled = '1' and \
g.name = '${quote_mysql:$local_part}'}}} \
{$sender_address} \
{${lookup mysql{select u.username \
from domains d, groups g, group_contents c, users u \
where d.enabled = '1' and d.domain = '${quote_mysql:$domain}' and \
d.domain_id = g.domain_id and g.name = '${quote_mysql:$local_part}' and \
g.enabled = '1' and \
g.is_public = 'N' and c.member_id = u.user_id and \
d.domain_id = u.domain_id and u.enabled = '1' \
and u.username = '${quote_mysql:$sender_address}' }}}}
data = ${lookup mysql{ \
select u.username \
from domains d, groups g, group_contents c, users u \
where d.enabled = '1' and \
d.domain = '${quote_mysql:$domain}' and \
d.domain_id = g.domain_id and \
g.enabled = '1' and \
g.id = c.group_id and \
c.member_id = u.user_id and \
d.domain_id = u.domain_id and \
u.enabled = '1' and \
g.name = '${quote_mysql:$local_part}'} }
local_part_suffix = -*
local_part_suffix_optional
retry_use_local_part
reply_transport = address_reply
pipe_transport = address_pipe
700.transports.conf:
remote_smtp: driver = smtp interface = MY_IP local_delivery: driver = appendfile file = /var/mail/$local_part delivery_date_add envelope_to_add return_path_add group = mail user = $local_part mode = 0660 no_mode_fail_narrower virtual_delivery: driver = appendfile envelope_to_add return_path_add mode = 0600 maildir_format = true create_directory = true directory = ${lookup mysql{select smtp from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.domain_id = domains.domain_id}} user = ${lookup mysql{select users.uid from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.domain_id = domains.domain_id}} group = ${lookup mysql{select users.gid from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.domain_id = domains.domain_id}} quota = ${lookup mysql{select users.quota from users,domains \ where localpart = '${quote_mysql:$local_part}' \ and domain = '${quote_mysql:$domain}' \ and users.domain_id = domains.domain_id}{${value}M}} quota_is_inclusive = false #quota_size_regex = ,S=(\d+): quota_warn_threshold = 75% maildir_use_size_file = false quota_warn_message = "To: $local_part@$domain\n\ Subject: Mailbox quota warning\n\n\ This message was automatically generated by the mail delivery software.\n\n\ You are now using over 75% of your allocated mail storage quota.\n\n\ If your mailbox fills completely, further incoming messages will be automatically\n\ returned to their senders.\n\n\ Please take note of this and remove unwanted mail from your mailbox.\n" virtual_vacation_delivery: driver = autoreply from = "${local_part}@${domain}" to = ${sender_address} subject = "Autoreply from ${local_part}@${domain}" text = ${lookup mysql{select vacation from users,domains \ where domain='${quote_mysql:$domain}' \ and localpart='${quote_mysql:$local_part}' \ and users.domain_id=domains.domain_id}} mailman_transport: driver = pipe command = MAILMAN_WRAP \ '${if def:local_part_suffix \ {${sg{$local_part_suffix}{-(\\w+)(\\+.*)?}{\$1}}} \ {post}}' \ $local_part current_directory = MAILMAN_HOME home_directory = MAILMAN_HOME user = MAILMAN_USER group = MAILMAN_GROUP address_pipe: driver = pipe return_output user = ${lookup mysql{select users.uid from users,domains where localpart = '${quote_mysql:$local_part}' and domain = '${quote_mysql:$domain}' and users.domain_id = domains.domain_id}} group = ${lookup mysql{select users.gid from users,domains where localpart = '${quote_mysql:$local_part}' and domain = '${quote_mysql:$domain}' and users.domain_id = domains.domain_id}} address_pipe_catchall: driver = pipe return_output user = ${lookup mysql{select users.uid from users,domains where localpart = '*' and domain = '${quote_mysql:$domain}' and users.domain_id = domains.domain_id}} group = ${lookup mysql{select users.gid from users,domains where localpart = '*' and domain = '${quote_mysql:$domain}' and users.domain_id = domains.domain_id}} address_pipe_local: driver = pipe return_output address_file: driver = appendfile delivery_date_add envelope_to_add return_path_add address_directory: driver = appendfile maildir_format address_reply: driver = autoreply
800.retry.conf:
begin retry # Domain Error Retries # ------ ----- ------- * * F,2h,15m; G,16h,1h,1.5; F,14d,6h
900.authenticators.conf:
plain_login: driver = plaintext public_name = PLAIN server_condition = ${lookup mysql{SELECT '1' FROM users \ WHERE username = '${quote_mysql:$2}' \ AND clear = '${quote_mysql:$3}'} {yes}{no}} server_set_id = $2 fixed_login: driver = plaintext public_name = LOGIN server_prompts = "Username:: : Password::" server_condition = ${lookup mysql{SELECT '1' FROM users \ WHERE username = '${quote_mysql:$1}' \ AND clear = '${quote_mysql:$2}'} {yes}{no}} server_set_id = $1 fixed_cram: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${lookup mysql{SELECT clear FROM users \ WHERE username = '${quote_mysql:$1}'}{$value}fail} server_set_id = $1
dialup_hosts:
# dialup hosts ^\.*dsl\.* ^\.*dialup\.* ^\.*dialin\.* ^\.*pool\.* ^\.*peer\.* ^\.*dhcp\.* ^\.*dynamic\.* ^\.*cable\.* ^\.*ppp\.* # expressions for digit in hosts ^\d+[-\.]\d+[-\.]\d+[-\.] ^\d{5,} # by ded3axap ^.*([1-9]+)\\-([0-9]+)\\-([0-9]+)\\-([1-9]+).* ^.*([1-9]+).([0-9]+).([0-9]+).([1-9]+).* ^.*pool.* ^.*dial.* ^.*dyn.* ^.*ppp.* ^.*fbx.* ^.*cable.* ^.*dsl.* ^.*dynamic.* ^.*fibertel.* ^.*broadband.* ^.*hsd1.* ^.*telecable.* ^.*dhcp.* ^.*kabel.* ^.*client.* ^.*in-addr.* ^.*user.* ^.*cpe.* ^.*tampabay.* ^.*phx1.* ^.*static.* ^.*rev.* ^.*speedy.* ^.*genericrev.* ^.*cdma.* ^.*catv.* ^.*customer.* # optional - by ded3axap ^.*rima-tde\\.net ^.*comcast\\.net ^.*pppoe\\.mtu-net\\.ru ^.*proxad\\.net ^.*bezeqint\\.net ^.*arcor-ip\\.net ^.*novis\\.pt ^.*rr\\.com ^.*verizon\\.net ^.*chello\\.nl ^.*ono\\.com ^.*t-dialin\\.net ^.*telenet\\.be ^.*virtua.com\\.br ^.*veloxzone.com\\.br ^.*tpnet\\.pl ^.*com\\.au ^.*asianet\\.co\\.th ^.*interbusiness\\.it ^.*webandnetworksolutions\\.com ^.*xtra.co\\.nz ^.*atlanticbb\\.net ^.*sinor\\.ru ^.*tiscali\\.fr ^.*wanadoo\\.fr ^.*pacbell\\.net ^.*prodigy\\.net ^.*charter\\.com ^.*barak-online\\.net ^.*qwest\\.net ^.*cm\\.vtr\\.net ^.*link\\.com\\.eg ^.*t-ipconnect\\.de ^.*mindspring\\.com ^.*telesp\\.net\\.br ^.*home\\.nl ^.*cable\\.ntl\\.com ^.*netvision\\.net\\.il ^.*btcentralplus\\.com ^.*surewest\\.net ^.*anteldata\\.net\\.uy ^.*mm\\.pl ^.*euskaltel\\.es ^.*satnet\\.net ^.*kabelbw\\.de ^.*skylink\\.ru ^.*consumerpcinc\\.com ^.*yourhostingaccount\\.com
system-filter:
logfile /var/log/exim/mainlog if $acl_c_spam matches ^\\d+ then # Строим новую тему письма - если спам # Проверяем содержимое переменной со счётчиком спамерских очков. headers add "X-Spam-score: $acl_m3" # рихтуем хедеры if $acl_m4 is above 0 then headers add "Old-Subject: $h_subject:" headers remove "Subject" headers add "Subject: *SPAM* [$acl_m3 points] $h_old-subject:" headers add "X-Spam: YES" # Старый заголовок оставляем, на всякий случай #headers remove "Old-Subject" endif if $acl_m6 is above 0 then fail text "Scored too much spam points" logwrite "SPAM: Spam count = $acl_m3" endif endif
whitelist-hosts:
127.0.0.1/32
whitelist-sender:
[email protected]
Создаем базу данных, заливаем дамп:
CREATE TABLE IF NOT EXISTS `blocklists` ( `block_id` int(10) unsigned NOT NULL auto_increment, `domain_id` mediumint(8) unsigned NOT NULL default '0', `user_id` int(10) unsigned default NULL, `blockhdr` varchar(192) NOT NULL default '', `blockval` varchar(192) NOT NULL default '', `color` varchar(8) NOT NULL default '', PRIMARY KEY (`block_id`) ) TYPE=MyISAM ; CREATE TABLE IF NOT EXISTS `domainalias` ( `domain_id` mediumint(8) unsigned NOT NULL default '0', `alias` varchar(64) default NULL ) TYPE=MyISAM; CREATE TABLE IF NOT EXISTS `domains` ( `domain_id` mediumint(8) unsigned NOT NULL auto_increment, `domain` varchar(64) NOT NULL default '', `maildir` varchar(128) NOT NULL default '', `uid` smallint(5) unsigned NOT NULL default '1002', `gid` smallint(5) unsigned NOT NULL default '6', `max_accounts` int(10) unsigned NOT NULL default '0', `quotas` int(10) unsigned NOT NULL default '0', `type` varchar(5) default NULL, `avscan` tinyint(1) NOT NULL default '0', `blocklists` tinyint(1) NOT NULL default '0', `complexpass` tinyint(1) NOT NULL default '0', `enabled` tinyint(1) NOT NULL default '1', `mailinglists` tinyint(1) NOT NULL default '0', `maxmsgsize` mediumint(8) unsigned NOT NULL default '0', `pipe` tinyint(1) NOT NULL default '0', `spamassassin` tinyint(1) NOT NULL default '0', `greylist` tinyint(4) NOT NULL default '1', `sa_tag` smallint(5) unsigned NOT NULL default '0', `sa_refuse` smallint(5) unsigned NOT NULL default '0', PRIMARY KEY (`domain_id`), UNIQUE KEY `domain` (`domain`), KEY `domain_id` (`domain_id`), KEY `domains` (`domain`) ) TYPE=MyISAM ; INSERT INTO `domains` (`domain_id`, `domain`, `maildir`, `uid`, `gid`, `max_accounts`, `quotas`, `type`, `avscan`, `blocklists`, `complexpass`, `enabled`, `mailinglists`, `maxmsgsize`, `pipe`, `spamassassin`, `greylist`, `sa_tag`, `sa_refuse`) VALUES (1, 'admin', '', 1002, 6, 0, 0, NULL, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0); CREATE TABLE IF NOT EXISTS `exim_greylist` ( `id` bigint(20) NOT NULL auto_increment, `relay_ip` varchar(80) default NULL, `block_expires` datetime NOT NULL default '0000-00-00 00:00:00', `record_expires` datetime NOT NULL default '9999-12-31 23:59:59', `create_time` datetime NOT NULL default '0000-00-00 00:00:00', `type` enum('AUTO','MANUAL') NOT NULL default 'MANUAL', `passcount` bigint(20) NOT NULL default '0', `blockcount` bigint(20) NOT NULL default '0', PRIMARY KEY (`id`) ) TYPE=MyISAM ; CREATE TABLE IF NOT EXISTS `exim_greylist_log` ( `id` bigint(20) NOT NULL auto_increment, `listid` bigint(20) NOT NULL default '0', `timestamp` datetime NOT NULL default '0000-00-00 00:00:00', `kind` enum('deferred','accepted') NOT NULL default 'deferred', PRIMARY KEY (`id`) ) TYPE=MyISAM ; CREATE TABLE IF NOT EXISTS `groups` ( `id` int(10) NOT NULL auto_increment, `domain_id` mediumint(8) unsigned NOT NULL, `name` varchar(64) NOT NULL, `is_public` char(1) NOT NULL default 'Y', `enabled` tinyint(1) NOT NULL default '1', PRIMARY KEY (`id`), UNIQUE KEY `group_name` (`domain_id`,`name`) ) TYPE=MyISAM ; CREATE TABLE IF NOT EXISTS `group_contents` ( `group_id` int(10) NOT NULL, `member_id` int(10) NOT NULL, PRIMARY KEY (`group_id`,`member_id`) ) TYPE=MyISAM; CREATE TABLE IF NOT EXISTS `list_top_level_domains` ( `unic_id` int(3) NOT NULL auto_increment, `zone` varchar(15) binary NOT NULL default '', `description` varchar(64) binary NOT NULL default '', PRIMARY KEY (`unic_id`), UNIQUE KEY `zone` (`zone`) ) TYPE=MyISAM ; INSERT INTO `list_top_level_domains` (`unic_id`, `zone`, `description`) VALUES (1, '.ac', 'Ascension Island'), (2, '.ad', 'Andorra'), (3, '.ae', 'United Arab Emirates'), (4, '.af', 'Afghanistan'), (5, '.ag', 'Antigua and Barbuda'), (6, '.ai', 'Anguilla'), (7, '.al', 'Albania'), (8, '.am', 'Armenia'), (9, '.an', 'Netherlands Antilles'), (10, '.ao', 'Angola'), (11, '.aq', 'Antarctica'), (12, '.ar', 'Argentina'), (13, '.as', 'American Samoa'), (14, '.at', 'Austria'), (15, '.au', 'Australia'), (16, '.aw', 'Aruba'), (17, '.ax', 'Aland Islands'), (18, '.az', 'Azerbaijan'), (19, '.ba', 'Bosnia and Herzegovina'), (20, '.bb', 'Barbados'), (21, '.bd', 'Bangladesh'), (22, '.be', 'Belgium'), (23, '.bf', 'Burkina Faso'), (24, '.bg', 'Bulgaria'), (25, '.bh', 'Bahrain'), (26, '.bi', 'Burundi'), (27, '.bj', 'Benin'), (28, '.bm', 'Bermuda'), (29, '.bn', 'Brunei Darussalam'), (30, '.bo', 'Bolivia'), (31, '.br', 'Brazil'), (32, '.bs', 'Bahamas'), (33, '.bt', 'Bhutan'), (34, '.bv', 'Bouvet Island'), (35, '.bw', 'Botswana'), (36, '.by', 'Belarus'), (37, '.bz', 'Belize'), (38, '.ca', 'Canada'), (39, '.cc', 'Cocos (Keeling) Islands'), (40, '.cd', 'Congo, The Democratic Republic o'), (41, '.cf', 'Central African Republic'), (42, '.cg', 'Congo, Republic of'), (43, '.ch', 'Switzerland'), (44, '.ci', 'Cote d''Ivoire'), (45, '.ck', 'Cook Islands'), (46, '.cl', 'Chile'), (47, '.cm', 'Cameroon'), (48, '.cn', 'China'), (49, '.co', 'Colombia'), (50, '.cr', 'Costa Rica'), (51, '.cu', 'Cuba'), (52, '.cv', 'Cape Verde'), (53, '.cx', 'Christmas Island'), (54, '.cy', 'Cyprus'), (55, '.cz', 'Czech Republic'), (56, '.de', 'Germany'), (57, '.dj', 'Djibouti'), (58, '.dk', 'Denmark'), (59, '.dm', 'Dominica'), (60, '.do', 'Dominican Republic'), (61, '.dz', 'Algeria'), (62, '.ec', 'Ecuador'), (63, '.ee', 'Estonia'), (64, '.eg', 'Egypt'), (65, '.eh', 'Western Sahara'), (66, '.er', 'Eritrea'), (67, '.es', 'Spain'), (68, '.et', 'Ethiopia'), (69, '.eu', 'European Union'), (70, '.fi', 'Finland'), (71, '.fj', 'Fiji'), (72, '.fk', 'Falkland Islands (Malvinas)'), (73, '.fm', 'Micronesia, Federated States of'), (74, '.fo', 'Faroe Islands'), (75, '.fr', 'France'), (76, '.ga', 'Gabon'), (77, '.gb', 'United Kingdom'), (78, '.gd', 'Grenada'), (79, '.ge', 'Georgia'), (80, '.gf', 'French Guiana'), (81, '.gg', 'Guernsey'), (82, '.gh', 'Ghana'), (83, '.gi', 'Gibraltar'), (84, '.gl', 'Greenland'), (85, '.gm', 'Gambia'), (86, '.gn', 'Guinea'), (87, '.gp', 'Guadeloupe'), (88, '.gq', 'Equatorial Guinea'), (89, '.gr', 'Greece'), (90, '.gs', 'South Georgia and the South Sand'), (91, '.gt', 'Guatemala'), (92, '.gu', 'Guam'), (93, '.gw', 'Guinea-Bissau'), (94, '.gy', 'Guyana'), (95, '.hk', 'Hong Kong'), (96, '.hm', 'Heard and McDonald Islands'), (97, '.hn', 'Honduras'), (98, '.hr', 'Croatia/Hrvatska'), (99, '.ht', 'Haiti'), (100, '.hu', 'Hungary'), (101, '.id', 'Indonesia'), (102, '.ie', 'Ireland'), (103, '.il', 'Israel'), (104, '.im', 'Isle of Man'), (105, '.in', 'India'), (106, '.io', 'British Indian Ocean Territory'), (107, '.iq', 'Iraq'), (108, '.ir', 'Iran, Islamic Republic of'), (109, '.is', 'Iceland'), (110, '.it', 'Italy'), (111, '.je', 'Jersey'), (112, '.jm', 'Jamaica'), (113, '.jo', 'Jordan'), (114, '.jp', 'Japan'), (115, '.ke', 'Kenya'), (116, '.kg', 'Kyrgyzstan'), (117, '.kh', 'Cambodia'), (118, '.ki', 'Kiribati'), (119, '.km', 'Comoros'), (120, '.kn', 'Saint Kitts and Nevis'), (121, '.kp', 'Korea, Democratic People''s Repub'), (122, '.kr', 'Korea, Republic of'), (123, '.kw', 'Kuwait'), (124, '.ky', 'Cayman Islands'), (125, '.kz', 'Kazakhstan'), (126, '.la', 'Lao People''s Democratic Republic'), (127, '.lb', 'Lebanon'), (128, '.lc', 'Saint Lucia'), (129, '.li', 'Liechtenstein'), (130, '.lk', 'Sri Lanka'), (131, '.lr', 'Liberia'), (132, '.ls', 'Lesotho'), (133, '.lt', 'Lithuania'), (134, '.lu', 'Luxembourg'), (135, '.lv', 'Latvia'), (136, '.ly', 'Libyan Arab Jamahiriya'), (137, '.ma', 'Morocco'), (138, '.mc', 'Monaco'), (139, '.md', 'Moldova, Republic of'), (140, '.me', 'Montenegro'), (141, '.mg', 'Madagascar'), (142, '.mh', 'Marshall Islands'), (143, '.mk', 'Macedonia, The Former Yugoslav R'), (144, '.ml', 'Mali'), (145, '.mm', 'Myanmar'), (146, '.mn', 'Mongolia'), (147, '.mo', 'Macao'), (148, '.mp', 'Northern Mariana Islands'), (149, '.mq', 'Martinique'), (150, '.mr', 'Mauritania'), (151, '.ms', 'Montserrat'), (152, '.mt', 'Malta'), (153, '.mu', 'Mauritius'), (154, '.mv', 'Maldives'), (155, '.mw', 'Malawi'), (156, '.mx', 'Mexico'), (157, '.my', 'Malaysia'), (158, '.mz', 'Mozambique'), (159, '.na', 'Namibia'), (160, '.nc', 'New Caledonia'), (161, '.ne', 'Niger'), (162, '.nf', 'Norfolk Island'), (163, '.ng', 'Nigeria'), (164, '.ni', 'Nicaragua'), (165, '.nl', 'Netherlands'), (166, '.no', 'Norway'), (167, '.np', 'Nepal'), (168, '.nr', 'Nauru'), (169, '.nu', 'Niue'), (170, '.nz', 'New Zealand'), (171, '.om', 'Oman'), (172, '.pa', 'Panama'), (173, '.pe', 'Peru'), (174, '.pf', 'French Polynesia'), (175, '.pg', 'Papua New Guinea'), (176, '.ph', 'Philippines'), (177, '.pk', 'Pakistan'), (178, '.pl', 'Poland'), (179, '.pm', 'Saint Pierre and Miquelon'), (180, '.pn', 'Pitcairn Island'), (181, '.pr', 'Puerto Rico'), (182, '.ps', 'Palestinian Territory, Occupied'), (183, '.pt', 'Portugal'), (184, '.pw', 'Palau'), (185, '.py', 'Paraguay'), (186, '.qa', 'Qatar'), (187, '.re', 'Reunion Island'), (188, '.ro', 'Romania'), (189, '.rs', 'Serbia'), (190, '.ru', 'Russian Federation'), (191, '.rw', 'Rwanda'), (192, '.sa', 'Saudi Arabia'), (193, '.sb', 'Solomon Islands'), (194, '.sc', 'Seychelles'), (195, '.sd', 'Sudan'), (196, '.se', 'Sweden'), (197, '.sg', 'Singapore'), (198, '.sh', 'Saint Helena'), (199, '.si', 'Slovenia'), (200, '.sj', 'Svalbard and Jan Mayen Islands'), (201, '.sk', 'Slovak Republic'), (202, '.sl', 'Sierra Leone'), (203, '.sm', 'San Marino'), (204, '.sn', 'Senegal'), (205, '.so', 'Somalia'), (206, '.sr', 'Suriname'), (207, '.st', 'Sao Tome and Principe'), (208, '.su', 'Soviet Union (being phased out)'), (209, '.sv', 'El Salvador'), (210, '.sy', 'Syrian Arab Republic'), (211, '.sz', 'Swaziland'), (212, '.tc', 'Turks and Caicos Islands'), (213, '.td', 'Chad'), (214, '.tf', 'French Southern Territories'), (215, '.tg', 'Togo'), (216, '.th', 'Thailand'), (217, '.tj', 'Tajikistan'), (218, '.tk', 'Tokelau'), (219, '.tl', 'Timor-Leste'), (220, '.tm', 'Turkmenistan'), (221, '.tn', 'Tunisia'), (222, '.to', 'Tonga'), (223, '.tp', 'East Timor'), (224, '.tr', 'Turkey'), (225, '.tt', 'Trinidad and Tobago'), (226, '.tv', 'Tuvalu'), (227, '.tw', 'Taiwan'), (228, '.tz', 'Tanzania'), (229, '.ua', 'Ukraine'), (230, '.ug', 'Uganda'), (231, '.uk', 'United Kingdom'), (232, '.um', 'United States Minor Outlying Isl'), (233, '.us', 'United States'), (234, '.uy', 'Uruguay'), (235, '.uz', 'Uzbekistan'), (236, '.va', 'Holy See (Vatican City State)'), (237, '.vc', 'Saint Vincent and the Grenadines'), (238, '.ve', 'Venezuela'), (239, '.vg', 'Virgin Islands, British'), (240, '.vi', 'Virgin Islands, U'), (241, '.vn', 'Vietnam'), (242, '.vu', 'Vanuatu'), (243, '.wf', 'Wallis and Futuna Islands'), (244, '.ws', 'Samoa'), (245, '.ye', 'Yemen'), (246, '.yt', 'Mayotte'), (247, '.yu', 'Yugoslavia'), (248, '.za', 'South Africa'), (249, '.zm', 'Zambia'), (250, '.zw', 'Zimbabwe'), (251, '.com', 'operated by VeriSign Global Registry Services'), (252, '.net', 'operated by VeriSign Global Registry Services'), (253, '.biz', 'restricted to businesses'), (254, '.org', ' intended to serve the noncommercial community, but all are elig'), (255, '.aero', 'reserved for members of the air-transport industry'), (256, '.cat', 'reserved for the Catalan linguistic and cultural community'), (257, '.coop', 'reserved for cooperative associations'), (258, '.info', 'operated by Afilias Limited'), (259, '.jobs', 'reserved for human resource managers'), (260, '.mobi', 'reserved for consumers and providers of mobile products and serv'), (261, '.muzeum', 'reserved for museums'), (262, '.name', 'reserved for individuals'), (263, '.pro', 'restricted to credentialed professionals and related entities'), (264, '.travel', 'reserved for entities whose primary area of activity is in the t'), (265, '.edu', 'reserved for postsecondary institutions accredited by an agency '), (266, '.mil', 'reserved exclusively for the United States Military'), (267, '.int', 'used only for registering organizations established by internati'), (268, '.gov', 'reserved exclusively for the United States Government'); CREATE TABLE IF NOT EXISTS `users` ( `user_id` int(10) unsigned NOT NULL auto_increment, `domain_id` mediumint(8) unsigned NOT NULL default '0', `localpart` varchar(192) NOT NULL default '', `username` varchar(255) NOT NULL default '', `clear` varchar(255) default NULL, `crypt` varchar(48) default NULL, `uid` smallint(5) unsigned NOT NULL default '1002', `gid` smallint(5) unsigned NOT NULL default '6', `smtp` text, `pop` varchar(255) default NULL, `type` enum('local','alias','catch','fail','piped','admin','site') NOT NULL default 'local', `admin` tinyint(1) NOT NULL default '0', `on_avscan` tinyint(1) NOT NULL default '0', `on_blocklist` tinyint(1) NOT NULL default '0', `on_complexpass` tinyint(1) NOT NULL default '0', `on_forward` tinyint(1) NOT NULL default '0', `on_piped` tinyint(1) NOT NULL default '0', `on_spamassassin` tinyint(1) NOT NULL default '0', `on_vacation` tinyint(1) NOT NULL default '0', `enabled` tinyint(1) NOT NULL default '1', `flags` varchar(16) default NULL, `forward` varchar(255) default NULL, `unseen` bool default '0', `maxmsgsize` mediumint(8) unsigned NOT NULL default '0', `quota` int(10) unsigned NOT NULL default '0', `realname` varchar(255) default NULL, `sa_tag` smallint(5) unsigned NOT NULL default '0', `sa_refuse` smallint(5) unsigned NOT NULL default '0', `tagline` varchar(255) default NULL, `vacation` varchar(255) default NULL, PRIMARY KEY (`user_id`), UNIQUE KEY `username` (`localpart`,`domain_id`), KEY `local` (`localpart`) ) TYPE=MyISAM ; INSERT INTO `users` (`user_id`, `domain_id`, `localpart`, `username`, `clear`, `crypt`, `uid`, `gid`, `smtp`, `pop`, `type`, `admin`, `on_avscan`, `on_blocklist`, `on_complexpass`, `on_forward`, `on_piped`, `on_spamassassin`, `on_vacation`, `enabled`, `flags`, `forward`, `maxmsgsize`, `quota`, `realname`, `sa_tag`, `sa_refuse`, `tagline`, `vacation`) VALUES (1, 1, 'siteadmin', 'siteadmin', '123465', MD5('123465'), 65535, 65535, '', '', 'site', 1, 0, 0, 0, 0, 0, 0, 0, 1, NULL, NULL, 0, 0, 'SiteAdmin', 60, 600, NULL, NULL);
В дампе предварительно надо поправить значения пользователя и группы, под которыми будет работать Exim (мы раньше их записали, получилось 1002 и 6 соответственно). Останавливаем Sendmail, правим /etc/rc.conf:
# /etc/rc.d/sendmail stop # echo sendmail_enable=\"NONE\" >> /etc/rc.conf # echo exim_enable=\"YES\" >> /etc/rc.conf
И переходим к следующей части нашего сетапа.
Почтовый сервер как у провайдера, часть 1: Exim
Почтовый сервер как у провайдера, часть 2: ClamAV, SpamAssassin, Dovecot
Почтовый сервер как у провайдера, часть 3: Vexim
Почтовый сервер как у провайдера, часть 4: взлетаем
874 thoughts on “Почтовый сервер как у провайдера, часть 1: Exim”
http://advadisk.com/ — where to buy advair
http://advadisk.com/ — advair patent expire
Hey, how are you doing?
I’m 23, from Algorat and i’m just now starting my online currency making journey.
I kill in true-love with making coins online after discovering the hypebeast clothing and shoes resell customer base in 2018. I started buying things i liked and selling them used for the treatment of the nevertheless evaluation i bought it and from there i started wisdom hither reselling.Then youtube started recommending dropshipping and affiliate marketing videos and i got a sales berth at a big retailer here in Portugal and my passion unprejudiced grew wings.
I just started my from the word go dropshipping enterprise in January and i’m planning to construct a label overtime. It is hoped during the course of this year i can moulder it into a money-making brand.
I’m also selling fashionable products on ebay on the side like ring lights, because in my idea this products are too saturated to base a website all over but can still get some trifling profits that i can supply on the real firm I want to grow, without spending my savings.
I plan take doing automated youtube channels too, but haven’t done in profoundly delving yet…
My primary focus at present is dropshipping because it’s what i’ve been studying more in the pattern two of months. but i’m open to any indication, entertain quota in the comments if you call to mind a consider other fields are value to research, as i’m trendy and don’t obtain a collection of acquaintance beside everything.
I want to learn and promote my skills and i have a yen for to better you upon too, so if you’re a mentor or just want you had a familiar that you could piece all your marketing adventures with, like i do, please sock me up! In the point, it’s all everywhere networking and connecting with each other, so receive’s do it!
Hey, how are you doing?
I’m 23, from Algorat and i’m just now starting my online currency making journey.
I cut in true-love with making coins online after discovering the hypebeast clothing and shoes resell sell in 2018. I started buying things i liked and selling them euphemistic pre-owned for the treatment of the unmodified evaluation i bought it and from there i started wisdom about reselling.Then youtube started recommending dropshipping and affiliate marketing videos and i got a sales berth at a big retailer here in Portugal and my passion merely grew wings.
I well-founded started my first dropshipping transaction in January and i’m planning to increase a disgrace overtime. It is hoped as surplus the course of this year i can move it into a fruitful brand.
I’m also selling in vogue products on ebay on the side like cestos lights, because in my thought this products are too saturated to base a website about but can still pick up some trifling profits that i can induct on the material vocation I require to grow, without spending my savings.
I consideration take doing automated youtube channels too, but haven’t done in profoundly enquire yet…
My primary woolly now is dropshipping because it’s what i’ve been studying more in the matrix link of months. but i’m unsigned to any suspicion, divert serving in the comments if you think other fields are merit to explore, as i’m modish and don’t obtain a share of acquaintance encircling everything.
I want to learn and promote my skills and i have a yen for to better you originate too, so if you’re a mentor or fitting want you had a new zealand mate that you could piece all your marketing adventures with, like i do, please smash hit me up! In the end, it’s all close to networking and connecting with each other, so let’s do it!
Do you have a spam problem on this website; I also
am a blogger, and I was curious about your situation; many of us have created some nice practices and
we are looking to exchange methods with other folks, please shoot me an email
if interested.
Hi there, after reading this amazing piece of writing i am as
well glad to share my know-how here with friends.
Wonderful work! This is the type of information that
are meant to be shared across the net. Disgrace on Google for
now not positioning this submit upper! Come on over and talk over with my site .
Thank you =)
If you wish for to take a great deal from this piece of writing then you
have to apply these techniques to your won web site.
It is not my first time to pay a visit this web page, i am browsing this web
site dailly and obtain nice facts from here everyday.
alt com
Wow! At last I got a website from where I be capable of truly take useful data regarding
my study and knowledge.
If you are going for best contents like me, just visit this
site everyday as it offers feature contents, thanks
I’m more than happy to find this website. I want to to thank you for
ones time for this particularly fantastic read!!
I definitely appreciated every bit of it and I have
you saved to fav to check out new information in your web site.
GO!!!
This phrase was said by the first cosmonaut on Earth — Yuri Gagarin. (Yuri Gagarin)
He was the first astronaut on Earth. He was Russian! …
Now Russia is becoming a strong country, gas pipelines, a vaccine against COVID-19, an army.
Is this very reminiscent of the communist Soviet Union?
How do you think?
Now we have total control in our country. I am interested in the opinion of foreigners.
… rolo Gelenter norvatic
ПОЕХАЛИ!!
http://cialinic.com/ — average price of cialis daily
http://cialinic.com/ — can you buy real cialis online
what organs are affecrted by hiv https://sinrecetaes.com/ — comprar viagra espanol
learning how to write essays essay zoo pay someone to do assignment international essay writing competition writing service help writing college papers research paper university resume and cover letter help
synthroid conversion buy synthroid without a prescription effects of stopping synthroid suddenly what if i poop after taking synthroid
Declaration an attempt poetry overhaul with au courant writers is completely noteworthy because an qualified member of the fourth estate can be your specialist in such a business. visit this website
When you upon to look as a replacement for an piece journalism op-ed article services, you forced to reminisce over to read the testimonials and reviews.
This drive come you a excess perspicaciousness of the qualities of the venture writers.
sildenafil 100mg online can you buy strattera online viagra from mexico sildenafil buy online india viagra online pills
sildenafil from india ivermectin 2ml how to get viagra prescription in australia sildenafil 25mg 50mg 100mg viagra for sale paypal online tadalafil 20mg daily cialis prescription prednisone tablets 5mg price generic viagra gel cialis 2.5 mg price
strattera 40 mg pills generic
buy cialis soft tabs online canadian world pharmacy cialis 5mg daily buy online legal online pharmacy coupon code cialis 20mg online
online shopping pharmacy india
cialis 2.5 daily
It’s a shame you don’t have a donate button! I’d definitely donate to this
superb blog! I suppose for now i’ll settle for bookmarking and adding your RSS feed to my Google account.
I look forward to new updates and will talk about
this blog with my Facebook group. Chat soon!
Реальные знакомства https://3nakomctba.ru/id000034.html
Non-specific Dope Far this offshoot
https://ivermectinstrom.com ivermectin
Essay longhand accommodation could be a reassuring in making the paper. Just a approachable, further imagined prospect of try writing, wish have a superb comprehension far the newspaper he desires. Absolutely, both something a shot scribble literary works service and maestro article expos‚ service proffer the famous value. Most affordable Disquisition Poetry Service is usually available. In non-alphabetical to funding the writers of your essay. Any of the piece fiction assistants online must have all the responsibility to insure the individual is capable.
If you’ve establish a exotic newspaper, you should be undisputed that the scribbler is effective of working in your own language. Or you can ordered a crap into done with our latest newspaper guides for. We tender marvy services with no charges, to grab the overcome possible article. These articles are printed for you as a person before our experts at your own home.
https://math-papers.webflow.io/
A notable aspect of theme composing is it is not performed online and in a college. Such reports may be imperative and resolve acceptable be depended upon throughout your entire boarding-school life. Completing your homework in the fashion in which it’s on tap has a influential impact on your analysis results. While composing, we ethical puissance cater you with suitable suggestions instead of your overall composition. Our writers are recognized at hand our customers in place of their amazing skilled which is deemed necessary in their outstanding industry.
Accustomed Message Here this product
https://vidalistawiz.com tadalafil
Decree an theme poetry maintenance with aware writers is very noteworthy because an mavin member of the fourth estate can be your professional in such a business. great post to read
When you umpire fix to look in the interest of an disquisition criticism services, you must think back on to read the testimonials and reviews. This drive come you a celebrated vision of the qualities of the essay writers.
mirtazapine for dogs mirtazapine moa mirtazapine 30mg tablet
free dating near you
female dating profile examples
Decree an attempt theme overhaul with knowledgeable writers is completely important because an qualified writer can be your professional in such a business.
When you umpire fix to look as a replacement for an make an effort writing services, you must remember to read the testimonials and reviews. This drive
https://essayformea.losblogos.com/5101889/a-simple-key-for-online-assignment-service-unveiled gross you a celebrated insight of the qualities of the try writers.
Accustomed Message Fro this by-product
https://albuterolday.com buy asthma inhalers without an rx
3D Игровые автоматы в казино онлайн — доступ для всех без исключения без исключения желающих и только по демо-счетам. Деньги реально выводить из казино на настоящие счета в каждых платежных системах, браузерные слоты на денежные средства, казино, лотерея и много прочего.
http://womensretreat.fbcglenarden.org/2020/09/17/internet-kazino-v-internete-168/|
Accustomed Dope Far this by-product
https://stromectolivermect.com stromectol
https://ivermectinstrom.com is stromectol over the counter
https://ivermectstromect.com ivermectin horse paste for humans
https://ivermectinsts.com ivermectin australia
https://ivermectinst.com avermectin
General Dope Here this outcome
https://ivermectstromect.com que es la ivermectina
https://stromectolivermect.com stromectol canada
https://ivermectinsts.com buy 3 mg ivermectin tablets
https://ivermectinsts.com ivermectin 3 mg
https://ivermectinst.com ivermectin 12 mg
Hmm is anyone else experiencing problems with the images on this blog
loading? I’m trying to figure out if its a problem on my end or if it’s the blog.
Any feed-back would be greatly appreciated.
General Low-down Fro this outcome
https://ivermectinst.com ivermectina efectos secundarios
https://ivermectinst.com ivermectina precio
https://stromectolivermect.com ivermectin dosage
https://ivermectstromect.com ivermectin 6 mg
https://ivermectstromect.com ivermectin 12 mg
Hello, for all time i used to check webpage posts here early
in the dawn, as i enjoy to find out more and more.
I’d like to find out more? I’d want to find out some additional information.
canada viagra otc
Appreciating the persistence you put into your site and in depth information you present.
It’s nice to come across a blog every once in a while that isn’t the same outdated rehashed information. Wonderful read!
I’ve bookmarked your site and I’m adding your RSS feeds to my
Google account.
buy cheap sildenafil online viagra pfizer 100mg viagra for sale mexico viagra online india buy medicine tadalafil tablets
Идеи для дачи в фотографиях https://pro-dachnikov.com/
Thankfulness to my father who informed me on the topic of this web
site, this website is genuinely amazing.
Дачные идеи в фотографиях https://pro-dachnikov.com/
of course like your web-site however you have to
check the spelling on several of your posts.
Several of them are rife with spelling problems and I
in finding it very troublesome to tell the truth nevertheless I’ll definitely come again again.