[Exim-rusers] message_size_limit в транспорте

286 views
Skip to first unread message

Dmitry Chertischev

unread,
May 24, 2007, 3:41:15 AM5/24/07
to CIS Exim users mailing list
exim-4.67.

Добавил в транспорт appendfile message_size_limit = 100K
При отправке письма размером более 100Кб отправителю возвращается
невнятный отлуп:

A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:

save to /
generated by ad...@test1.visla.pp.ru

Т.е. причина отлупа не указывается, хотя в лог пишет нормальную диагностику:
T=virtual_delivery: message is too big (transport limit = 102400)

Можно ли сделать так, чтобы и в отлупе было сказано "message is too big"?

Дмитрий


_______________________________________________
exim-users mailing list
exim-...@exim.org.ua
http://exim.org.ua/mailman/listinfo/exim-users

Dmitry Chertischev

unread,
May 24, 2007, 4:22:37 AM5/24/07
to CIS Exim users mailing list
Dmitry Chertischev wrote:
> exim-4.67.
>
> Добавил в транспорт appendfile message_size_limit = 100K
> При отправке письма размером более 100Кб отправителю возвращается
> невнятный отлуп:
>
> A message that you sent could not be delivered to one or more of its
> recipients. This is a permanent error. The following address(es) failed:
>
> save to /
> generated by ad...@test1.visla.pp.ru
>
> Т.е. причина отлупа не указывается, хотя в лог пишет нормальную диагностику:
> T=virtual_delivery: message is too big (transport limit = 102400)
>
> Можно ли сделать так, чтобы и в отлупе было сказано "message is too big"?
>

Задача такая. Есть почтовые ящики, причем каждый ящик представляет из
себя алиас. Ящик может алиасится в / (тогода redirect роутер передает
его в транспорт), либо алиасится на другой адрес.
Требется дать возможность пользователям устанавливать макс. размер
входящего письма. Через ACL сделать не получится, поскольку на этом
этапе мы не знаем конечный ящик получателя.
Сначала думал сделать через транспорт с опцией message_size_limit.
Но может лучше добавить еще один редирект роутер?
Типа того:

condition = не превышает ли размер письма макс. размер письма для
конкретного ящика
data = :fail: message is too big

Наверное через роутер даже лучше. Можно будет на этапе ACL проверять
через verify = recipient

Alexander Shikoff

unread,
May 24, 2007, 4:30:51 AM5/24/07
to CIS Exim users mailing list

Вы сами ставите задачу и даете ее решение :)

Я делал в точности так, как Вы описываете:

MYSQL_SZ_IN_MSG_MAX=${lookup mysql{SELECT `max_in_msg_size` FROM `mailboxes` INNER JOIN `domains` ON `domains`.`id` = `mailboxes`.`domain_id` WHERE `mailboxes`.`login` = '${quote_mysql:$local_part}' AND `domains`.`name` = '${quote_mysql:$domain}' LIMIT 1}{$value}}

virtual_user_deny:
driver = redirect
domains = +virtual_domains
condition = ${if and {\
{>{MYSQL_SZ_IN_MSG_MAX}{0}}\
{>{$message_size}{MYSQL_SZ_IN_MSG_MAX}}\
} }
data = :fail:Cannot accept message with body size $message_body_size bytes for recipient $local_part@$domain (max MYSQL_SZ_IN_MSG_MAX bytes)
allow_fail

Есть одно примечание. Этот роутер сработает с verify recipient только тогда,
когда размер письма известен до DATA. А не все релеи сообщают размер письма
на этапе MAIL FROM/RCPT TO. Иначе $message_size останется неопределенным,
и прийдется принять письмо полностью, чтобы узнать его размер.

--
Kind Regards, Alexander Shikoff
mino...@crete.org.ua
Mob.: +380 67 946 31 49

Dmitry Chertischev

unread,
May 24, 2007, 4:35:36 AM5/24/07
to CIS Exim users mailing list
> Я делал в точности так, как Вы описываете:
>
> MYSQL_SZ_IN_MSG_MAX=${lookup mysql{SELECT `max_in_msg_size` FROM `mailboxes` INNER JOIN `domains` ON `domains`.`id` = `mailboxes`.`domain_id` WHERE `mailboxes`.`login` = '${quote_mysql:$local_part}' AND `domains`.`name` = '${quote_mysql:$domain}' LIMIT 1}{$value}}
>
> virtual_user_deny:
> driver = redirect
> domains = +virtual_domains
> condition = ${if and {\
> {>{MYSQL_SZ_IN_MSG_MAX}{0}}\
> {>{$message_size}{MYSQL_SZ_IN_MSG_MAX}}\
> } }
> data = :fail:Cannot accept message with body size $message_body_size bytes for recipient $local_part@$domain (max MYSQL_SZ_IN_MSG_MAX bytes)
> allow_fail

