Сервер в кармане, или просто о сложном!

главная - Статьи - Почта - Sendmail



Копирование почты с помощью sendmail

Теги: sendmail

Нижеизложенный материал не претендует на полноту, четкость, ясность или достоверность изложения и предоставляется автором "КАК ЕСТЬ". Автор не несет никакой отвественности за любое использование данного материала. Любое использование, копирование, цитирование, полностью или частично должно включать данный текст, ссылку на данный ресурс, а так же следующию строку без изменений:


Принцип работы копирования почтовых сообщений с помощью sendmail, описанный в данной статье, состоит в описании своего майлера(mailer), называемого в дальнейшем copymail, а так же в задании набора правил, который "передает" всю проходящую почту на наш майлер. Copymail, получив почтовое сообщение, действует как обычный транспортный агент, доставляя письмо оригинальному получателю, а так же на дополнительный адрес, заданный администратором. Почтовый адрес, на который будет копироваться почта, не обязательно должен быть локальным для данной машины. Описанный майлер (copymail) представляет из себя sendmail с "оригинальным" (без изменений) конфигурационным файлом.

sendmail(1), работающий в режиме daemon (-bd) получает (A) письмо и передает (B) его sendmail(2). ( sendmail(2) — это вышеописанный майлер copymail). sendmail(2) отсылает письмо оригинальному получателю (C) и дополнительному получателю (D).

Далее описаны несколько вариантов, конфигурации sendmail, для различных требований к копированию почтовых сообщений.
При описании, автор подразумевает, что читатель обладает некоторым "специфическим" набором знаний, а именно:

  • знает что такое sendmail :) .
  • знает что такое m4.
  • умеет из .mc файла получить .cf.
  • знает где находится ${CFDIR}.
  • знает куда должны помещаться конфигурационные файлы sendmail.

