Люблю работать: даже когда что-то сильно загрязнилось, ты всегда можешь это отчистить.
(с) Бог, "Брюс Всемогущий"

 

Конечно, борьба со спамом отнюдь не новинка — но, с другой стороны, проблема как была, так и остается, несмотря даже на многолетнюю борьбу. Сегодня я расскажу, что такое спам для меня лично и как я лично с ним борюсь

Что такое спам и как с ним бороться


"Пинцет, приплыли,— скажет кое-кто из вас.— Да мы и так все в курсе, что такое спам, потому что он нас и так давно достал и вааще опротивел, в натуре!".


Ладно, если вы такие гармонично развитые, буду краток и конкретен — в смысле говорить стану конкретно о моих проблемах, а вы уж там проектируйте на свою специфику. Может, кое-что и почерпнете.


Спам (и вы с этим согласитесь) — это, типа, нежелательная электронная почта. Но что такое "нежелательная"? Я могу говорить о пяти градациях желательности.


1. Срочные сообщения. Например рассылаемые внутри самой компании, типа "собрание акционеров — завтра в одиннадцать, Ваша кандидатура будет поддержана, но только в Вашем присутствии". Вряд ли вы захотите пропустить такое сообщение или прочитать его послезавтра, поэтому его нужно броадкастить. То есть после прихода такого письма на один из ящиков наш "мейлбот" должен порассылать его на остальные ваши почтовые эккаунты, так чтобы было больше шансов, что вы получите и прочтете его вовремя. Некисло было бы, если бы уведомление о таких письмах приходили еще и в виде SMS.


2. Важные сообщения. Такие сообщения не так важно прочитать немедленно, как вообще не потерять. Поэтому тут тоже желательно разослать на все остальные эккаунты уведомление, типа "посмотри туда — там много вкусного". Это особенно хорошо работает, когда почта с вложениями приходит на работу, а вы получаете уведомление на GPRS-эккаунт, по которому получать вложенные файлы дорого. У меня к такой категории относятся письма моих дорогих авторов.


3. Сообщения FYI. Да простят меня уважаемые трансглобальные компании, но большинство писем-рассылок от них можно смело отнести к этой категории. Например, одна глубоко уважаемая мною компания почти ежедневно присылает рассылки типа "В Мухосранске [благодаря нам] открылось новое интернет-кафе с беспроводным доступом" или "Наши Новые Продукты помогают бороться со СПИДом". Нельзя сказать, чтобы подобная информация подлежала особому изучению — но, тем не менее, каждая такая рассылка потенциально может лечь в основу статьи. Опять же, редко, но бывает, что приходит нечто действительно важное, например приглашение на интересную презентацию.


Словом, к этому разряду сообщений относится информация, не то чтобы заслуживающая нотификаций, однако же и не такая, которую нужно удалять. К этой же категории относятся другие типы рассылок, например анекдоты. Вряд ли вы захотите, чтобы на вашу мобилку приходили уведомления "Вы получили новые анекдоты с omen.ru" — но и удалять их как спам тоже неправильно, ведь нет другой такой радости, как почитать "пропущенные" анекдоты.


4. Неизвестная почта. В 99% случаев это очередной спам, который еще не попал в базу данных спама. Но также возможно, что это какое-нибудь зарубежное (русское, белорусское, израильское...) издательство спрашивает разрешения на перепечатку статей, или, может быть, какой-нибудь автор изменил почтовый адрес, или кто-то хочет еще что-то, например читатель спрашивает "как подписаться на ваш журнал в Молдавии?". Такое тоже не нужно удалять, хотя и читать можно значительно реже.


5. Спам. Ну, вот и добрались мы до спама. Спам, в терминологии нашей программы,— это сообщение, которое проходит "на ура!" (TRUE, YES, OK) тест спама. Что такое тест спама, точно сказать нельзя, но предположительно заголовки и текст письма должны удачно (точнее, неудачно для самого спама) сравниваться с некоторыми шаблонами — например, с регулярными выражениями, взятыми из базы данных "о спаме". Существуют и онлайн-базы таких образцов, о чем мы еще скажем пару слов.


Как видите, не все так просто — кроме спама есть и еще другие варианты. В духе старых, в смысле битых переменным током, кодировщиков я ввожу (для внутреннего употребления) перечислимый тип:

 

enum mailType {Emergency=0,Attention,Fyi,Unknown,Spam}

 