Во, так я себе и представлял :)

>
> Есть одно примечание. Этот роутер сработает с verify recipient только тогда,
> когда размер письма известен до DATA. А не все релеи сообщают размер письма
> на этапе MAIL FROM/RCPT TO. Иначе $message_size останется неопределенным,
> и прийдется принять письмо полностью, чтобы узнать его размер.

Это да.

Дмитрий

Дмитрий

unread,
May 25, 2007, 4:04:41 AM5/25/07
to exim-...@exim.org.ua
Если ты собираешься проверять входящие сообщения на message-size, то
необходимо 2 проверки:

1. В acl_smtp_rcpt:
# Определяем лимит сообщения
warn set acl_m1 = ${lookup mysql{MYSQL_SIZEMESS}{${value}${lookup mysql{MYSQL_IN_UNIT}{${value}}}}{DEFAULT_SIZE_LIMIT}}

deny message = Too big size of message. Incoming message size limit = $acl_m1.
domains = +local_domains
condition = ${if > {$message_size}{$acl_m1}}

# В acl_check_data: не работает проверка доменов. В переменной будет домен, если он наш, иначе пустая.
warn set acl_m3 = ${lookup mysql{MYSQL_DOMAINS}}

2. В acl_smtp_data:
# Ограничения на приём сообщения , если сообщение больше определённого размера не принимаем.
deny message = Too big size of message. Incoming message size limit = $acl_m1
condition = ${if or {{eq{domain.ru}{$acl_m3}}{eq{domain2}{$acl_m3}}}{yes}{no}}
condition = ${if > {$message_size}{$acl_m1}}


Есть esmtpa, который передают размер сообщения при отправке и
smtp, в котором это значение будет после приёма сообщения.

igor

unread,
May 25, 2007, 4:36:56 AM5/25/07
to CIS Exim users mailing list
Здравствуйте.

Вы писали 24 мая 2007 г., 12:30:51:

AS> virtual_user_deny:
AS> driver = redirect
AS> domains = +virtual_domains
AS> condition = ${if and {\
AS> {>{MYSQL_SZ_IN_MSG_MAX}{0}}\
AS>
AS> {>{$message_size}{MYSQL_SZ_IN_MSG_MAX}}\
AS> } }
AS> data = :fail:Cannot accept message with body
AS> size $message_body_size bytes for recipient
AS> $local_part@$domain (max MYSQL_SZ_IN_MSG_MAX bytes)
AS> allow_fail

Не могли бы вы объяснить, почему такой хитрый condition ?
Почему там конструкция MYSQL_SZ_IN_MSG_MAX два раза прописана ?
Ведь в этом случае - запрос вроде будет дважды выполнен ?
Можно-ли как-то упростить, например - передав в запрос $message_size и
что бы запрос вернул (или не вернул) записи, которые попадают под
ограничение по размеру ? Понятно, что в этом случае ограничение будет
срабатывать только после приема письма, но мне в принципе так и
надо...

Dmitry Chertischev

unread,
May 25, 2007, 4:39:54 AM5/25/07
to igor, CIS Exim users mailing list
igor wrote:
> Здравствуйте.
>
> Вы писали 24 мая 2007 г., 12:30:51:
>
> AS> virtual_user_deny:
> AS> driver = redirect
> AS> domains = +virtual_domains
> AS> condition = ${if and {\
> AS> {>{MYSQL_SZ_IN_MSG_MAX}{0}}\
> AS>
> AS> {>{$message_size}{MYSQL_SZ_IN_MSG_MAX}}\
> AS> } }
> AS> data = :fail:Cannot accept message with body
> AS> size $message_body_size bytes for recipient
> AS> $local_part@$domain (max MYSQL_SZ_IN_MSG_MAX bytes)
> AS> allow_fail
>
> Не могли бы вы объяснить, почему такой хитрый condition ?
> Почему там конструкция MYSQL_SZ_IN_MSG_MAX два раза прописана ?
> Ведь в этом случае - запрос вроде будет дважды выполнен ?
> Можно-ли как-то упростить, например - передав в запрос $message_size и
> что бы запрос вернул (или не вернул) записи, которые попадают под
> ограничение по размеру ? Понятно, что в этом случае ограничение будет
> срабатывать только после приема письма, но мне в принципе так и
> надо...
>

