Автоматизация веб-проектов через электронную почту::Журнал СА 4.2004
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Подписка
Архив номеров
Где купить
Наука и технологии
Авторам
Рекламодателям
Контакты
   

  Опросы
  Статьи

Событие  

В банке рассола ждет сисадмина с полей фрактал-кукумбер

Читайте впечатления о слете ДСА 2024, рассказанные волонтером и участником слета

 Читать далее...

Организация бесперебойной работы  

Бесперебойная работа ИТ-инфраструктуры в режиме 24/7 Как обеспечить ее в нынешних условиях?

Год назад ИТ-компания «Крок» провела исследование «Ключевые тренды сервисного рынка 2023». Результаты

 Читать далее...

Книжная полка  

Читайте и познавайте мир технологий!

Издательство «БХВ» продолжает радовать выпуском интересных и полезных, к тому же прекрасно

 Читать далее...

СУБД PostgreSQL  

СУБД Postgres Pro

Сертификация по новым требованиям ФСТЭК и роль администратора без доступа к данным

 Читать далее...

Критическая инфраструктура  

КИИ для оператора связи. Готовы ли компании к повышению уровня кибербезопасности?

Похоже, что провайдеры и операторы связи начали забывать о требованиях законодательства

 Читать далее...

Архитектура ПО  

Архитектурные метрики. Качество архитектуры и способность системы к эволюционированию

Обычно соответствие программного продукта требованиям мы проверяем через скоуп вполне себе понятных

 Читать далее...

Как хорошо вы это знаете  

Что вам известно о разработках компании ARinteg?

Компания ARinteg (ООО «АРинтег») – системный интегратор на российском рынке ИБ –

 Читать далее...

Графические редакторы  

Рисование абстрактных гор в стиле Paper Cut

Векторный графический редактор Inkscape – яркий представитель той прослойки open source, с

 Читать далее...

День сисадмина  

Учите матчасть! Или как стать системным администратором

Лето – время не только отпусков, но и хорошая возможность определиться с профессией

 Читать далее...

День сисадмина  

Живой айтишник – это всегда движение. Остановка смерти подобна

Наши авторы рассказывают о своем опыте и дают советы начинающим системным администраторам.

 Читать далее...

Виртуализация  

Рынок решений для виртуализации

По данным «Обзора российского рынка инфраструктурного ПО и перспектив его развития», сделанного

 Читать далее...

Книжная полка  

Как стать креативным и востребованным

Издательский дом «Питер» предлагает новинки компьютерной литературы, а также книги по бизнесу

 Читать далее...

Книжная полка  

От создания сайтов до разработки и реализации API

В издательстве «БХВ» недавно вышли книги, которые будут интересны системным администраторам, создателям

 Читать далее...

Разбор полетов  

Ошибок опыт трудный

Как часто мы легко повторяем, что не надо бояться совершать ошибки, мол,

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 6144
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 6857
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

12.03.2018г.
Просмотров: 4140
Комментарии: 0
Глубокое обучение с точки зрения практика

 Читать далее...

12.03.2018г.
Просмотров: 2978
Комментарии: 0
Изучаем pandas

 Читать далее...

12.03.2018г.
Просмотров: 3781
Комментарии: 0
Программирование на языке Rust (Цветное издание)

 Читать далее...

19.12.2017г.
Просмотров: 3789
Комментарии: 0
Глубокое обучение

 Читать далее...

19.12.2017г.
Просмотров: 6283
Комментарии: 0
Анализ социальных медиа на Python

 Читать далее...

19.12.2017г.
Просмотров: 3134
Комментарии: 0
Основы блокчейна

 Читать далее...

19.12.2017г.
Просмотров: 3434
Комментарии: 0
Java 9. Полный обзор нововведений

 Читать далее...

16.02.2017г.
Просмотров: 7246
Комментарии: 0
Опоздавших не бывает, или книга о стеке

 Читать далее...

17.05.2016г.
Просмотров: 10616
Комментарии: 0
Теория вычислений для программистов

 Читать далее...

30.03.2015г.
Просмотров: 12336
Комментарии: 0
От математики к обобщенному программированию

 Читать далее...

18.02.2014г.
Просмотров: 13969
Комментарии: 0
Рецензия на книгу «Читаем Тьюринга»

 Читать далее...

13.02.2014г.
Просмотров: 9100
Комментарии: 0
Читайте, размышляйте, действуйте

 Читать далее...

12.02.2014г.
Просмотров: 7053
Комментарии: 0
Рисуем наши мысли

 Читать далее...

10.02.2014г.
Просмотров: 5362
Комментарии: 3
Страна в цифрах

 Читать далее...