Теперь рассмотрим методы борьбы со спамом. Есть три варианта: убивать спам на сервере, на стороне клиента, и, наконец, "третий вариант" — то, что я называю "half-loading", по аналогии с прогрессивным когда-то способом загрузки VHS-касссет. Что это такое — скоро узнаете, но, если вы помните, в отношении VHS, это приводило к ускоренной перемотке и быстрому запуску воспроизведения. Так же и у нас — это будет работать быстро, экономить трафик и заодно бережно относиться к "головкам воспроизведения" (типа к вашим мозгам).


Для того чтобы убивать спам на сервере, нужно этим сервером располагать, то есть быть системным администратором, и кроме этого иметь политическое решение руководства по данному вопросу. В принципе, для всех современных серверов существует возможность "навесить" антиспамерскую программу. Этот вопрос мы рассматривать не будем — мои статьи скорее для программистов, таких же маниаков кода, как я сам. (Хотя обзор таких программ это отличная тема, так что жду от вас такую статью знаков эдак на 20К — высылайте на мэйл по мере готовности.)


Второй метод — убийство на стороне клиента. Таким образом работает несколько антиспамовых программ, например McAfee Spam Killer. Эти программы, в основном, служат в качестве локальных мэйл-серверов. Они получают почту по протоколу POP3, разбирают ее на предмет "спам — не спам", после чего вы получаете почту у локального POP3-сервера, так же как вы делали бы это удаленно — при установке программы она "переводит стрелки" на себя как на сервер. Этот метод имеет три недостатка, что и повлекло, так сказать, @thread, то есть продолжение темы.


Во-первых, все протестированные мною программы глючили в той или иной мере. То ли сервер вис, не отвечал на запросы. У того же MSK (McAfee Spam Killer) были какие-то проблемы с менеджментом паролей — программа никак не могла запомнить, как я подключаюсь к удаленному серверу. Другие софтины показывали другие глюки.
Второе: все эти антиспамерские программы экономят ваши нервы — но не трафик. Ведь для того, чтобы принять решение, они выкачивают письмо целиком, разбирают его на "поля" — заголовки, тело, аттачменты — и уже после этого принимают решения о "валидности" донесений.


Третье: они закрыты, платны, проприетарны и не переносимы между платформами. И хотя для меня лично проблемы переносимости уже не существует: я использую MS Windows только для таких приложений, как Painkiller или Warhammer 40К — тем не менее, существуют же люди (даже и среди наших читателей), для которых MS Word и VBA все еще незаменимые инструменты. Я, конечно, влияю, как могу, провожу работу — но все равно приходится рассчитывать и на тех "виндози", которые никак не бросят своих вредных привычек запускать программы из каталога c:\windows.


Впрочем, в таких коммерческих программах есть одно огромное преимущество — они бесплатно загружают базы данных "горячих спамерских выражений". Это отличная фича, ведь если может xine использовать виндов-плеерские кодеки, то почему же мы не можем отсниффить трафик (или проэксплорить готовые закачанные файлы) таких любезных программ и пополнить свой "лексикон" тысячей-другой правил из таких баз. Но это отдельная тема — мы здесь не будем заниматься такими вещами. Притом использование правил в определенном формате повлечет реконструкцию движка синтаксического анализатора — а это вообще бесконечная история.


Другие известные производители таких баз данных — тот же Norton (Symantec) и Лаборатория Касперского (анализ текстовых данных в процессе разбора спама выполняют специалисты компании "Ашманов и Партнеры"). Больше о последнем альянсе — на странице
www.kaspersky.com/news?id=966096, а мы тем временем будем продвигаться к нашему персональному счастью, куда более счастливому.


Итак, мы хотим преодолеть закрытость, моноплатформенность и коммерческий базис перечисленных программ. К тому же, дополнительное условие — как можно меньше трафика. А как побочный эффект — самообразование, самоуважение и самодостаточность нас как программеров, пусть пока и с маленькой буквы.


Критерий истины


По ходу определимся, что именно считать "положительным результатом". Поскольку большинство современных пользователей располагает более чем одним подключением, их, соответственно, можно ранжировать от дешевых и медленных (или разделяемых, например в офисе) до быстродействующих, но дорогих (таких как GPRS, Volia Broadband, Cyfra Net — и прочих зависимых от трафика подключений).


