Нижеизложенный материал не претендует на полноту, четкость, ясность или достоверность изложения и предоставляется автором "КАК ЕСТЬ". Автор не несет никакой отвественности за любое использование данного материала. Любое использование, копирование, цитирование, полностью или частично должно включать данный текст, ссылку на данный ресурс, а так же следующию строку без изменений: |
© 2001-2002, O. Koreshkov <okorsalut.ru>. |
Принцип работы копирования почтовых сообщений с помощью sendmail, описанный в данной статье, состоит в описании своего майлера(mailer), называемого в дальнейшем copymail, а так же в задании набора правил, который "передает" всю проходящую почту на наш майлер. Copymail, получив почтовое сообщение, действует как обычный транспортный агент, доставляя письмо оригинальному получателю, а так же на дополнительный адрес, заданный администратором. Почтовый адрес, на который будет копироваться почта, не обязательно должен быть локальным для данной машины. Описанный майлер (copymail) представляет из себя sendmail с "оригинальным" (без изменений) конфигурационным файлом.
Рис. 1
sendmail(1), работающий в режиме daemon (-bd) получает (A) письмо и передает (B) его sendmail(2). ( sendmail(2) — это вышеописанный майлер copymail). sendmail(2) отсылает письмо оригинальному получателю (C) и дополнительному получателю (D).
Далее описаны несколько вариантов, конфигурации sendmail, для различных требований к копированию почтовых сообщений.
При описании, автор подразумевает, что читатель обладает некоторым "специфическим" набором знаний, а именно:
define(`COPYMAIL_MAILBOX',`user@domen')
MAILER(copymail)
заменив 'user@domen' на пользователя который должен получать копии всех сообщений
(он не обязательно должен быть локальным пользователем на данной машине).
Недостатки:
¹. В этом и последующих примерах можно помещать строки из copymail.m4 непосредственно в конфигурационный
файл sendmail(.mc), не забывая о правильном порядке директив.
². MAILER следует помещать в конце конфигурационного файла, а define — до MAILER.
define(`COPYMAIL_MAILBOX',`user@domen')
define(`NOCOPY_CONFIG',`/etc/mail/sendmail.cf')
MAILER(copymail)
/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 уйдет в "вечный" цикл, с доставкой писем самой себе и с потреблением всех ресурсов системы.
Желательно иметь возможность как то управлять процессом копирования почты. Например, избирательно копировать сообщения от какой либо группы пользователей или наоборот — не копировать. Для этого предназначен 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, а в результате почта для этого пользователя все равно копируется, то попробуйте воспользоваться следующими рекомендациями:
mx# sendmail -bt -C /etc/mail/sendmail.copy.cf
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> $={NOCOPY}
> user@domen.ru
>
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
>
Копирование почты является нарушением морально-этических (а возможно даже и юридических) прав,
если только пользователь не был предупрежден об этом до начала процесса копирования почты
(а ещё лучше до того как получил почтовый ящик)...
Предлагаемый ниже вариант 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 следует дополнить по аналогии с приведенным примером.
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
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
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
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
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
Solaris | /usr/lib/mail |
Linux | /usr/lib/sendmail-cf |
FreeBSD | /usr/share/sendmail/cf |
P.S. Поправки приветствуются...