18.12.2013г.
Просмотров: 4594
Комментарии: 0
Большие данные меняют нашу жизнь

 Читать далее...

18.12.2013г.
Просмотров: 3402
Комментарии: 0
Компьютерные технологии – корень зла для точки роста

 Читать далее...

04.12.2013г.
Просмотров: 3129
Комментарии: 0
Паутина в облаках

 Читать далее...

03.12.2013г.
Просмотров: 3379
Комментарии: 0
Рецензия на книгу «MongoDB в действии»

 Читать далее...

02.12.2013г.
Просмотров: 3000
Комментарии: 0
Не думай о минутах свысока

 Читать далее...

Друзья сайта  

 Автоматизация веб-проектов через электронную почту

Архив номеров / 2004 / Выпуск №4 (17) / Автоматизация веб-проектов через электронную почту

Рубрика: Веб /  Веб

Игорь Тетерин

Автоматизация веб-проектов через электронную почту

Если взглянуть на мир со стороны, становится абсолютно не понятно, кто и как управляет сайтами. Информации на этот счет крайне мало, хотя, думаю, существует достаточное количество интересных решений. Более-менее развитые движки сайтов предоставляют веб-интерфейс управления контентом, если, конечно, это не считается принципиальным аппендиксом. Про то, что я буду описывать, лично мне нигде пока слышать не доводилось.

Сразу же уточним, чего мы хотим добиться. Наша задача – сделать как можно более удобный и доступный интерфейс для наполнения сайта контентом, то есть переложить часть рутины на скрипты и сотрудников. Значит, нам предстоит заняться автоматизацией этого процесса.

Иногда дело доходит до смешного. Есть у человека свой проект, и даже есть свой движок. Но для каждого нового динамического раздела он пишет и рисует формы, пишет обработчики, вставляет проверки. Появляется новый раздел – берем шаблон предыдущего, корректируем, правим, редизайним, проверяем и выкладываем. И еще раз проверяем.

Такой вот обьем работы ради того, чтобы добавить один раздел. А кто-то ведь еще работает и делает это через dial-up. Любой, кто занимался этим, поймет – эта работа для орков. Мы же – программисты.

У нас есть свой проект, и тратить кучу времени на разработку каждого отдельно взятого раздела мы не хотим. Лучше мы помучаемся один раз, зато потом жизнь наша станет сладкой и динамичной.

Новый принцип автоматизации. Основы. Сравнения

Как-то давно, когда я писал ret 0.8 (ядро для интернет-сайтов), мой друг заметил, что было бы весьма удобно, если бы сайтом можно было управлять через электронную почту. Тогда мы не уделили этому вопросу должного внимания. Позднее – только вспоминали про эту технологию. И вот, наконец, я решил испробовать это на одном разделе своего сайта http://revda.biz.

Написал простой скрипт, который читает почту из рассылки и публикует все, что попадет, на сайт. И тут я понял, что это очень удобно! Люди, которые писали в рассылку, просто переписывались, при этом страница сайта была в постоянном движении. Те, кто заходил на эту страницу, знали и понимали – за новой информацией туда можно заходить каждый день. Да, пока это больше похоже на обычный интернет-трэд, но все же!

Как все это выглядит? Наша задача – обрабатывать письма, которые мы будем брать с заранее созданного почтового ящика. Этот же ящик мы можем подписать на рассылки или нечто подобное, дело даже не только в рассылках. Мы можем дать адрес ящика нужным нам людям для того, чтобы они присылали туда новую информацию почтой, и не приучать их пользоваться для этого каким-либо веб-интерфейсом. Кроме того, наш сайт может брать что-то из сети Интернет, а результат пересылать на тот же почтовый ящик.

Грубо говоря, наш почтовый ящик стал централизованным источником информации. Этого обычно не скажешь о веб-интерфейсе, где приходится (по большей части) кого-то напрягать, заставлять или самому работать ручками. Более того – мы можем автоматически обрабатывать не один ящик, а несколько, закрепив за каждым свою тематику.

Этот подход также решает вопрос вашего присутствия в Интернете. Так как мы работаем с почтовым ящиком, то для того, чтобы обработать материал, ответить кому-то или сделать что-то еще, нам достаточно просто скачать почту, поработать с ней и отослать ответы.

Пока все выглядит очень красиво. Однако, чтобы создать нечто подобное в реальности, нам придется ввязаться в битву с одним, а может, и двумя, самыми запутанными стандартами: MIME и HTML.