Так вот, можно предположить, что программа может работать, к примеру, на медленном соединении — и при этом фильтровать все множество ваших почтовых эккаунтов (кроме одного — скоростного). При этом программа "заходит" на серверы, удаляет нежелательные письма, создает нотификации по другим, оставляет без внимания третьи и, наконец, пересылает четвертые на "непубличный" адрес, известный только вам одному. Предполагается, что программа работает периодически — скажем, раз в 10 минут. Если вдруг вы придете "на работу" в произвольный момент и проверите свою почту по одному из публичных эккаунтов, то, вероятно, увидите пару писем, которые должны были бы отнесены к спаму, но пришли уже после того, как наш клинер-бот опрашивал этот сервер. Вероятность такого расклада — вероятность прихода спама в течении пяти минут: я условно "прихожу" иногда сразу после очистки, иногда — в конце цикла, но статистически — в середине тех десяти минут, что проходят между проверками.

 

Если я получаю спам регулярно, по 48 писем в течение суток, то вероятность получения одного письма в течение 5 минут — 1/6, то есть я буду видеть одно "левое" письмо каждый шестой раз проверки почты. На работе почту я получаю трижды в сутки — то есть я буду получать "точный спам" раз в два дня. Это меня полностью устраивает, такие кондишины я рассматриваю как состояние "счастливый потребитель", то есть точка отсчета моего счастья в отношении спама. В качестве дополнительного "извинения" наша программа так и называется — "очиститель", без упоминания спама как такового. Просто станет чище.


Второй вопрос: ложное срабатывание спам-фильтра. Что будет, если вы определите домен guy.ru как запретный, но ваш лучший друг заведет там учетную запись? По правде говоря, я, как пользователь с 10-летним стажем (да, примерно 10 лет назад все и началось — я имею в виду Сеть, а не gay.ru), никогда не видел, чтобы люди потеряли из-за не полученного электронного письма работу, семью или здоровье. Точно так же не припомню случая, чтобы люди в один день меняли свою почту, полностью "съезжая" со всех старых ящиков — разве что они сами хотят, чтобы их забыли.


Свет, музыка: вползают питоны


Проанализировав все входные данные, я пришел к единственно правильному выводу: в качестве языка программирования для моего приложения будет выступать интерпретируемый язык пятого поколения Python. Для этого есть масса показаний, главное из которых — этот язык для меня в данный момент интереснее всех остальных-прочих, и это — не шуткаJ. Причиной тому — Python, переносимый на многие платформы язык, который имеет ясный синтаксис, мощную поддержку сетевых интерфейсов, доступ к универсальной библиотеке графического интерфейса Tk, а также, что немаловажно, множество других библиотек в составе дистрибутива, что позволяет решать большинство рутинных действий программирования.


Не зря Python изначально ориентирован на быструю разработку проектов — меня как раз вполне устраивает что "я решаю свои проблемы — а "Питон" делает все остальное". Уже с точки зрения некоторого опыта могу сказать, что цикл разработки на "Питоне" — даже по сравнению с теми же C или Java — отличается "нулевой длинной", то есть количество "сборок" за час может достигать 60 и более.


И уж совсем некстати хочу добавить, что "Питон" к питонам не имеет особого отношения — язык назван в честь Monty Python's Flying Circus, популярного в 70-е годы британского комедийого сериала. Тем не менее, я рассматриваю этот интерпретатор как разновидность жителей серпентария — наблюдая, с какой регулярностью он поглощает приложения, раньше "принадлежащие" Perl, bash и Tcl, а также — Java и C++.


Вот и вся любовь: голый POP


Теперь нас заинтересует проза жизни, а именно — тот транспортный протокол верхнего уровня, по которому мы (наш MailCleaner) будем получать доступ к серверу почты. На сегодня, несмотря на наличие IMAP, по-прежнему надежно можно рассчитывать только на протокол POP3. Этот протокол вообще-то к почте имеет некоторое отношение, но не такое фундаментальное, как sendmail и SMTP. Сервер POP3 по запросу пользовательского приложения "шарит" по домашним каталогам пользователей на сервере, ищет там почтовые ящики и "выворачивает" их на потребу пользователю.


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


Этот протокол, как и многие другие, является обычной текстовой "перепиской" между клиентом и сервером. Сервер ждет запросов, обычно на порту 110, после установки TCP-соединения выполняет несложную аутентификацию (если не включены механизмы более сложной аутентификации — но к нашей теме они не имеют отношения). В результате мы имеем открытый POP3-сеанс: первая операция в сеансе — получение списка сообщений. Точнее, уже само подключение дает нам количество сообщений и общее количество байт (октетов), но для этого также можно использовать команду STAT.


Следующим этапом может быть получение списка сообщений командой LIST (я не использую этот шаг) и, наконец, пересылка самих сообщений — целиком или какую-то их часть. Последнюю возможность мы будем активно эксплуатировать.