Не будет запрос 2 раза выполнен. exim закэширует данные после первого
запроса и при потоврном вызове MYSQL_SZ_IN_MSG_MAX просто возьмет данные
их кэша.

Дмитрий

Alexander Shikoff

unread,
May 25, 2007, 4:47:46 AM5/25/07
to CIS Exim users mailing list
On Fri, May 25, 2007 at 12:36:56PM +0400, igor wrote:
> Здравствуйте.
>
> Вы писали 24 мая 2007 г., 12:30:51:
>
> AS> virtual_user_deny:
> AS> driver = redirect
> AS> domains = +virtual_domains
> AS> condition = ${if and {\
> AS> {>{MYSQL_SZ_IN_MSG_MAX}{0}}\
> AS>
> AS> {>{$message_size}{MYSQL_SZ_IN_MSG_MAX}}\
> AS> } }
> AS> data = :fail:Cannot accept message with body
> AS> size $message_body_size bytes for recipient
> AS> $local_part@$domain (max MYSQL_SZ_IN_MSG_MAX bytes)
> AS> allow_fail
>
> Не могли бы вы объяснить, почему такой хитрый condition ?
> Почему там конструкция MYSQL_SZ_IN_MSG_MAX два раза прописана ?
Потому что если MYSQL_SZ_IN_MSG_MAX возвращает 0, то в моей реализации
это значит, что ограничений нет.

> Ведь в этом случае - запрос вроде будет дважды выполнен ?

Не будет. exim кеширует результаты выполнения SQL-запросов.

--
Kind Regards, Alexander Shikoff
mino...@crete.org.ua
Mob.: +380 67 946 31 49

_______________________________________________

igor

unread,
May 25, 2007, 4:54:15 AM5/25/07
to CIS Exim users mailing list
DC> Не будет запрос 2 раза выполнен. exim закэширует данные после первого
DC> запроса и при потоврном вызове MYSQL_SZ_IN_MSG_MAX просто возьмет данные
DC> их кэша.

Все равно как-то непонятно. Вот текст запроса:


MYSQL_SZ_IN_MSG_MAX=${lookup mysql{SELECT `max_in_msg_size` FROM `mailboxes` INNER JOIN `domains` ON `domains`.`id` =
`mailboxes`.`domain_id` WHERE `mailboxes`.`login` = '${quote_mysql:$local_part}' AND `domains`.`name` =
'${quote_mysql:$domain}' LIMIT 1}{$value}}

Для чего нужен LIMIT 1 ? Ведь по идее - при такой постановки условия
в WHERE - запрос и так должен вернуть одну запись.
Я просто хочу разобратьсЯ, так как мне необходимо прикрутить тоже
проверку на размер письма, но таблицы и поля в MySQL для Exim-а у
меня по другому устроены.

Alexander Shikoff

unread,
May 25, 2007, 5:00:57 AM5/25/07
to CIS Exim users mailing list
On Fri, May 25, 2007 at 12:54:15PM +0400, igor wrote:
> DC> Не будет запрос 2 раза выполнен. exim закэширует данные после первого
> DC> запроса и при потоврном вызове MYSQL_SZ_IN_MSG_MAX просто возьмет данные
> DC> их кэша.
>
> Все равно как-то непонятно. Вот текст запроса:
> MYSQL_SZ_IN_MSG_MAX=${lookup mysql{SELECT `max_in_msg_size` FROM `mailboxes` INNER JOIN `domains` ON `domains`.`id` =
> `mailboxes`.`domain_id` WHERE `mailboxes`.`login` = '${quote_mysql:$local_part}' AND `domains`.`name` =
> '${quote_mysql:$domain}' LIMIT 1}{$value}}
>
> Для чего нужен LIMIT 1 ? Ведь по идее - при такой постановки условия
> в WHERE - запрос и так должен вернуть одну запись.
Такая форма запроса - особенности реализации. LIMIT 1 - дополнительная
защита от случайностей.

--
Kind Regards, Alexander Shikoff
mino...@crete.org.ua
Mob.: +380 67 946 31 49

_______________________________________________

igor

unread,
May 25, 2007, 6:07:30 AM5/25/07
to CIS Exim users mailing list
>> Не могли бы вы объяснить, почему такой хитрый condition ?
>> Почему там конструкция MYSQL_SZ_IN_MSG_MAX два раза прописана ?
AS> Потому что если MYSQL_SZ_IN_MSG_MAX возвращает 0, то в моей реализации
AS> это значит, что ограничений нет.

Понятно. Я сделаю попроще - изначально установлю какой-нить лимит -
думаю - 25Мб на письмо хватит.

Reply all
Reply to author
Forward
0 new messages