Вариант 1.
(C одним конфигурационным файлом sendmail)

  • Следует поместить файл copymail.m4 (Вариант 1)¹ в директорию ${CFDIR}/mailer.
  • В файл конфигурации sendmail (.mc) добавить² следующие строчки:
    	define(`COPYMAIL_MAILBOX',`user@domen')
    	MAILER(copymail)
    заменив 'user@domen' на пользователя который должен получать копии всех сообщений (он не обязательно должен быть локальным пользователем на данной машине).
  • Скомпилировать и установить новый конфиг.
  • Перезапустить sendmail.

Вся проходящая почта будет (дополнительно) пересылаться на заданный почтовый адрес.

Недостатки:

  • В логах будут сообщения вида: Oct 11 15:59:54 mx.domen.ru sendmail[9151]: g1EsNvk01649: to=user2@somewere.com.COPYMAIL ... .
  • При генерации уведомлений об ошибках доставки, в сообщениях будут указываться адреса вида user@domen.COPYMAIL.

¹. В этом и последующих примерах можно помещать строки из copymail.m4 непосредственно в конфигурационный файл sendmail(.mc), не забывая о правильном порядке директив.
². MAILER следует помещать в конце конфигурационного файла, а define — до MAILER.


Вариант 2.
(C двумя конфигурационными файлами sendmail)

  • Следует поместить copymail.m4 (Вариант 2) в директорию ${CFDIR}/mailer
  • Скопируйте ваш конфигурационный файл sendmail (.mc) в файл под именем sendmail.copy.mc
  • Добавить следующие строчки в файл sendmail.copy.mc:
    	define(`COPYMAIL_MAILBOX',`user@domen')
    	define(`NOCOPY_CONFIG',`/etc/mail/sendmail.cf')
    	MAILER(copymail)
  • Скомпилировать sendmail.copy.mc и установить как sendmail.copy.cf
  • Остановить sendmail и запустить, следующим образом:
    	/usr/sbin/sendmail -bd -C /etc/mail/sendmail.copy.cf
    	/usr/sbin/sendmail -q30m -C /etc/mail/sendmail.cf
    
    N.B. Такой запуск sendmail необходим для того, что бы письмо, находящееся в очереди не копировалось каждые N минут, при каждой попытке доставки. Первая копия (-bd) работает как SMTP daemon, принимая письма (и копируя их). Вторая копия (-q30) работает обработчиком (queueing) очереди, доставляя письма находящиеся в очереди (и не копируя их, так как перед тем как попасть в очередь письма уже были скопированы).

ВНИМАНИЕ! Если вы допустите ошибку при конфигурировании sendmail (например вместо конфигурационного файла "nocopy", вы укажете "copy"), sendmail уйдет в "вечный" цикл, с доставкой писем самой себе и с потреблением всех ресурсов системы.


Вариант 3.
(C возможностью избирательно копировать почту)

Желательно иметь возможность как то управлять процессом копирования почты. Например, избирательно копировать сообщения от какой либо группы пользователей или наоборот — не копировать. Для этого предназначен copymail.m4 (Вариант 3). Sendmail следует сконфигурировать как по Варианту 2, только вместо copymail.m4 (Вариант 2) возьмите copymail.m4 (Вариант 3)

Следует, так же создать файл /etc/mail/nocopy-users и поместить в него почтовые адреса (в виде user@FQDN-domen ) или IP адреса (в форме X.X.X.X). Почтовые сообщения приходящие на почтовые адреса¹, перечисленные в /etc/mail/nocopy-users или отправлямые от почтового адреса² или с IP адреса, перечисленных в /etc/mail/nocopy-users, не будут копироваться.

Для достижения обратного результата, т.е. копирования почтовых сообщений от определенных почтовых адресов или на определенные почтовые адреса, и прохождения всех остальных почтовых сообщений без копирования, следует воспользоваться copymail.m4 (Вариант 4).
Так же, следует создать файл /etc/mail/copy-users и поместить в него "копируемые" адреса (формат адресов см. выше).

¹. Имеется в виду rcpt to: <addr>
². Имеется в виду mail from: <addr>

Тестирование и отладка.

Прежде чем запускать sendmail в "боевом" режиме, я советую проверить полученную конфигурацию. Для этого следует запустить sendmail в режиме тестирования адреса (ключ -bt). Рассмотрим результат преобразования адреса, который должен получиться при использовании copymail.m4 (Вариант 1):

mx# sendmail -bt -C /etc/mail/sendmail.cf
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> 3,0 user@domen.ru
canonify           input: user @ domen . ru
Canonify2          input: user < @ domen . ru >
Canonify2        returns: user < @ domen . ru . >
canonify         returns: user < @ domen . ru . >
parse              input: user < @ domen . ru . >
Parse0             input: user < @ domen . ru . >
Parse0           returns: user < @ domen . ru . >
ParseLocal         input: user < @ domen . ru . >
ParseLocal       returns: $# copymail $@ domen . ru . COPYMAIL $: user @ domen . ru . COPYMAIL
parse            returns: $# copymail $@ domen . ru . COPYMAIL $: user @ domen . ru . COPYMAIL
>

В результате должен вызваться майлер copymail и адрес должен переписаться в виде user@domen.ru.COPYMAIL. Теперь следует проверить "обратное" преобразование, т.е. письмо принятое от copymail должно разрешиться в "нормальный" адрес:

> 3,0 user@domen.ru.COPYMAIL
canonify           input: user @ domen . ru . COPYMAIL
Canonify2          input: user < @ domen . ru . COPYMAIL >
Canonify2        returns: user < @ domen . ru . COPYMAIL >
canonify         returns: user < @ domen . ru . COPYMAIL >
parse              input: user < @ domen . ru . COPYMAIL >
Parse0             input: user < @ domen . ru . COPYMAIL >
Parse0           returns: user < @ domen . ru . COPYMAIL >
ParseLocal         input: user < @ domen . ru . COPYMAIL >
ParseLocal       returns: user < @ domen . ru . >
Parse1             input: user < @ domen . ru . >
MailerToTriple     input: < > user < @ domen . ru . >
MailerToTriple   returns: user < @ domen . ru . >
Parse1           returns: $# esmtp $@ domen . ru . $: user < @ domen . ru . >
parse            returns: $# esmtp $@ domen . ru . $: user < @ domen . ru . >
>

В результате адрес должен разрешиться в один из майлеров, кроме copymail. К примеру адрес может разрешиться в локальный майлер ($# local $: user) или в майлер esmtp ($# esmtp $@ domen . ru . $: user < @ domen . ru . >).

Теперь рассмотрим результат преобразования адреса при использовании copymail.m4 (Вариант 2 (3,4)):

mx# sendmail -bt -C /etc/mail/sendmail.copy.cf
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> 3,0 user@domen.ru
canonify           input: user @ domen . ru
Canonify2          input: user < @ domen . ru >
Canonify2        returns: user < @ domen . ru . >
canonify         returns: user < @ domen . ru . >
parse              input: user < @ domen . ru . >
Parse0             input: user < @ domen . ru . >
Parse0           returns: user < @ domen . ru . >
ParseLocal         input: user < @ domen . ru . >
ParseLocal       returns: $# copymail $@ localhost $: user < @ domen . ru . >
parse            returns: $# copymail $@ localhost $: user < @ domen . ru . >
>

В результате должен вызваться майлер copymail: $# copymail $@ localhost $: user < @ domen . ru . >.

 

Если в результате тестирования адресов у вас не получается то, что вы ожидаете, например используется copymail.m4 (Вариант 3), пользователь user@domen.ru включен в /etc/mail/nocopy-users, а в результате почта для этого пользователя все равно копируется, то попробуйте воспользоваться следующими рекомендациями:

  • Не забывайте перезапускать sendmail после установки нового конфигурационного файла.
  • Не забывайте перезапускать sendmail после изменения списка адресов в файлах /etc/mail/nocopy-users или /etc/mail/copy-users.
  • Не забывайте что правая и левая части в правилах подстановки (R) отделяются табуляцией.
  • Проверьте что вы правильно указали sendmail файл /etc/mail/nocopy-users и sendmail загрузил список в класс NOCOPY. (Конструкция $={NOCOPY} позволяет просмотреть содержимое класса).
    mx# sendmail -bt -C /etc/mail/sendmail.copy.cf
    ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
    Enter <ruleset> <address>
    > $={NOCOPY}
    > user@domen.ru
    >
    
  • Поробуйте воспользоваться отладочным режимом (-d) sendmail, что бы получить больше информации о процессе преобразования адресов:
    mx# sendmail -bt -d21.12 -C /etc/mail/sendmail.copy.cf
    ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
    Enter <ruleset> <address>
    > 3,0 user@domen.ru
    ...
    -----callsubr ParseLocal (98)
    ParseLocal         input: user < @ domen . ru . >
    -----trying rule: $* < @ $+ . > $*
    -----rule matches: $: $1 < @ $2 . > $3 $| $1 @ $2
    rewritten as: user < @ domen . ru . > $| user @ domen . ru
    -----trying rule: $* < @ $+ . > $* $| $={NOCOPY}
    -----rule matches: $@ $1 < @ $2 . > $3
    rewritten as: user < @ domen . ru . >
    ParseLocal       returns: user < @ domen . ru . >
    rewritten as: user < @ domen . ru . >
    ...
    parse            returns: $# local $: user
    >
    

 


Privacy violation.
(Морально-этические стороны вопроса)

Копирование почты является нарушением морально-этических (а возможно даже и юридических) прав, если только пользователь не был предупрежден об этом до начала процесса копирования почты (а ещё лучше до того как получил почтовый ящик)... Предлагаемый ниже вариант copymail.m4 позволяет вставить в каждое копируемое письмо некоторый заголовок (например назовем его X-Privacy-violation), в котором будет честно сказано что данное письмо было скопировано, а так же будет указано кому и зачем оно было скопировано. По такому же принципу можно изменить/дополнить один из стандарных заголовков, например To: или Subject:.

...
Received: (from user@localhost)
	by mx.domen.ru ESMTP id g1KEPD001282
	for user2@domen.ru; Wed, 20 Feb 2002 17:25:13 +0300 (MSK)
	(envelope-from user)
Date: Wed, 20 Feb 2002 17:25:13 +0300 (MSK)
From: User 

Другие варианты copymail.m4 следует дополнить по аналогии с приведенным примером.

 


copymail.m4 (Вариант 1):

PUSHDIVERT(-1)

ifdef(`COPYMAIL_MAILBOX',,
`define(`COPYMAIL_MAILBOX', `postmaster')')dnl
POPDIVERT

#########################################
### COPYMAIL Mailer specification ###
#########################################

VERSIONID(`$Id: cpsendmail.html,v 1.2 2002/06/14 18:39:10 freeman Exp $')dnl

LOCAL_CONFIG
D{COPYMAIL}COPYMAIL
C{CP}${COPYMAIL}

LOCAL_RULE_0
# Send all mail to copymail mailer
R$* < @ $+ . $~{CP} . > $#copymail $@ $2 . $3 . ${COPYMAIL} $: $1 @ $2 . $3 . ${COPYMAIL}
# if mail has been processed by copymail mailer, process it usual way...
R$* < @ $* . ${COPYMAIL} > $1 < @ $2 . >

# Send message to original recipient + additional mailbox: COPYMAIL_MAILBOX
Mcopymail, P=/usr/sbin/sendmail, F=fmSDFMu, S=0, R=0,
A=sendmail -N never COPYMAIL_MAILBOX.${COPYMAIL} $u

copymail.m4 (Вариант 2):

PUSHDIVERT(-1)

ifdef(`COPYMAIL_MAILBOX',,
`define(`COPYMAIL_MAILBOX', `postmaster')')dnl

ifdef(`NOCOPY_CONFIG',,
`errprint(`*** You must define NOCOPY_CONFIG for copymail mailer!!! ***')')dnl

POPDIVERT
#########################################
### COPYMAIL Mailer specification ###
#########################################

VERSIONID(`$Id: cpsendmail.html,v 1.2 2002/06/14 18:39:10 freeman Exp $')dnl

LOCAL_RULE_0
# Send all mail to copymail mailer
R$* < @ $+ . > $* $#copymail $@ localhost $: $1 < @ $2 . > $3

# Send message to original recipient + additional mailbox: COPYMAIL_MAILBOX
Mcopymail, P=/usr/sbin/sendmail, F=fmSDFMu, S=0, R=0,
A=sendmail -N never -C NOCOPY_CONFIG COPYMAIL_MAILBOX $u

copymail.m4 (Вариант 3):

PUSHDIVERT(-1)

ifdef(`COPYMAIL_MAILBOX',,
`define(`COPYMAIL_MAILBOX', `postmaster')')dnl

ifdef(`NOCOPY_USERS',,
`define(`NOCOPY_USERS', `-o /etc/mail/nocopy-users')')dnl

ifdef(`NOCOPY_CONFIG',,
`errprint(`*** You must define NOCOPY_CONFIG for copymail mailer!!! ***')')dnl

POPDIVERT
#########################################
### COPYMAIL Mailer specification ###
#########################################

VERSIONID(`$Id: cpsendmail.html,v 1.2 2002/06/14 18:39:10 freeman Exp $')dnl

LOCAL_CONFIG
F{NOCOPY}NOCOPY_USERS

LOCAL_RULE_0
# Send all mail (except $={NOCOPY}) to copymail mailer
R$* < @ $+ . > $* $: $1 < @ $2 . > $3 $| $1 @ $2
R$* < @ $+ . > $* $| $={NOCOPY} $@ $1 <@ $2 . > $3
R$* < @ $+ . > $* $| $* $: $1 <@ $2 . > $3 $| $&{client_addr}
R$* < @ $+ . > $* $| $={NOCOPY} $@ $1 <@ $2 . > $3
R$* < @ $+ . > $* $| $* $: $1 <@ $2 . > $3 $| $&f
R$* < @ $+ . > $* $| <$*> $: $1 <@ $2 . > $3 $| $4
R$* < @ $+ . > $* $| $={NOCOPY} $@ $1 <@ $2 . > $3
R$* < @ $+ . > $* $| $* $#copymail $@ localhost $: $1 < @ $2 . > $3

# Send message to original recipient + additional mailbox: COPYMAIL_MAILBOX
Mcopymail, P=/usr/sbin/sendmail, F=fmSDFMu, S=0, R=0,
A=sendmail -N never -C NOCOPY_CONFIG COPYMAIL_MAILBOX $u

copymail.m4 (Вариант 4):

PUSHDIVERT(-1)

ifdef(`COPYMAIL_MAILBOX',,
`define(`COPYMAIL_MAILBOX', `postmaster')')dnl

ifdef(`COPY_USERS',,
`define(`COPY_USERS', `-o /etc/mail/copy-users')')dnl

ifdef(`NOCOPY_CONFIG',,
`errprint(`*** You must define NOCOPY_CONFIG for copymail mailer!!! ***')')dnl

POPDIVERT
#########################################
### COPYMAIL Mailer specification ###
#########################################

VERSIONID(`$Id: cpsendmail.html,v 1.2 2002/06/14 18:39:10 freeman Exp $')dnl

LOCAL_CONFIG
F{COPY}COPY_USERS

LOCAL_RULE_0
# Send mail $={COPY} to copymail mailer
R$* < @ $+ . > $* $: $1 < @ $2 . > $3 $| $1 @ $2
R$* < @ $+ . > $* $| $={COPY} $#copymail $@ localhost $: $1 < @ $2 . > $3
R$* < @ $+ . > $* $| $* $: $1 <@ $2 . > $3 $| $&{client_addr}
R$* < @ $+ . > $* $| $={COPY} $#copymail $@ localhost $: $1 < @ $2 . > $3
R$* < @ $+ . > $* $| $* $: $1 <@ $2 . > $3 $| $&f
R$* < @ $+ . > $* $| <$*> $: $1 <@ $2 . > $3 $| $4
R$* < @ $+ . > $* $| $={COPY} $#copymail $@ localhost $: $1 < @ $2 . > $3
R$* < @ $+ . > $* $| $* $: $1 <@ $2 . > $3

# Send message to original recipient + additional mailbox: COPYMAIL_MAILBOX
Mcopymail, P=/usr/sbin/sendmail, F=fmSDFMu, S=0, R=0,
A=sendmail -N never -C NOCOPY_CONFIG COPYMAIL_MAILBOX $u

copymail.m4 (Вариант 5):

PUSHDIVERT(-1)

ifdef(`COPYMAIL_MAILBOX',,
`define(`COPYMAIL_MAILBOX', `postmaster')')dnl

ifdef(`NOCOPY_CONFIG',,
`errprint(`*** You must define NOCOPY_CONFIG for copymail mailer!!! ***')')dnl

POPDIVERT
#########################################
### COPYMAIL Mailer specification ###
#########################################

VERSIONID(`$Id: cpsendmail.html,v 1.2 2002/06/14 18:39:10 freeman Exp $')dnl

LOCAL_CONFIG
H?{COPIED}?X-Privacy-violation: The copy of this message was sent to <COPYMAIL_MAILBOX> due to business requirements
Kiscopied macro

LOCAL_RULE_0
# Send all mail to copymail mailer
R$* < @ $+ . > $* $#copymail $@ localhost $: $1 < @ $2 . > $3 $(iscopied {COPIED} $@ YES $)

# Send message to original recipient + additional mailbox: COPYMAIL_MAILBOX
Mcopymail, P=/usr/sbin/sendmail, F=fmSDFMu, S=0, R=0,
A=sendmail -N never -C NOCOPY_CONFIG COPYMAIL_MAILBOX $u

Расположение ${CFDIR} в некоторых OS:

Solaris /usr/lib/mail
Linux /usr/lib/sendmail-cf
FreeBSD /usr/share/sendmail/cf

Список литературы:



Авторизуйтесь для добавления комментариев!


    забыли пароль?    новый пользователь?