Наконец, если ваш почтовый клиент настроен так, чтобы удалять сообщения с сервера, то он может выдать команды удаления. А чтобы не запутаться окончательно, сервер не удаляет сообщения до закрытия сеанса, и вы можете их еще "отозвать" — так же как вы отзываете удаленные записи базы данных (правда, в POP3 можно отзывать только все "записи" сразу, а не по одной). Обратите внимание: разрыв соединения не должен привести к удалению помеченных записей, так что если ваша программа "наудаляла" явно лишнего, то можете просто "убить ее в голову", так чтобы она не отсоединилась,— и сообщения должны сохраниться.


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


Аналогично, сервер не будет добавлять сообщения, пришедшие в то время, пока сеанс открыт — можно сказать, что сеанс фиксирует транзакцию. Для нас это значит, что после команды LIST сообщения будут сохранять свои порядковые номера до закрытия сеанса. POP3-сервер лочит ваш удаленный почтовый ящик, так что даже другая программа не вмешается в этот процесс — по этой причине и вы не сможете дважды войти под одним почтовым эккаунтом.


Вот как может выглядеть типичная POP3 сессия — предполагается, что ошибок не возникает (S обозначает сообщения сервера, а С — клиента):

 

S +OK POP3 server ready
C USER ac
S +OK ac is real user
С PASS password
S +OK ac has 145 messages (967000 octets)
С STAT
S +OK 188  967000
C LIST
S ....
....
C QUIT

 

Я не буду особо вдаваться в этот протокол, замечу только, что мы можем в течение POP-сессии:

  • STAT получить от сервера общее количество писем;
  • LIST получить распечатку "номер письма-его размер";
  • TOP получить заголовок и несколько первых строк заданного письма г) RETR получить письмо полностью;
  • DELE/RSET удалить/отозвать письмо.

Более подробно об этом вы можете почитать (по-русски), например, здесь: www.codenet.ru/webmast/pop3.php. Мы же тем временем переходим к практике программирования на Python.


Прототип "очистительной" программы


Мы называем нашу программу "очистительной", хотя в полной версии она также делает много креативных вещей, например пересылает некоторые письма или уведомляет о получении. Как уже было сказано, Python имеет множество полезных библиотек, в том числе реализующих почтовые протоколы. Поэтому — в качестве награды за проницательность при выборе языка программирования — мы не должны реализовывать детали этого протокола (следить за CR+LF в конце посылаемых на сервер строк и т.д.).


В качестве прототипа моих программ был использован код из книги Марка Лутца "Программирование на Питон", стр. 565-567 (меня удивляют люди, делающие вид, будто они придумали что-то новое там, где уже все придумано другими). Вот немного упрощенный скелет программы, обрабатывающей почту,— распечатку отладочных дампов, естественно, можно убрать:

 

#!/usr/bin/python
import poplib,sys
srv=poplib.POP3('mail.comizdat.com')
svr.user('ac')
svr.pass_('password')
try:
   print svr.getwelcome()
   msgCount,msgBytes=svr.stat()
   print 'There is',msgCount,'messages in',msgBytes,'bytes'
   print svr.list()
   print '- '*40
   raw_input('[Press any key]')
   for i in range(msgCount):
      hdr,top,octets=srv.top(i+1,1)
      for line in top: print line
      print '- '*40
      if i
         raw_input('[Press any key]')
finally:
   svr.quit()
priny 'Bye'

 

Даже если вы никогда раньше не писали на Python, вам все и так должно быть ясно — я считаю это хорошим свойством языка. Если вы не в курсе, в Python роль операторных скобок типа { или } играют отступы — это экономит еще пару символов даже по сравнению с таким "жадным на слова" языком, как C, и делает код Python очень красивым. Этот пример выводит много информации на экран, но реальное приложение вместо этого будет делать действительно полезные вещи.


Поговорим немного о возможном "облегченном" алгоритме очистки почты. Здесь мы только извлекаем "топ", то есть заголовок писем и несколько первых строк. Загружать "топ" очень выгодно — размер заголовка обычно весит около 2 Кб, так что даже 100 писем дадут всего лишь 200 Кб. И заголовка, как правило, вполне достаточно для включения искусственного интеллекта "сортировщика". Не волнуйтесь о размере строк (ведь сейчас под строкой можно понимать и "крошку" в 2 Гб): почтовые программы всегда разбивают любое поле письма, в том числе и аттачмент в MIME-кодировке, на строки приемлемой длины — так что много мы не "утянем".


В заголовке можно поискать такие полезные вещи, как адреса из белого списка, а также "призраки спама". Как показал опыт, человек почти всегда может на основании заголовка и первых десяти первых строк определить "спам или нет". А раз это может решить человек, то и программе такое по силам — главное суметь передать свои знания.


