URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID1
Нить номер: 92896
[ Назад ]

Исходное сообщение
"Настройка умной архивации вход/исход писем Postfix"

Отправлено Андрей , 18-Янв-12 12:10 
Добрый день!
Вот такая вот задачка от руководства:

1. Имеем postfix+mysql+dovecot+ спам фильтры и антивирус
В данный момент вся входящая и исходящая переписка через hash карты:

main.cf:
recipient_bcc_maps = hash:/etc/postfix/recipient_bcc
sender_bcc_maps = hash:/etc/postfix/sender_bcc

cat /etc/postfix/recipient_bcc
@мой_домен recipient_alias

cat /etc/postfix/sender_bcc
@мой_домен sender_alias

Соответственно в /etc/aliases заданы :
recipient_alias: user@мой_домен, backup_input@мой_домен
sender_alias: user@мой_домен, backup_output@дом_домен

Т.е через учетку user@мой_домен проходит вся переписка (нужно для внешний программ), вся входящая почта по всему домену летит в backup_input одной кучей и соответственно вся исходящая - в backup_output, также общей кучей

Задача:
Сделать так чтобы вся вход. переписка в backup_input раскидывалась по созданный папкам (пр. arhiv/input_mail/имя_почтового_ящика) и вся исходящая в backup_output также по папкам (пр. arhiv/output_mail/имя_ящика)
Планируется долгосрочное хранение всей корпоративной переписки, с необходимостью быстро найти нужную переписку по пользователю для руководста.

Какие есть идеи?
С postfix работаю меньше года
Заранее благодарен!


Содержание

Сообщения в этом обсуждении
"Настройка умной архивации вход/исход писем Postfix"
Отправлено awk_noob , 18-Янв-12 13:39 
1. Добавляем в постфикс след строку
[root@bc ~]# cat /usr/local/etc/postfix/main.cf | grep bcc
always_bcc=backup@domen.ru
Теперь ВСЯ почта будет дублироваться этому пользователю.
2. Создаем этого почтового пользователя.
3. Редактируем крон

[root@bc ~]# cat /etc/crontab | grep big
57      */2     *       *       *       root    /mnt/big/backup_mail/list_mail_users.pl
59      */2     *       *       *       root    /mnt/big/backup_mail/all.sh
0       */2     *       *       *       root    /mnt/big/backup_mail/mail_backup.pl –q

Скрипты выглядят так.(скриптописатель из меня никакой – буду признателен за любые исправления)

4. Тут мы получаем список наших почтовых пользователей и засовываем его во временный файл.

[root@bc /mnt/big/backup_mail]# cat list_mail_users.pl
#!/usr/bin/perl
unlink ("/mnt/big/backup_mail/111");
#`rm /mnt/big/backup_mail/vusers`;
opendir (TEMPDIR,'/var/spool/mail') || die "Не могу открыть каталог /var/spool/mail: $!";
@FILES=grep(!/^\.\.?/, readdir TEMPDIR);
closedir(TEMPDIR);
foreach (@FILES) {
    $_="$_ /var/spool/mail/$_";
    `echo "$_" >> /mnt/big/backup_mail/111`;
}