Победить в битве с HTML достаточно трудно – это довольно противоречивый и очень динамичный стандарт. Тут придется не один раз приложить и руки, и голову. В рамках нашей задачи мы коснемся его только слегка.

Выбор платформы, языка и оценка задачи

На чем будет работать наш обработчик почты? Ответ очевиден, если предположить, что все должно работать и на Windows, и на UNIX-платформах. Мы не станем ограничивать себя чем-то одним, поэтому после разработки обработчика сможем использовать его и там, и там. А это весьма удобно.

На чем будем писать? Немного подумаем. Учитывая, что PHP я не знаю и знать не хочу, остается один выбор – Perl. К тому же Perl, с моей точки зрения, концептуально более правильный язык и больше подходит на роль стандартного. Но не это важно, важны принципы и алгоритм, а реализовывать можно хоть на Ruby.

Ну и, наконец, перед нами стоит задача написать обработчик почты. То есть нам потребуется автоматизировать прием, отправку, разбор писем. Плюс к этому возникает проблема безопасности и защищенности такого решения.

Что же нам потребуется? Один почтовый ящик, хостинг (хотя можно и локально) с поддержкой Perl и несколькими дополнительными модулями с CPAN. Ну и остальное «огнестрельное оружие», вроде putty, far, TheBat и т. д.

Переходим к практике

Рассмотрим очень простой пример. Первое, что нам потребуется – подключение нужных модулей:

use Net::POP3;use MIME::Parser;

use MIME::Entity;

use MIME::Head;

use MIME::Body;

use MIME::Words qw(:all);

use MIME::QuotedPrint;

use MIME::Base64;

Определим основные объекты и переменные:

my $parser = MIME::Parser->new;

$parser->output_to_core(1);

$parser->tmp_to_core(1);

$mail_server='127.0.0.1';

$username='login';

$password='password';

Теперь получим список писем:

$pop = Net::POP3->new($mail_server)

        or die "Can't open coonection to $mail_server :$!\n";

$pop->login($username, $password)

        or die "Can't Authenticate: $!\n";

$messages = $pop->list

        or die "Can't get listof undeleted messages: $!\n";

Начинаем обрабатывать каждое письмо:

foreach $msgid (keys %$messages)

    {

        $message = $pop->get($msgid);

        unless (defined $message)

            {

            warn "Couldn't fetch $msgid from server: $!\n";

            next;

            }

Следующий метод изначально был взят у Рэндола Шварца. Если вы поищете в Сети, то найдете нечто вроде Perl-Column, мне встречался даже перевод, правда, неполный.

Далее следует примерно такой алгоритм: если в письме есть часть типа text/plain, то берется именно эта часть, а все остальное игнорируется.

Таким образом, если мы встречаем письмо, где есть HTML-часть и текст, то в качестве входящих данных берется именно текст. Если текстовой части нет – письмо игнорируется.

        $pop->delete ( $msgid );

        @message = @$message;

        $ent = $parser->parse_data ( \@message );

        $bodyCoding = $ent->head->mime_attr( 'Content-type.charset' );

        $origType = $ent->head->get( 'Content-Transfer-Encoding',0 );

        if ( $ent->effective_type eq 'text/plain' )

            {

            # письмо - только текст

            $bodyCoding = $ent->head->mime_attr (

'Content-type.charset');

            $origType = $ent->head->get(

'Content-Transfer-Encoding',0 );

            $body = $ent->body_as_string;

            }

        elsif (

$ent->effective_type eq 'multipart/alternative'

                 and $ent->parts(0)->effective_type eq 'text/plain' )

                 {

      # письмо, где первая часть мультипар - текст

      $bodyCoding = $ent->parts(0)->head->mime_attr(

'Content-type.charset' );

      $origType = $ent->parts(0)->head->get(

'Content-Transfer-Encoding',0 );

      $body = $ent->parts(0)->body_as_string;

      }

  elsif (

$ent->effective_type eq 'multipart/alternative'

            and $ent->parts(1)->ffective_type eq 'text/plain' )

                 {

      # письмо, где вторая часть мультипарт - текст

      $bodyCoding = $ent->parts(1)->head->mime_attr(

'Content-type.charset');

      $origType = $ent->parts(1)->head->get(

'Content-Transfer-Encoding',0 );

      $body = $ent->parts(1)->body_as_string;

      }

  else {next}

  chomp $origType;

Чем универсален этот код, так это тем, что в нём происходят все стандартные MIME-декодировки – Base64 и Quoted-Printable – и перекодирование из ISO и KOI в Windows-1251.

        # Если закодировано, декодируем его, во имя счастья

        if (lc($origType) eq 'quoted-printable')

            { $body  =  MIME::QuotedPrint::decode($body); }

        if (lc($origType) eq 'base64')

            { $body  =  MIME::Base64::decode($body); }

        $bodyCoding = lc($bodyCoding);

        # Перекодировка кирилицы у тела, если надо.

        if ($bodyCoding ne '')

            {

      if ($bodyCoding eq 'koi8-r') {$bodyCoding = 'koi'}

            if ($bodyCoding eq 'koi8r') {$bodyCoding = 'koi'}

            if ($bodyCoding eq 'iso8859-5') {$bodyCoding = 'iso'}

            if ($bodyCoding eq 'koi8-u') {$bodyCoding = 'koi'}

      if ($bodyCoding eq 'koi' || $bodyCoding eq 'iso')

                { $body = encoder($body, $bodyCoding, 'win') }

        }

        $subj  =  join( "",

map {xcode( ${$_}[1], ${$_}[0])}

     decode_mimewords(

         $ent->head->get('Subject',0)

     )

      );

  $date = $ent->head->get('Date',0);

  }