У меня в этом смысле свой, совершенно изящный (хотя по сути — брутальный) подход: вместо сложных синтаксических анализаторов я просто использую список строк. Для любого получаемого мною спама оказалось достаточно всего-то 28 образцов (у вас будет не больше, но эти строки еще нужно найти!), которые ищутся, в целях экономии процессорного времени, во всем, что получено в ответ на TOP. При этом не задействуются такие сложные вещи, как регулярные выражения и разбор заголовков, а также интерпретация http-формата сообщения — вместо этого приходится тщательно продумывать, что может стать признаком спама.

Питоны и спам в реальной жизни


Программа, собственно MailCleaner ничего у меня не спрашивает, а "проходится" по сообщениям, получает их топ-1 и удаляет те сообщения, которые проходят на тест спама. Сама загрузка образцов производится бесцеремонно: загружается вся база данных в список и так далее — мы уже не в том веке, чтобы обращать внимание на загрузку пару килобайт данных в оперативную память. На вид этот код еще проще:

 

#!/usr/bin/python
...
   print 'There is',msgCount,'messages in',msgBytes,'bytes'
spamList=open('spam.rules','r').readlines()
   cnt=0
   for i in range(msgCount):
      hdr,top,octets=srv.top(i+1,1)
      topLine=''
      for j in top:topLine+=j.lower()
      for j in spamList:
         if topLine.find(j[:-1])>=0:
        srv.dele(i+1)
            cnt+=1
                 break
   finally:
      srv.quit()
   print 'All done, master -',cnt,'of',msgCount,'messages cleaned %[]'

 

Там же (заголовки ведь все равно получены) в реальной программе происходит и "позитив" — проверки по каждому сообщению идут одна за одной:

  • белый лист — форвард (Emergency);
  • белый лист — нотификация (Attention);
  • спам.

Можно предположить, что вдумчивый спамер может "подстроиться" под одного из моих "белых" корреспондентов, но я таких умных спамеров не видел — и не надеюсь увидеть. И хотя рассылки якобы "изнутри" нашей редакции встречаются — но их выдает поле Received from с одним из "стремных" серверов в качестве источника, а также несколько почтовых адресов в списке To:, которые не предназначены для реальных сотрудников. Запуская MailCleaner перед началом работы SpamTrainer’а, я всегда уверен в том, что уже введенные в базу варианты повторяться не будут.


Последние замечания


Как указывается в документации к Python, команда TOP не реализована на некоторых "самодельных" POP3-серверах как второстепенная. Поэтому, мол, относится к ней нужно осторожно. Я такого эффекта не обнаружил, так что пожаловаться на жизнь не могу, но если у вас по этой причине не станет работать мой код, то, возможно, закачку "верхушки" придется заменить на закачку всего сообщения.

2005.04.25
19.03.2009
В IV квартале 2008 г. украинский рынок серверов по сравнению с аналогичным периодом прошлого года сократился в денежном выражении на 34% – до $30 млн (в ценах для конечных пользователей), а за весь календарный год – более чем на 5%, до 132 млн долл.


12.03.2009
4 марта в Киеве компания Telco провела конференцию "Инновационные телекоммуникации", посвященную новым эффективным телекоммуникационным технологиям для решения задач современного бизнеса.


05.03.2009
25 февраля в Киеве компания IBM, при информационной поддержке "1С" и Canonical, провела конференцию "Как сохранить деньги в условиях кризиса?"


26.02.2009
18-19 февраля в Киеве прошел юбилейный съезд ИТ-директоров Украины. Участниками данного мероприятия стали ИТ-директора, ИТ-менеджеры, поставщики ИТ-решений из Киева, Николаева, Днепропетровска, Чернигова и других городов Украины...


19.02.2009
10 февраля в Киеве состоялась пресс-конференция, посвященная итогам деятельности компании "DiaWest – Комп’ютерний світ" в 2008 году.


12.02.2009
С 5 февраля 2009 г. в Киеве начали работу учебные курсы по использованию услуг "электронного предприятия/ учреждения" на базе сети информационно-маркетинговых центров (ИМЦ).


04.02.2009
29 января 2009 года в редакции еженедельника "Computer World/Украина" состоялось награждение победителей акции "Оформи подписку – получи приз!".


29.01.2009
22 января в Киеве компания "МУК" и представительство компании Cisco в Украине провели семинар для партнеров "Обзор продуктов и решений Cisco Small Business"

 

 
 
Copyright © 1997-2008 ИД "Комиздат".