5. Тут мы всего лишь меняем слеш в другую сторону ((( ну не умею я кодить(((

[root@bc /mnt/big/backup_mail]# cat all.sh
#!/bin/sh
sed 's/\(.*\)@/\1\\@/' 111 > vusers

6. Тут немного уличной магии (вот этот скрипт уже не мой. Но все замечания только приветствуются)

[root@bc /mnt/big/backup_mail]# cat mail_backup.pl
#!/usr/bin/perl
#
# vars
use Log::LogLite;

$LOG_DIRECTORY = "/mnt/big/backup_mail";
$ERROR_LOG_LEVEL = 6;
$CALLER="mail_backup.pl";
# create new Log::LogLite object
$log = new Log::LogLite($LOG_DIRECTORY."/backup.log", $ERROR_LOG_LEVEL);

use File::Copy;

$backup_path="/mnt/big/backup_mail/mail";   #куда копируется ВСЯ почта
$bcm_path="/var/spool/mail/backup\@domen.ru/new";  #откуда, с какого ящика
$config_path="/mnt/big/backup_mail/vusers";  #где находятся все пользователи домена
#$banner="E-mail backup & sorting program by ONYX.\n";

#print $banner;

#attempt to read postbackup maildir
opendir(MDIR,"$bcm_path") or die "Cant find postbackup maildir! Check $bcm_path for existense.\n";
@files=readdir(MDIR);
closedir(MDIR);
if (scalar(@files)==2)  #abort if no mail to backup
   {
      $log->write("No mails to backup! Aborted.",$CALLER);
      die "No mails to backup! Aborted.\n";
   }

#finded files
print "The following mails will be stored:\n\n";
for ($j=2;$j <= scalar(@files)-1;$j++)
{
        print "$files[$j]\n";
}

printf("\nTotal: %d mails.\n",scalar(@files)-2);

#yes_no confirmation
if (!defined($ARGV[0]) or $ARGV[0] ne "-q")
{
   print "\nConfirm? [y/n]: ";
   $yes_no=<STDIN>;
   chop($yes_no);
   if ($yes_no ne 'y')
      {
              die "Not confirmed. Type 'y' to confirm! Aborted.\n";
      }
}

#reading the config file
open(CONF,"$config_path") or die "Cant read postfix config! Check $config_path for existense.\n";
$e=0;
while (<CONF>)
   {
      if ($_=~m|(\S+)|)
         {
            $config[$e]=$1;
            $e++;
         }
   }
close(CONF);

#ok, here we go
chdir($bcm_path);
$lc=0;
for ($i=2;$i <= scalar(@files)-1;$i++)
{
   @content=0;

   open(MFILE,"$files[$i]") or die "Cant open $files[$i]! checkit.\n";
   while ($line=<MFILE>)
      {
         $content[$lc]=$line;
         if ($line=~m|X-Anti-Virus|i)
      {
         last;
      }
         $lc++;
      }
   close(MFILE);

   for ($q=0;$q <= scalar(@content)-1;$q++)
      {
         #chop($content[$q]);
         if ($content[$q]=~m|^From:.+<(\S+)>|i)
            {
               if ($il=is_local(@config,$1)) #if sender is local...
                  {
                     $ret=backup_mail($files[$i], $1,"out"); #store the mail in his out dir
                     print "$ret";
                  }
            }
         if ($content[$q]=~m|^\tfor <(\S+)>|)
            {
               if ($il=is_local(@config,$1)) #if recipient is local
                  {
                     $ret=backup_mail($files[$i], $1,"in"); #store the mail in his in dir
                     print "$ret";
                  }
            }
      }
   unlink($files[$i]) and print " *******$files[$i] deleted.\n";
}

$log->write((scalar(@files)-2)." mails backed up OK.",$CALLER);
exit 1;

sub backup_mail()
{
mkdir("$backup_path/$_[1]");
mkdir("$backup_path/$_[1]/out");
mkdir("$backup_path/$_[1]/in");
if ($_[2] eq "out")
   {
      copy("$_[0]","$backup_path/$_[1]/out/$_[0]") or return "Cant copy to  $backup_path/$_[1]/out/$_[0]! Check it.\n";
      return "$backup_path/$_[1]/out/$_[0]\t\tOK\n";
   }
   else
   {
      copy("$_[0]","$backup_path/$_[1]/in/$_[0]") or return "Cant copy to  $backup_path/$_[1]/in/$_[0]! Check it.\n";
      return "$backup_path/$_[1]/in/$_[0]\t\tOK\n";
   }

}

sub is_local()
{
for ($r=0;$r <= scalar(@_)-2;$r++)
      {
         if ($_[scalar(@_)-1] eq $_[$r])
            {
               return 1;
            }
      }
return 0;
}

Теперь по адресу /mnt/big/backup_mail/mail у нас есть папки со всеми нашими почтовыми пользователями

[root@bc /mnt/big/backup_mail/mail]# ls
abramova@domen.ru          lagutina@domen.ru
lebedev@domen.ru          
a.melnikov@domen.ru          len@domen.ru
abdullin@domen.ru            lepeshkina@domen.ru
           lipatova@domen.ru
admin@domen.ru               logina@domen.ru
        

в которых есть папки IN и OUT соответственно отправленные и полученные письма.

Если надо вытаскивать почту дата/ин/оут пр. скриптом тоже могу прислать


"Настройка умной архивации вход/исход писем Postfix"
Отправлено Андрей , 18-Янв-12 15:49 
>[оверквотинг удален]
> abramova@domen.ru          lagutina@domen.ru
> lebedev@domen.ru
> a.melnikov@domen.ru          len@domen.ru
> abdullin@domen.ru            
> lepeshkina@domen.ru
>            lipatova@domen.ru
> admin@domen.ru            
>    logina@domen.ru
> в которых есть папки IN и OUT соответственно отправленные и полученные письма.
> Если надо вытаскивать почту дата/ин/оут пр. скриптом тоже могу прислать

Оо..щас буду пробывать, спасибо!!!

1)
> 4. Тут мы получаем список наших почтовых пользователей и засовываем его во
> временный файл

У меня все пользователи хранятся в базе Mysql, применим ли для данной ситуации данный скрипт?

2) $backup_path="/mnt/big/backup_mail/mail";   #куда копируется ВСЯ почта
> $bcm_path="/var/spool/mail/backup\@domen.ru/new";  #откуда, с какого ящика
> $config_path="/mnt/big/backup_mail/vusers";  #где находятся все пользователи домена

Насчет $config_path я так понимаю тож, нужно как то настроить под взаимодействие с БД Mysql ?

3) Да, почту потом нужно будет вытаскивать, пришлите пожалуйста скрипт.


"Настройка умной архивации вход/исход писем Postfix"
Отправлено awk_noob , 18-Янв-12 16:19 
> Оо..щас буду пробывать, спасибо!!!
> У меня все пользователи хранятся в базе Mysql, применим ли для данной
> ситуации данный скрипт?

у меня тоже. но почта-то у меня не в мускуле лежит, а в папках вида /вар/спул/маил/пользов@домен

> Насчет $config_path я так понимаю тож, нужно как то настроить под взаимодействие
> с БД Mysql ?

никаких связей с мускулом.

> 3) Да, почту потом нужно будет вытаскивать, пришлите пожалуйста скрипт.

Теперь мы хотим вытащить письма за определенный период от определенного пользователя, но хотим это не ручками, а красиво. К тому же мы можем сразу интересующую почту отправить кому-то еще.
Для этого опять есть скрипт (опять мой – все замечания приветствуются)

[root@bc ~]# cat watch.sh
#!/bin/sh
echo "Введите Фамилию пользователя полное имя user@domen.ru"
read NAME
echo "Получено (in), Отправлено (out)?"
read ROUTE
echo "Нужны внутренние письма (domen)(1) или внешние(2)?"
read DESTINATION
echo "Введите начальную дату поиска писем в формате YYYY-mm-dd"
read DATE_START
echo "Ведите конечную дату поиска писем в формате YYYY-mm-dd"
read DATE_END
CURRENT_DATE=`date "+%Y-%m-%d"`
# Считываем фамилию пользователя и входящее это сообщение или исходящее
#а также - внутренне это сообщение, или внешнее
PREF="/mnt/big/backup_mail/mail"
#корень, откуда начинаем идти по почтовым ящикам
TOTAL="$PREF/$NAME/$ROUTE"
#конкретная папка , откуда будем всё копировать
TEM="/mnt/big/temp"
#как можно догадаться из названия - временная папка
yday()
{
    perl -e '
        use POSIX qw(strftime);
        $fmt = "%j";  # %j day of year 1 - 366
        $mday = substr("$ARGV[0]", 8, 2);
        $mon =  substr("$ARGV[0]", 5 ,2);
        $year = substr("$ARGV[0]", 0 ,4);
        $weekday =
        strftime($fmt, 0, 0, 0, $mday , $mon - 1, $year - 1900, -1, -1, -1);
        print int $weekday;
            ' "$1"
}
#это какая-то сложная функция на перл для вычисления по дням

very_old=$( yday $DATE_START )
old=$( yday $DATE_END )
q=$( yday $CURRENT_DATE )
FULL_TIME=$(( $q - $very_old ))
# сколько дней от текущей даты до начала выборки
SMALL_TIME=$(( $q - $old ))
# сколько дней от текущей даты до конца выборки
cd $TOTAL

WATCH=/var/spool/mail/watch@domen.ru/new/
find . -mtime +$SMALL_TIME -mtime -$FULL_TIME -exec cp -p '{}' $TEM ';'

cd $TEM

if [ "$ROUTE" = in ]; then
копируем нужные письма
    if [ "$DESTINATION" = 1 ]; then
    cp -p $(grep -l "^From: .*domen" *) $WATCH
        else
    cp -p $(grep -L "^From: .*domen" *) $WATCH
    fi
else
if [ "$DESTINATION" = 1 ]; then
    cp -p $(grep -l "^To: .*domen" *) $WATCH
        else
    cp -p $(grep -L "^To: .*domen" *) $WATCH
    fi
fi
#копируем в папку пользователя watch@domen.ru нужные письма с учётом введенных дат
rm $TEM/*
# очищаем временную папку

Вот как-то так. Если приделаете вэб морду для последнего скрипта – честь вам и хвала!



"Настройка умной архивации вход/исход писем Postfix"
Отправлено miemshik , 23-Янв-12 00:14 
Спасибо за огромную помощь, буду все прикручивать к нашей системе.

Есть вопрос
>$config_path="/mnt/big/backup_mail/vusers";  #где находятся все пользователи домена

Здесь указан путь до файла, содержащего целевых пользователей

В моем случае все учетки лежат в БД Mysql и связь с ними через парамерт в main.cf:
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf

На
http://z-up.ru/mediawiki/index.php?title=%D0%A0�...
есть инфа что обычно этот файл указывают как значение параметра virtual_mailbox_maps в конфигурации postfix для виртуальных пользователей (или другие файлы *_maps).

Но пытаюсь указать параметр вида $config_path="mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf" (может как то подругому нужно указывать его?) то скрипт отрабатывает до ошибки:
=======
The following mails will be stored:

.
1327185036.M760397P2388.mail-postfix,S=3067,W=3176
1327185079.M579289P2401.mail-postfix,S=1872,W=1935
1327185028.M241687P2383.mail-postfix,S=3067,W=3176

Total: 4 mails.

Confirm? [y/n]:y
Cant unlink source file .!
2. Storing: inbox -> Unsorted -> Done.
=======
И создается только папка Unsorted с подпапками in и out (пустые), письма так и остаются нетронутыми на почте, куда все копируется через парамерт always_bcc

Подскажите, где ошибка. Как адаптировать скрипт под данную ситуацию, чтобы он узнал полный список учеток домена.  
Заранее благодарен!