Собственно, все. Переменная $subj содержит тему письма, $body – тело письма, а $date – дату. Остальные параметры письма вы сможете легко получить, используя уже подключенные в программе модули.

Теперь вы смело можете сохранить в базе данных полученные результаты. Я, например, сохраняю их таким образом:

        use collector;

        ($r) = Add2Revorum ( \$subj, \$body, \$date );

где модуль collector.pm – часть моего движка сайта, которая создает необходимую структуру и, используя ядро ret WebOS и модуль Storable, пишет её базу (обычные плоские файлы).

О проблеме альтернативной СУБД я напишу в другой статье. Те, кого это заинтересовало, могут обратиться за подробностями по интернет-адресу: http://jkeks.far.ru/ret.

Подпрограммы или процедуры, ответственные за перекодировку:

sub xcode {

  # определяем кодировку и вызываем перекодировщик, если нужно

  my ($charset, $src)  =  @_;

  my %charsets = (

    'windows-1251' =>'win',

    'iso8859-5' =>'iso',

    'koi8-r' =>'koi',

    'koi8r' =>'koi',

    'koi8-u' =>'koi',

  );

  return $src unless ($charsets{lc($charset)});

  return encoder($src, $charsets{lc($charset)}, 'win');

}

Огромная благодарность российскому разработчику библиотек pvd – Денису Познякову (Denis Poznyakov, pvdenis@usa.net) – за минимальный код перекодировки русских символов. Перекодировка основывается на данных полей письма, тут нет попытки создания какого-либо анализатора.

sub encoder {

  my $enstring = shift; my $cfrom = shift; my $cto = shift;

  my %codefunk = (

    win => "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF",

    koi => "\xE1\xE2\xF7\xE7\xE4\xE5\xF6\xFA\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF2\xF3\xF4\xF5\xE6\xE8\xE3\xFE\xFB\xFD\xFF\xF9\xF8\xFC\xE0\xF1\xC1\xC2\xD7\xC7\xC4\xC5\xD6\xDA\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD2\xD3\xD4\xD5\xC6\xC8\xC3\xDE\xDB\xDD\xDF\xD9\xD8\xDC\xC0\xD1",

    iso => "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF",

    dos => "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF",

    koi_lc => "tr/\xB3\xE0-\xFF/\xA3\xC0-\xDF/",

    koi_uc =>"tr/\xA3\xC0-\xDF/\xB3\xE0-\xFF/",

    win_lc => "tr/\xA8\xC0-\xDF/\xB8\xE0-\xFF/",

    win_uc =>"tr/\xB8\xE0-\xFF/\xA8\xC0-\xDF/",

    alt_lc => "tr/\xF0\x80-\x9F/\xF1\xA0-\xAF\xE0-\xEF/",

    alt_uc => alt_lc => "tr/\xF1\xA0-\xAF\xE0-\xEF/\xF0\x80-\x9F/",

    iso_lc => "tr/\xA1\xB0-\xCF/\xF1\xD0-\xEF/",

    iso_uc => "tr/\xF1\xD0-\xEF/\xA1\xB0-\xCF/",

    dos_lc => "tr/\x80-\x9F/\xA0-\xAF\xE0-\xEF/",

    dos_uc => "tr/\xA0-\xAF\xE0-\xEF/\x80-\x9F/",

    mac_lc => "tr/\xDD\x80-\xDF/\xDE\xE0-\xFE\xDF/",

    mac_uc => mac_lc => "tr/\xDE\xE0-\xFE\xDF/\xDD\x80-\xDF/"

  );

  if (!$enstring or !$cfrom or !$cto) {return 0}

  else {

    if ($cfrom ne "" and $cto ne "lc" and $cto ne "uc") {

      $_ = $enstring;$cfrom = $codefunk{$cfrom};$cto = $codefunk{$cto};

      eval "tr/$cfrom/$cto/"; return $_;

    }

    elsif (($cfrom ne "") and ($cto eq "lc" or $cto eq "uc")) {

      $_ = $enstring; $cfrom = $codefunk{"$cfrom\_$cto"};

      eval $cfrom; return $_;

    }

  }

  return $enstring;

}

Если вы не поняли, как это работает, поясню. Данный пример скачивает с почтового ящика все письма, обрабатывает их и передает системе управления базами данных либо куда-то еще. Этот код является основой описываемой технологии. Как я и обещал, соблюдена полная кросс-платформенность между Windows и UNUX-системами. Все используемые в скрипте библиотеки легко доступны.

От редактора: в процессе редактирования статьи было замечено, что тот же самый Outlook Express нечасто кодирует русские буквы в заголовках сообщений. Все это, конечно, зависит от настроек, но мало кто из пользователей Outlook занимается дотошной настройкой своего почтового клиента.

Поэтому процедура xcode при работе с такими заголовками не диагностировала необходимость перекодирования. Немного подумав, была придумана небольшая модификация. Это не панацея, а скромная попытка перекрыть некоторые проблемы – угадать кодировку KOI8-R в заголовке. Для этого внесем только одну коррективу в процедуру xcode – чуть усилим проверку:

    # закомментируем строку, возвращающую неизмененный

    # заголовок и продолжим проверку:

    # return $src unless ($charsets{lc($charset)});

    unless ($charsets{lc($charset)})

      {

    # если кодировка неопределенна, считаем вхождение

    # больших и маленьких русских букв

      $upper = "ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ";

      $lower = "ёйцукенгшщзхъфывапролджэячсмитьбю";

      $ucount = eval("\$src =~ tr/$upper/$upper/;");

      $lcount = eval("\$src =~ tr/$lower/$lower/;");

      # если больших букв больше - скорее всего это KOI8

    # и мы перекодируем это в Windows

      return encoder($src, 'koi', 'win') if ($ucount > $lcount);

    # иначе, как и ранее, возвращаем неизмененный заголовок

      return $src;

      }

Собственно, идея основана на том факте, что слово «Новость» в кодировке KOI будет восприниматься как «оПЧПУФШ» в кодировке Windows. Прием довольно спорный, но имеет право на существование. Абсолютно не применим на больших объемах текста – поверьте на слово.

Тема безопасности, аутентификация, вклинивания

Любое письмо, попавшее на ящик, может стать атакой или просто спамом. Как с этим бороться?

Прежде всего вы можете организовать интернет-рассылку, где сможете управлять регистрацией нужных вам подписчиков. Обычно в системах рассылки уже встроены свои собственные механизмы борьбы со спамом.

Описанный выше сценарий также подходит к делу принципиально. Принимаются только те сообщения, которые пришли в виде текста. Кроме того, вырезаются баннеры, расположенные обычно после символов «\n— \n» (это – стандарт TheBat). Также скрипт соблюдает логику: «можно только то, что разрешено», а не «можно то, что не запрещено».

Если проблемно организовать рассылку, скорее всего вам необходимо будет добавить проверку ключа (например, в теме письма должен быть соответствующий идентификатор). Идентификатор отбрасывает почти все проблемы с безопасностью, однако это не накладывает ограничения на входящий трафик.

Но самый безопасный вариант – принимать только текст, зашифрованный или подписанный при помощи программ семейства PGP. Это также исключит возможность прочитывания писем при случайном доступе к ящику.

Немного рекламы

Ранее мы коснулись темы хранения данных. Важно понимать, что кроме простых функций вроде публикации рассылки, со временем функциональность может обрасти связями с различными разделами, а приходящие данные смогут иметь сложную структуру. Плюс ко всему – не каждый может себе позволить профессиональный хостинг.

Ради этого всего появилось на свет ядро ret WebOS, которое (как одно из направлений) предлагает альтернативу серверу SQL. Код системы минималистичен и для своей работы требует лишь наличия модуля Storable (который входит в стандартную поставку с Perl 5.8).

В свою очередь модуль blogs.pm предоставляет возможность хранить структуры данных любой сложности и осуществлять к ним доступ как к разделам сайта. Данные хранятся в плоских файлах. Интернет-адрес проекта: http://jkeks.far.ru/ret. Добро пожаловать!


Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-45
E-mail: sa@samag.ru