Program filter pozwala na filtrowanie poczty w oparciu o zawartość jedynie czterech specyficznych pól nagłówka ("From:", "To:", "Subject:" i "Sender:"), oraz wielkość listu. Znacznym ograniczeniem jest również niemożliwość zastosowania kolejno kilku reguł do tego samego listu: po napotkaniu pierwszego spełnionego warunku i wykonaniu odpowiadającej mu akcji przetwarzanie reguł zostaje zakończone. Z tych powodów nawet autorzy programu filter uważają go obecnie za przestarzały i nie dołączają go już do najnowszych wersji pakietu elm (moim zdaniem niesłusznie, gdyż dla użytkownika o nieskomplikowanych wymaganiach odnośnie filtrowania poczty jest on wciąż bardzo wygodnym narzędziem), zalecając zamiast niego użycie do przetwarzania przychodzącej poczty programu o nazwie procmail.
Podstawowe funkcje programu procmail wydają się być analogiczne do tych, jakie zapewnia filter - przychodzący list może być zapisany do pliku, przesłany ("sforwardowany") na inny adres lub grupę adresów e-mail, bądź przekazany do obróbki przez dowolny program lub polecenie systemu Unix. O sile programu stanowi jednak możliwość łączenia tych funkcji (także kolejno kilku) z dowolnie złożonymi warunkami. Przeszukiwać można dowolne pola nagłówka, a także samą treść listu. Obok tradycyjnych warunków logicznych typu "tak-nie" można także definiować reguły, oceniające listy punktami: każde spełnienie przez dany list pewnego warunku (np. każde wystąpienie w treści listu słowa "money" albo "sex") dodaje lub odejmuje od ustalonej początkowej liczby punktów określoną wartość; końcowa suma decyduje o tym, czy akcja określona dla takiej reguły zostanie wykonana, czy też nie. Jeżeli dodać do tego zwyczajną w Unixie możliwość zapisywania bardzo złożonych kombinacji poleceń w postaci skryptów shella (które mogą być wywoływane z wnętrza procmaila), otrzymamy obraz zaiste bardzo potężnego narzędzia.
"|/usr/local/bin/procmail"
(zakładając oczywiście, że procmail w ogóle jest zainstalowany na
naszym serwerze - i że znajduje się on w katalogu /usr/local/bin;
podobnie jak w przypadku programu filter, także i tutaj do
ustalenia właściwego "miejsca pobytu" programu posłużyć może komenda
whereis). Chociaż plik .forward w postaci
przedstawionej powyżej działa poprawnie, autorzy programu zalecają
wywoływanie go za pośrednictwem polecenia exec, dającego
oszczędniejsze wykorzystanie pamięci, a więc plik przybierze postać
"|exec /usr/local/bin/procmail"
if (to = "list@listserv.com") then save "list_folder"
powodująca umieszczenie wszystkich listów otrzymanych z listy
dyskusyjnej o adresie list@listserv.com w pliku o nazwie
list_folder w katalogu macierzystym zamiast w domyślnej
skrzynce pocztowej (adres listy dyskusyjnej umieszczony jest w polu
"To:" nagłówka, jako że list jest adresowany do listy; pole
"From:" zawiera adres oryginalnego nadawcy), w wersji dla procmaila
przybierze postać:
:0:
* ^To:.*list@listserv.com
list_folder
Każda reguła w pliku .procmailrc składa się z kilku
(typowo trzech) wierszy. Pierwszy wiersz, sygnalizujący początek
reguły, rozpoczyna się znakami ":0" (dwukropek i zero), po których
może wystąpić kilka dodatkowych znaków, modyfikujących sposób
przetwarzania reguły (w tym przypadku występuje tam kolejny
dwukropek, którego znaczenie będzie omówione dalej). W kolejnych
wierszach umieszczamy jeden lub więcej warunków (w szczególnych
przypadkach może warunków nie być wcale) - każdy wiersz zawierający
warunek musi być poprzedzony znakiem gwiazdki. Wreszcie ostatni
wiersz zawiera akcję, która ma być wykonana w przypadku
spełnienia warunku (w razie, gdy warunków jest więcej niż jeden,
akcja jest wykonywana w przypadku spełnienia wszystkich
warunków). Dopuszczalna jest tylko jedna akcja, można jednak
definiować kolejne reguły uzależnione od poprzednich, wykonujące
kolejne akcje; można też umieścić w regule jako akcję
"zagnieżdżony", wewnętrzny blok kilku reguł. Jeżeli nasze przykładowe
listy z listy dyskusyjnej oprócz zapisywania do pliku chcielibyśmy
równocześnie forwardować do kolegi, który sam nie jest
zapisany na listę, moglibyśmy to zrealizować np. w następujący
sposób:
:0 c:
* ^To:.*list@listserv.com
list_folder
:0
* ^To:.*list@listserv.com
! kolega@firma.com.pl
Litera "c" w pierwszym wierszu pierwszej reguły nakazuje programowi,
aby mimo spełnienia warunku i wykonania akcji związanej z regułą
(zapisanie listu w pliku list_folder) nie przerywał przetwarzania -
jak robi to program filter - lecz przeszedł do kolejnej
reguły. Ponieważ w następnej regule nie występuje już "c", na niej
przetwarzanie się kończy.Przedstawiony sposób nie jest jednak najekonomiczniejszy, gdyż w drugiej regule następuje powtórne sprawdzanie warunku - przy skomplikowanych warunkach może to niepotrzebnie zajmować czas, a nadto istnieje niebezpieczeństwo pomyłki przy ich przepisywaniu... Lepsza jest następująca metoda:
:0 c:
* ^To:.*list@listserv.com
list_folder
:0 A
! kolega@firma.com.pl
Litera "A" w pierwszym wierszu drugiej reguły oznacza, że ma ona być
przetwarzana tylko wtedy, gdy warunek w poprzedniej regule (nie
zawierającej litery "A") był prawdziwy. W takim przypadku warunek w
samej tej regule nie jest już potrzebny - akcja wykonywana
jest zawsze, gdy spełniony był poprzedni warunek.Możemy też użyć zagnieżdżonego bloku reguł:
:0
* ^To:.*list@listserv.com
{
:0 c:
list_folder
:0
! kolega@firma.com.pl
}
W tym przypadku, jeżeli warunek zostanie spełniony, wykonywana
akcja polegać będzie na przetworzeniu reguł zawartych w
wewnętrznym bloku, tj. między znakami "{" i "}". Obie znajdujące się
tam reguły są pozbawione warunków - sprowadzają się zatem do
wykonania odpowiadających im akcji.Jak częściowo widać z przytoczonych już przykładów, w wierszu akcji może znajdować się znak "{", otwierający zagnieżdżony blok reguł, jeden lub więcej adresów e-mailowych poprzedzonych znakiem "!" - co powoduje przesłanie listu na wskazany adres lub adresy - bądź nazwa pliku. Jeżeli wiersz nie zaczyna się od żadnego ze znaków "{", "!" ani "|" (ten ostatni jest omówiony poniżej), traktowany jest jako nazwa foldera (pliku lub katalogu), do którego ma być zapisany list. W przypadku pliku list zostanie dodany do jego zawartości w ogólnie przyjętym formacie dla folderów pocztowych w Unixie; jeżeli nazwa określa istniejący katalog, list zostanie zapisany jako osobny plik w tym katalogu (o automatycznie dobranej, niepowtarzalnej nazwie). Jeśli podana nazwa pliku lub katalogu nie zawiera bezwzględnej ścieżki dostępu (nie zaczyna się od znaku "/"), traktowana jest jako określona względem katalogu macierzystego użytkownika.
W wierszu akcji rozpoczynającym się od znaku "|" możemy podać dowolne polecenie systemu Unix (w tym także potok bądź grupę poleceń ujętych w nawiasy, zgodnie z normalnymi regułami składni shella Unixowego), które zostanie wykonane z treścią listu przekazaną na standardowe wejście. W ten sposób moglibyśmy na przykład użyć programu kompresującego gzip do przechowywania poczty z listy dyskusyjnej w postaci spakowanej, zajmującej mniej miejsca na dysku:
:0 w:
* ^To:.*list@listserv.com
| /usr/local/bin/gzip >>lista.gz
(znaczenie litery "w", która pojawiła się w pierwszym wierszu tej
reguły, zostanie objaśnione dalej).Gdy wywołanie polecenia zawartego w wierszu akcji z jakiegoś powodu się nie powiedzie (zwróci niezerowy kod zakończenia), procmail zachowuje się tak, jakby warunek nie był spełniony - to znaczy przetwarza następne reguły. Dzięki takiemu zachowaniu, jeżeli w naszym przykładzie wywołanie programu gzip zakończyłoby się niepowodzeniem, list, który nie mógł być zapisany do pliku skompresowanego, nie zostanie stracony, lecz znajdzie się w naszej standardowej skrzynce pocztowej - przy założeniu, że w pliku .procmailrc nie ma już żadnych dalszych reguł manipulujących tym listem. Gdybyśmy bowiem chcieli - tak jak we wcześniejszych przykładach - dołączyć drugą regułę, przesyłającą pocztę do naszego kolegi:
:0 wc:
* ^To:.*list@listserv.com
| /usr/local/bin/gzip >>lista.gz
:0 A
! kolega@firma.com.pl
(rzecz jasna do znacznika "w" w pierwszej regule musieliśmy tu dodać
jeszcze znacznik "c"), wówczas - niezależnie od tego czy wykonanie
programu gzip powiodło się, czy nie - po wykonaniu drugiej
reguły przetwarzanie tak czy tak zostanie przerwane i list nie trafi
do skrzynki pocztowej. Właściwsze byłoby tu zapisanie reguł w
kolejności odwrotnej:
:0 c
* ^To:.*list@listserv.com
! kolega@firma.com.pl
:0 Aw:
| /usr/local/bin/gzip >>lista.gz
Porównawszy powyższy zestaw akcji z oferowanym przez
program filter wydawać by się mogło, że brakuje jednej, dość
istotnej możliwości: kasowania listów spełniających dany warunek.
Filozofia procmaila jest tu dość prosta: aby skasować list, wystarczy
"zapisać" go do specjalnego pliku w Unixie, określającego tzw.
urządzenie puste (null device). Plik ten nosi nazwę
/dev/null i ma tę właściwość, iż wszelkie "zapisywane" do
niego dane... znikają bez śladu (urządzenie puste istnieje także w
systemie DOS/Windows, pod nazwą NUL). A więc aby np. skasować
wszystkie listy zawierające w temacie słowo "adult" piszemy:
:0
* ^Subject:.*adult
/dev/null
W programie filter operacja save używa semaforów automatycznie; w procmailu musimy każdorazowo jawnie określić, że dla danej reguły ma być stosowany semafor. Daje to nam jednak możliwość objęcia ochroną za pomocą semaforów nie tylko plików, do których procmail bezpośrednio zapisuje pocztę, lecz także plików tworzonych przez uruchamiane z jego wnętrza programy, tak jak w przedstawionym wyżej przykładzie z programem gzip. Przykład ten dopisuje skompresowaną treść listu do pliku lista.gz; w tym przypadku w pierwszym wierszu reguły użyliśmy dodatkowo litery "w", aby zaznaczyć, że procmail ma czekać z "podniesieniem" semafora aż do zakończenia działania programu gzip. Gdyby tej litery nie było, semafor zostałby "podniesiony" natychmiast po wczytaniu przez program gzip treści listu ze standardowego wejścia, co nie dawałoby pełnej gwarancji, iż nie nastąpią równoczesne próby zapisu do pliku lista.gz przez kilka programów. Dlatego czekamy do całkowitego zakończenia działania programu.
Nazwę pliku semafora (semafory realizowane są w postaci plików na dysku, więc - jak każdy plik - muszą mieć nazwy) procmail w większości typowych przypadków jest w stanie określić sam na podstawie nazwy pliku wyjściowego, do którego zapisywana jest poczta. Jednak w przypadkach niektórych bardziej skomplikowanych poleceń, w których trudno wprost wskazać plik "wyjściowy", może być niezbędne jawne podanie nazwy pliku semafora. Podaje się ją wówczas po dwukropku określającym, że ma być stosowany semafor, jak w poniższym przykładzie, zaczerpniętym z dokumentacji procmaila (reguła ta służy do eliminowania duplikatów listów - do tego przykładu wrócimy jeszcze w dalszej części tekstu). Używany będzie plik semafora o nazwie msgid.lock:
:0 wh: msgid.lock
| formail -D 8192 msgid.cache
Najprostszą postacią wyrażenia regularnego jest zwykły tekst; jeżeli w regule zapiszemy następujący warunek:
* adult
(pamiętamy, że każdy wiersz z warunkiem w pliku .procmailrc
rozpoczyna się od znaku gwiazdki), to będzie on spełniony, gdy
gdziekolwiek w nagłówku listu znaleziony zostanie tekst
"adult". Może on wystąpić w dowolnym polu: w temacie, adresie
e-mailowym lub nazwisku nadawcy lub odbiorcy, identyfikatorze
wiadomości, czy też w jednym z licznych zwykle nagłówków "Received:",
dodawanych do naszego listu przez kolejne przesyłające go serwery
pocztowe - albo jeszcze gdzieś indziej... Tak ogólny warunek jest
raczej mało przydatny, dlatego zwykle precyzujemy go, zapisując
wyrażenia takie jak te, których używaliśmy już w poprzednich
regułach:
* ^Subject:.*adult
czy
* ^To:.*list@listserv.com
Znak "^" w wyrażeniu regularnym ma specjalne znaczenie - oznacza
początek wiersza. Para znaków ".*" zastępuje natomiast ciąg dowolnych
znaków, o dowolnej długości - w tym także zerowej (nieco podobnie do
znaku "*" w nazwach plików w DOS-ie czy Windows - nazwy takie są
zresztą przykładem bardzo uproszczonych wyrażeń regularnych).
Pierwsze z wymienionych powyżej wyrażeń "pasuje" zatem do wiersza w
nagłówku listu, rozpoczynającego się od tekstu "Subject:", po którym
to tekście, oddzielony od niego dowolnym ciągiem znaków (może nie być
oddzielony niczym) następuje tekst "adult". Dalsza część wiersza nie
jest określona w wyrażeniu; może zawierać cokolwiek. W efekcie,
wyrażenie to pasuje do dowolnego wiersza zaczynającego się od tekstu
"Subject:" i zawierającego gdziekolwiek w dalszej treści tekst
"adult" (procmail przy porównywaniu tekstów nie rozróżnia dużych i
małych liter, chyba że jawnie nakaże mu się to zrobić). Podobnie
drugie wyrażenie oznacza wiersz zaczynający się tekstem "To:" i
zawierający "list@listserv.com". Ściśle rzecz biorąc, ponieważ kropka
w wyrażeniu regularnym zastępuje dowolny znak, w istocie warunek
będzie spełniony nie tylko dla wierszy zawierających dokładnie
"list@listserv.com", ale także gdy w miejscu kropki znajduje się
dowolny inny znak, np. "list@listservicom". Chcąc zapewnić, aby
wyrażenie pasowało tylko do wierszy zawierających w tym miejscu
faktyczną kropkę, musimy poprzedzić ją znakiem "\":
* ^To:.*list@listserv\.com
Podobna zasada obowiązuje, gdy w wyrażeniu chcemy umieścić w postaci
"dosłownej" inne znaki specjalne, takie jak * czy ^.Można tworzyć oczywiście bardziej skomplikowane wyrażenia:
* ^Subject:.*mass.+mail
Warunek ten "wychwytuje" wiersze Subject: zawierające teksty "mass" i
"mail" oddzielone przynajmniej jednym znakiem (a więc może to być np.
"mass-mailing", "mass e-mail" itp.). Znaki ".+", podobnie jak ".*",
oznaczają dowolny ciąg znaków, z tym, że w tym przypadku znaków tych
musi być co najmniej jeden (dla ".*" może ich być zero).Warunek o postaci
* ^Subject:.*(adult|sex|girls|porn)
jest spełniony, gdy wiersz rozpoczynający się od "Subject:" zawiera
dowolny z oddzielonych znakami "|" tekstów umieszczonych w nawiasach.Wyrażenia regularne stosowane w procmailu są zgodne z wyrażeniami regularnymi używanymi przez standardowy Unixowy program do przeszukiwania plików tekstowych, egrep - dokładniejsze informacje na temat ich składni można zatem znaleźć w opisie tego ostatniego (man egrep). Oprócz tego procmail zawiera kilka specjalnych wyrażeń regularnych, przydatnych przy analizowaniu poczty. Tekst "^TO" (istotne jest zapisanie go dużymi literami) służy do identyfikowania adresata listu; warunek
* ^TOkowalski@firma\.com\.pl
będzie spełniony, gdy dowolny nagłówek wskazujący na adresata (a więc
niekoniecznie "To:", ale także np. "Cc:", "Bcc:", czy - występujący w
listach forwardowanych z innego konta - "Resent-To:") będzie
zawierał tekst "kowalski@firma.com.pl". Innymi słowy - jest on
spełniony dla listów, które zostały w ten czy innym sposób wysłane do
użytkownika kowalski@firma.com.pl bezpośrednio, w
odróżnieniu od listów otrzymanych np. z list dyskusyjnych.Z kolei warunek o postaci
* ^FROM_DAEMON
(znowu istotne są duże litery) "pasuje" do większości listów
wysyłanych automatycznie przez programy, takich jak np. zwroty
"odbitej" poczty, komunikaty od listserwerów itp. "Wychwytuje" także
pocztę przychodzącą z części list dyskusyjnych. Warunek ten można
wykorzystać np., gdy definiujemy w pliku .procmailrc regułę
realizującą automatyczne odpowiadanie na listy, aby na tego typu
listy nie wysyłać odpowiedzi. Jego "okrojoną" wersją, rozpoznającą
tylko listy wysyłane przez serwery pocztowe (głównie komunikaty o
niemożliwości dostarczenia poczty), jest "^FROM_MAILER".Jak zostało powiedziane wcześniej, domyślnie jedynie nagłówek listu jest przeglądany w poszukiwaniu wyrażeń regularnych; sytuację tę można zmienić podając odpowiednie znaczniki w pierwszym wierszu reguły. Umieszczenie tam litery "B" powoduje, że przeszukiwana będzie tylko treść listu (a nie nagłówek); umieszczenie zaś liter "HB" powoduje poszukiwanie wyrażeń zarówno w nagłówku, jak i w treści listu. Przykładowo reguła
:0 HBc
* zebranie
! kolega@firma.com.pl
powoduje przekazanie na adres kolegi (z równoczesnym pozostawieniem w
naszej skrzynce pocztowej - znacznik "c") wszystkich listów
zawierających gdziekolwiek w treści bądź w nagłówku słowo "zebranie".Umieszczenie na początku warunku znaku "!" powoduje jego zaprzeczenie; na przykład poniższa reguła powoduje zapisanie do pliku o nazwie "biurowe" wszystkich listów wysłanych przez użytkownika "biuro", nie zawierających w temacie ciągu znaków "piln" (pilne, pilny, pilnie itp...) ani nie mających ustawionego statusu listu pilnego (nagłówek "Priority: urgent"):
:0:
* ^From:.*biuro
* !^Subject:.*piln
* !^Priority: urgent
biurowe
Innymi przydatnymi warunkami, nie będącymi już wyrażeniami
regularnymi, są warunki
* < liczba
oraz
* > liczba
spełnione odpowiednio, gdy wielkość listu jest mniejsza lub większa
od podanej liczby bajtów.
:0 B
* -3^0
* 1^1 money
/dev/null
Jak można zauważyć, w stosunku do zwykłego warunku warunek "punktowy"
rozszerzony jest o dodatkowy człon postaci "w^x", gdzie
w i x mogą być dowolnymi liczbami rzeczywistymi.
Wartość w to tzw. waga: oznacza ona liczbę punktów,
która będzie "zaliczona" za wystąpienie danego wyrażenia (jeżeli nie
określono żadnego wyrażenia - tak jak w drugim wierszu w regule
powyżej - dana liczba punktów zostanie zaliczona zawsze). Wartość
x stanowi tzw. wykładnik: ten z kolei decyduje o tym,
jak bardzo będą liczyć się kolejne wystąpienia danego wyrażenia
regularnego w stosunku do pierwszego. Gdy dane wyrażenie zostanie
znalezione w treści listu po raz pierwszy, zaliczana mu jest liczba
punktów równa w; gdy wystąpi po raz drugi - w*x, po raz
trzeci - w*x*x; i tak dalej... Typowe przypadki to wartości
x=0 - wówczas liczy się tylko pierwsze wystąpienie danego wyrażenia,
oraz x=1 - wówczas każde wystąpienie danego wyrażenia liczy się
jednakowo, i dodaje liczbę punktów równą w.W ostatecznym wyniku warunek uważa się za spełniony, jeżeli końcowa suma punktów jest większa od 0. W przedstawionej powyżej regule zatem każdemu listowi przypisywana jest na początek wartość -3 punkty (-3^0). Następnie każde wystąpienie słowa "money" zwiększa tę liczbę o 1 punkt (1^1). Jeżeli słowo to wystąpiło więcej niż 3 razy, końcowa suma punktów jest większa od zera i wykonywana jest akcja, polegająca na skierowaniu listu do /dev/null.
Innym przykładem może być eliminowanie listów, zawierających więcej cytatów (wierszy zaczynających się znakiem ">") niż własnego tekstu nadawcy listu - rzecz użyteczna zwłaszcza przy czytaniu poczty pochodzącej z list dyskusyjnych. Można to osiągnąć przy pomocy następującej reguły:
:0
* !^TOkowalski@firma\.com\.pl
{
:0 B
* 1^1 ^>
* -1^1 ^[^>]
/dev/null
}
Reguła ta w istocie, jak widać, składa się z dwóch zagnieżdżonych
reguł: zewnętrzna analizuje nagłówek listu, pomijając listy, które są
adresowane bezpośrednio na konto danego użytkownika. Nie chcemy
bowiem, aby list adresowany bezpośrednio do nas został przypadkowo
skasowany; interesuje nas jedynie filtrowanie korespondencji z list
dyskusyjnych. Jeżeli taki list zostanie znaleziony, uaktywniana jest
druga, wewnętrzna reguła, analizująca treść listu (właśnie potrzeba
analizowania przez jeden z warunków nagłówka, a drugi treści, była
powodem zastosowania dwu oddzielnych reguł, choć nie jest to jedyny
sposób, w jaki można to uzyskać). Wyrażenie regularne "^>" określa
wiersze rozpoczynające się od znaku ">"; za kady taki wiersz dodawany
jest jeden punkt. Z kolei za każdy wiersz rozpoczynający się znakiem
innym niż ">" (wyrażenie regularne postaci "[^lista-znaków]"
oznacza jakikolwiek znak różny od znaków zawartych na liście, a
więc "[^>]" to jakikolwiek znak różny od znaku ">") odejmowany jest
jeden punkt. Jeżeli suma punktów jest dodatnia (a zatem wiersze
zaczynające się od ">" są w przewadze), list trafia do /dev/null.
Na serwerze Novell istnieje możliwość autoforwardu poczty pod inny adres, jak również prosty mechanizm automatycznej odpowiedzi podobny nieco (choć uboższy w możliwościach) do Unixowego vacation, jednak żadne bardziej zaawansowane możliwości, np. filtrowania poczty na serwerze, nie są dostępne (filtrowanie odbywa się na poziomie klienta pocztowego). Dlatego całą pocztę z serwera Novell - pozostawiając ją oczywiście na tym serwerze do bezpośredniego czytania - forwarduję również na konto Unixowe, gdzie za pomocą procmaila dokonuję odpowiedniej obróbki poczty z obu (a właściwie, licząc adres przeznaczony dla listy providerów - z trzech) kont.
Gdy jestem poza pracą i domem, nie interesuje mnie z reguły czytanie poczty z kilku mniej ważnych list dyskusyjnych, na które jestem zapisany; poczta z tych list jest zatem kasowana - i tak pozostaje przecież na serwerze Novell, gdzie będę ją mógł przeczytać po powrocie. Stąd te początek mojego pliku .procmailrc wygląda następująco:
:0
* ^TOzen@uci\.agh\.edu\.pl
/dev/null
:0
* ^TOGURU@plearn\.edu\.pl
/dev/null
:0
* ^TOdoslynx-dev@.*ukans\.edu
/dev/null
Chcę czytać pocztę z listy polip@man.lodz.pl, nie chcę
jednak jej mieszać z "normalną" zawartością mojej skrzynki pocztowej.
Dlatego umieszczam ją w osobnym folderze, który będę mógł odczytywać
za pomocą programu pine (podkatalog mail jest
katalogiem, w którym pine domyślnie poszukuje folderów z pocztą):
:0:
* ^TOpolip@man\.lodz\.pl
mail/from-polip
Teraz zaczyna się ciekawa część pliku. Zwykle jest ona
"wyłączona" poprzez zamienienie jej w komentarze (znak "#" na
początku kadego wiersza); uaktywniam ją - poprzez usunięcie znaków
"#" - gdy wyjeżdżam na wakacje, lub z innego powodu przez dłuższy
czas nie będę czytał poczty:
#:0 ch
#* !^TOproviders
#* !^FROM_DAEMON
#* !^From:.*Jaroslaw Rafa
#* !^From:.*raj@.*wsp\.krakow\.pl
#* !^To:.*Multiple recipients
#* !^X-listname:.*
#* !^X-Listprocessor-Version:.*
#* !^Precedence:.*discussion
#* !^Return-Path:.*<owner-
#| /usr/bin/vacation -t20d raj
W takiej sytuacji wykorzystuję program vacation (por. pierwsza
część tekstu) do wysłania automatycznej odpowiedzi informującej o
mojej nieobecności. Nie chcę jednak odsyłać tej odpowiedzi na listy
przysłane na adres dotyczący listy providerów (na nie wysyłana
jest odrębna automatyczna odpowiedź, o czym jeszcze będzie mowa pod
koniec artykułu), sprawdzam zatem, czy list nie był adresowany na
konto "providers". Nie chcę odpowiadać na listy wysłane przez
automaty (np. zwroty niedoręczonej poczty) - warunek
"!^FROM_DAEMON". Nie ma również sensu odpowiadanie na ewentualne
listy od samego siebie. Warto zwrócić uwagę na sformułowanie
warunków rozpoznających te listy: ignorowane będą listy zawierające w
polu "From:" moje nazwisko, jak również listy wysłane z konta o
nazwie "raj" z dowolnego komputera w domenie wsp.krakow.pl.
Powinno to zapewnić pominięcie wszelkich listów wysłanych przeze
mnie, niezależnie od tego, z jakiego konta były wysyłane.Pozostałe warunki w tej regule służą zignorowaniu możliwie wielu charakterystycznych nagłówków, obecnych w poczcie z list dyskusyjnych, aby nie wysłać odpowiedzi na list otrzymany z takiej listy. Zwróćmy uwagę na znacznik "c" w pierwszym wierszu reguły - listy, na które została wysłana automatyczna odpowiedź, mają rzecz jasna pozostać w skrzynce pocztowej i być dalej przetwarzane przez procmail. Oprócz niego występuje też znacznik "h", powodujący, że do programu vacation przekazywany jest tylko nagłówek listu zamiast całej - być może długiej - jego treści; ta bowiem dla programu jest zbyteczna.
Zbliżamy się do końca pliku. Pozostaje jeszcze rozdzielenie dla wygody poczty sforwardowanej z konta na serwerze Novell - wędruje ona do foldera o nazwie "from-inf" - od poczty wysłanej bezpośrednio na konto Unixowe (pozostaje w standardowej skrzynce). Wyjątek stanowi tutaj jednakże poczta w sprawie listy providerów, którą otrzymuję czasem na konto na Novellu: takie listy ręcznie przesyłam sobie na konto "providers" i powinny one zostać w domyślnej skrzynce. Warto zwrócić uwagę, że rozdzielenia tego dokonujemy dopiero teraz - po ewentualnym wysłaniu automatycznej odpowiedzi programem vacation, dzięki czemu odpowiedź ta wysyłana jest dla listów przychodzących na obydwa konta. W regule wykorzystywane są charakterystyczne nagłówki, które system pocztowy serwera Novell wstawia przy forwardowaniu listu:
:0:
* ^Resent-From:.*raj@inf
* !^Resent-To:.*providers@
mail/from-inf
Obiecującym rozwiązaniem może tu być wykorzystanie możliwości "punktowej" oceny treści listu. Technikę tę wykorzystuje poniższa reguła, opracowana przez Pawła Krawczyka z krakowskiej firmy CETI Internet:
:0 HB:
* -250^0
* -1000^0 ^FROM.+@.+\.pl
* -2000^0 ^FROM.+@.+\.ceti\.com\.pl
* 100^0 !^From:
* 200^0 !^To:
* 100^0 !^Subject:
* 200^0 Received.*(advertise|stealth|bulk|sex)
* 100^2 Received.(comanche|apache).+(net|com|org)?
* 50^2 ^(From|To).*(sex|adult|porn)
* 200^0 Message-ID.*(advert|bulk|lov(e|ing)|aegispam)
* 190^0 ^Subject.*(\ sex|adult|porn|gay|erotic|advert|\ xxx\ |
zaprosz|bulk.+email|revenue|expense|profit|sperm|money|earn|
cash|free|lingerie)
* 20^0 ^Subject.*\$
* 100^0 ^Subject.*\$\$
* 500^0 ^Subject.*\$\$\$
* 20^0 ^Subject.*\!
* 100^0 ^Subject.*\!\!
* 300^0 ^Subject.*\!\!\!
* 50^2 ^PP-Warning:
* 20^2 \ sex|^sex|adult|erotic|gay|porn|chain.+letter|sponsor|\ xxx\ |
^xxx\ |bulk|girls|hardcore|\ cum|advertise|remove|revenue|
expense|profit|sperm|money|marketing|targeted\ search|
collect.+email|\ pay|lingerie|org(y|ies)|teens|sign\ up\ now
* 10^2 subject.+remove
* 10^2 remove.+(subject|request|list)
* 10^2 reply.*remove
* 10^2 one\ time.*(mail|message)
* 5^2 video|pictures|earn
IN.spam-catcher
Rozpoczynamy od wartości -250 punktów. Jeżeli list pochodzi z
Polski (adres "From:" kończy się na ".pl"), otrzymuje dodatkowo -1000
punktów - większość spamów pochodzi spoza Polski. Listom wysłanym z
domeny ceti.com.pl (oczywiście adaptując tę regułę dla własnych
potrzeb trzeba tu wstawić nazwę swojej własnej domeny) ujmuje się
jeszcze 2000 punktów, co niemal gwarantuje "przepuszczenie" listu
przez dalszą część reguły.Teraz rozpoczynamy liczenie punktów dodatnich. Po 100 punktów otrzymuje list za brak nagłówków "From:" lub "Subject:"; 200 punktów za brak nagłówka "To:". Kolejne punkty doliczane są w razie wykrycia w nagłówkach "Received:", "From:", "To:" lub "Message-Id:" charakterystycznych fragmentów adresów, które znajdywane były w wielu listach-spamach. Następnie sprawdzana jest obecność charakterystycznych słów, takich jak "sex" czy "cash", w temacie listu (ze względu na czytelność, warunek analizujący pole "Subject:" został powyżej rozdzielony na kilka wierszy, w rzeczywistości jednak powinien być zapisany jako jeden długi wiersz). 20 punktów otrzymuje list, w którego polu "Subject:" wystąpi znak dolara. Jeżeli jednak wystąpią dwa takie znaki jeden za drugim, doliczane jest dodatkowe 100 punktów, jeżeli zaś w temacie listu występuje ciąg aż trzech znaków "$" - dodaje się jeszcze 500 punktów. Analogicznie traktowane są występujące w temacie listu wykrzykniki.
Wreszcie przechodzimy do analizy treści listu. Kolejny długi warunek (podobnie jak poprzedni, powinien on być zapisany w jednym wierszu) poszukuje w treści listu słów kluczowych. Warto zwrócić uwagę na użyty w tym warunku wykładnik 2: oznacza on, że za pierwsze wystąpienie któregoś z wymienionych na liście słów bądź zwrotów list otrzyma 20 punktów, ale za następne - już 40 (20*2), za jeszcze następne - 80 (20*2*2), i tak dalej... Na zakończenie sprawdzana jest obecność często umieszczanej w treści spamów informacji, że jest to "jednorazowa przesyłka" (one time e-mail message), lub że dla wypisania się z listy należy wysłać odpowiedź z polem "Subject:" zawierającym "remove". Za wystąpienie jednego z charakterystycznych zwrotów doliczane jest 10 punktów.
Jeżeli list w wyniku tych wszystkich operacji uzyska dodatnią liczbę punktów, zapisywany jest do foldera o nazwie "IN.spam-catcher"; teoretycznie można byłoby go od razu skasować, ale ze względu na dość skomplikowaną i wysoce empiryczną konstrukcję reguły nie mamy żadnej gwarancji, że nie "wyrzuci" nam ona przypadkiem całkiem "normalnego" listu, nie zasługującego na takie potraktowanie. Dlatego lepiej przeglądać od czasu do czasu zawartość tego foldera i "naocznie" dokonywać ostatecznej weryfikacji odfiltrowanych listów.
:0 wh: msgid.lock
| formail -D 8192 msgid.cache
Wiele kopii tego samego listu może być spowodowanych np. wysłaniem
przez nadawcę tego samego listu na kilka list dyskusyjnych, na które
jesteśmy zapisani - wówczas dostaniemy po jednej kopii z każdej listy
(sytuacja taka jest szczególnie prawdopodobna, gdy listy sprzężone są
z grupami newsowymi). Przyczyną pojawiania się duplikatów może
być też błędne działanie programu używanego przez nadawcę: z
wysyłania w pewnych okolicznościach kilku kopii tego samego listu
znane są zarówno Outlook Express, jak i Netscape.Zastosowana w powyższej regule metoda eliminowania duplikatów opiera się na fakcie, iż każdy list wysłany pocztą elektroniczną lub do grupy newsowej zawiera w nagłówku niepowtarzalny identyfikator wiadomości (Message-Id:), nadawany przez program wysyłający. Każdy z Czytelników może łatwo odnaleźć nagłówki Message-Id: w listach znajdujących się we własnej skrzynce pocztowej; mogą one wyglądać na przykład tak:
Message-Id: <I_ks2.8075$014.827218@news.tpnet.pl>
Ze względu na sposób tworzenia identyfikatora, nie istnieją dwa różne
listy posiadające takie samo pole Message-Id: - dwa listy o takim
samym identyfikatorze z pewnością są dwiema kopiami tego samego
listu. Nie oznacza to, że listy o różnym Message-Id: są na pewno
różne - nadawca mógł przecież sam powtórnie wysłać identyczny list,
albo któryś serwer list dyskusyjnych mógł zmienić oryginalne pole
Message-Id: listu (choć jest to wysoce niewskazane, niektóre programy
obsługujące listy dyskusyjne tak robią), ale to już nieco inna
sprawa.Reguła wykorzystuje wchodzący w skład pakietu procmaila pomocniczy program o nazwie formail, będący uniwersalnym narzędziem do analizowania i modyfikowania nagłówków poczty. Program ten wywołany z parametrem -D sprawdza, czy identyfikator aktualnie przetwarzanego listu występuje w pliku o nazwie wymienionej w wywołaniu programu (w tym przypadku msgid.cache). Jeżeli identyfikatora bieżącego listu jeszcze w tym pliku nie ma, formail dopisuje go do pliku - tak więc ewentualny następny list z tym samym Message-Id: zostanie już zidentyfikowany jako duplikat (ze względu na tę modyfikację pliku konieczne jest użycie semafora) - i zwraca kod zakończenia różny od zera. W Unixie taki kod traktowany jest jako niepowodzenie wykonania programu, zatem procmail przetwarza list dalej, stosując do niego kolejne reguły z pliku .procmailrc lub - jeżeli dalszych reguł już nie ma - umieszczając w domyślnej skrzynce pocztowej. Jeżeli natomiast formail wykryje duplikat, to kończy działanie z kodem powrotu równym 0, co dla Unixa oznacza "sukces". Dalsze reguły nie będą więc przetwarzane - list, "zjedzony" przez program formail, nie trafi do skrzynki. Oczywiście najbardziej sensowne jest umieszczenie tej reguły na początku pliku .procmailrc, przed innymi regułami - np. rozdzielającymi pocztę z poszczególnych list dyskusyjnych do odpowiednich folderów.
Na uwagę zasługuje w tej regule jawne określenie nazwy pliku semafora, której procmail w tym przypadku nie jest w stanie ustalić sam. Warto zwrócić też uwagę na użycie znacznika "h", powodującego przekazanie do programu formail tylko nagłówków listu. Podana w wywołaniu formaila wartość 8192 zapobiega niekontrolowanemu rozrastaniu się pliku msgid.cache, ograniczając jego wielkość do 8 KB.
Aby przesłać wiadomość na telefon komórkowy z użyciem bramki Plus GSM, należy wysłać list na adres:
+48601xxxxxx@text.plusgsm.pl
gdzie "xxxxxx" jest numerem telefonu w sieci Plus GSM. Teoretycznie
zatem wydawałoby się, że do przekazywania poczty na "komórkę"
wystarczy zwykły plik .forward z wpisanym powyższym adresem.
Niestety, ten sposób nie działa. Winę za to ponosi serwer pocztowy
obsługujący bramkę text.plusgsm.pl. Serwer ten działa w oparciu o
oprogramowanie Microsoft Exchange, które ma błąd w implementacji
protokołu SMTP: zamiast pobierać adres odbiorcy poczty z komendy RCPT
wysyłanej przez serwer nadający - tak jak nakazuje to odnośny dokument
RFC - pobiera go z nagłówka "To:" otrzymywanego listu. Skutkiem tego
oprogramowanie to jest niezdolne do prawidłowego odbierania
jakichkolwiek listów autoforwardowanych z innego adresu, gdyż
w polu "To:" takiego listu występuje adres oryginalnego
odbiorcy, a nie adres, na który list jest przekazywany.Obejście tego dokuczliwego błędu możliwe jest znów dzięki wykorzystaniu programu formail - tym razem do zamiany nagłówka "To:" w liście przesyłanym do bramki Plusa na taki, jakiego spodziewa się Exchange. Najprostsza reguła przekazująca treść listu na telefon komórkowy może mieć postać:
:0 c
* !^From grapevine@text\.plusgsm\.pl
| formail -k -X Subject: -X From: -X To: \
-I "To: <+48601xxxxxx@text.plusgsm.pl>" | $SENDMAIL -t
(znak "\" umieszczony na końcu polecenia Unixowego oznacza
kontynuację komendy w następnym wierszu). Program formail
wywołany z parametrami jak powyżej pozostawia z nagłówków
oryginalnego listu jedynie pola "From:" i "Subject:" (wymienione w
parametrach -X), natomiast adres w polu "To:" zamienia na
podany w parametrze -I. Tak spreparowany list przekazywany
jest do programu sendmail, zajmującego się wysłaniem poczty. Zmienna
środowiskowa $SENDMAIL, ustawiana automatycznie przez procmaila,
podaje faktyczną ścieżkę dostępu do tego programu - zwykle jest to
/usr/lib/sendmail. Umieszczony w powyższej regule warunek nakazuje
ignorowanie listów przychodzących z adresu grapevine@text.plusgsm.pl
- spod takiego adresu oprogramowanie bramki Plus GSM wysyła
komunikaty o niemożliwości dostarczenia wiadomości na telefon. Chodzi
tu zatem o zapobieżenie "pętli pocztowej" - gdyby program próbował
przesyłać na telefon taki komunikat, otrzymałby kolejny komunikat o
niemożliwości dostarczenia itd...Bramka Plus GSM ogranicza ilość listów, które mogą być w określonym czasie przesyłane na dany numer telefonu, dlatego możemy chcieć przesyłać na "komórkę" tylko listy adresowane bezpośrednio do nas, z pominięciem poczty z list dyskusyjnych. Dodatkowo, ponieważ krótkie wiadomości tekstowe są naprawdę krótkie (160 znaków), sensowne może być wyeliminowanie z listu wszystkich wierszy zawierających cytaty - inaczej na wyświetlaczu telefonu moglibyśmy nic nie zobaczyć z właściwej treści listu. Za pomocą standardowego Unixowego narzędzia grep usuwamy z treści listu wszystkie wiersze zaczynające się od ">":
:0 c
* ^TOuzytkownik@domena\.com\.pl
* !^From grapevine@text\.plusgsm\.pl
| formail -k -X Subject: -X From: -X To: \
-I "To: <+48601xxxxxx@text.plusgsm.pl>" | grep -v "^>" | $SENDMAIL -t
Jako się rzekło, zagadnienie przesyłania poczty na telefon
komórkowy jest popularne w środowisku polskich użytkowników
Internetu. Można więc znaleźć w sieci cały szereg reguł, programów,
skryptów realizujących to zadanie - zarówno przeznaczonych dla
procmaila, jak też wywoływanych bezpośrednio z pliku .forward.
Istnieją też rozwiązania przeznaczone dla nietypowych systemów
transportu poczty, stosowanych w niektórych odmianach Unixa (np. SCO
Unix). Więcej informacji na ten temat znaleźć można pod adresami:
Wysyłając pocztę pod adresy różnych firm, możemy czasami spotkać się z autoresponderami: wysłanie listu na określony adres powoduje odesłanie automatycznej odpowiedzi o wcześniej przygotowanej treści. Odpowiedź taka może np. potwierdzać otrzymanie listu i informować, w jakim czasie można spodziewać się odpowiedzi - tego typu autorespondery stosują przykładowo działy obsługi technicznej dużych firm komputerowych. W takim przypadku nasza poczta zostanie jeszcze przeczytana przez człowieka, i oprócz odpowiedzi z autorespondera dostaniemy w późniejszym terminie "normalną" odpowiedź. Mogą być jednak także autorespondery całkowicie "bezludne", w przypadku których na listy wysłane na określone konto (np. info@firma.com.pl) odsyłana jest jedynie standardowa, automatyczna odpowiedź i list jest kasowany bez czytania - w treści listu znajduje się wówczas zazwyczaj odpowiednia informacja oraz "ludzkie" adresy, pod którymi należy się kontaktować w określonych sprawach.
Przy pomocy tandemu procmail i formail możemy stosunkowo prosto zrealizować obydwa typy autoresponderów. Typowa realizacja autorespondera w procmailu wygląda następująco:
:0 hc
* ^TOinfo@firma\.com\.pl
* !^FROM_DAEMON
* !^X-Loop: info@firma\.com\.pl
| (formail -r -A "Precedence: junk" \
-A "X-Loop: info@firma.com.pl" ; \
cat info.reply) | $SENDMAIL -t
Powyższa reguła może być wpisana w pliku .procmailrc dla
konta info@firma.com.pl, traktowanego jako "ogólne" konto
e-mailowe firmy. Jak widać, przy wysyłaniu odpowiedzi uwzględniane są
tylko listy adresowane bezpośrednio na to konto, nie pochodzące od
automatów (np. serwerów pocztowych) i nie zawierające specyficznego
nagłówka "X-Loop:", stanowiącego zabezpiecznie przed pętlą pocztową
(zob. poniżej). Jeżeli list spełnia ten warunek, za pomocą programu
formail generowany jest nagłówek odpowiedzi. Użycie parametru
-r automatycznie generuje pole "To:" zawierające adres nadawcy
oryginalnego listu oraz pole "Subject:", zawierające oryginalny temat
poprzedzony przez "Re:". Za pomocą parametrów -A dodawane są
do tego nagłówka pola "Precedence:" i "X-Loop:". Pierwsze z nich ma
na celu zapobieżenie temu, aby inne autorespondery nie odpowiadały na
wysłaną przez nas odpowiedź. Nagłówek "Precedence: junk" zwyczajowo
traktowany jest jako sygnał, że list pochodzi od automatu (jest on
uwzględniany m.in. przez wyrażenie ^FROM_DAEMON w procmailu). Jeżeli
zatem zdarzyłoby się nam wysłać odpowiedź z takim nagłówkiem na
konto, które również wyposażone jest w autoresponder, ten ostatni
powinien rozpoznać, że ma do czynienia z listem wygenerowanym
automatycznie i nie wysyłać własnej odpowiedzi.Pole "X-Loop:" stanowi dodatkowe zabezpieczenie przed pętlą pocztową. Gdyby wysłana przez nas odpowiedź jakimś sposobem (np. poprzez autoforward) trafiła z powrotem na nasze konto, warunek umieszczony w regule rozpozna obecność nagłówka "X-Loop:" i uniemożliwi wysłanie odpowiedzi do samego siebie.
Do wygenerowanego w powyższy sposób nagłówka dopisywana jest Unixową komendą cat treść odpowiedzi, znajdująca się w pliku o nazwie info.reply, i całość przekazywana jest - jak w poprzednim przykładzie - do programu sendmail. List pozostawiany jest w skrzynce pocztowej (znacznik "c" w pierwszym wierszu reguły), a więc tego typu autoresponder przeznaczony jest dla kont, na których poczta będzie jeszcze czytana przez człowieka. Aby uzyskać autoresponder "bezludny", należałoby po prostu ten znacznik usunąć. W tym przypadku możnaby jeszcze parametrem -A formaila dodać do odpowiedzi nagłówek "Reply-To:", zawierający "ludzki" adres, pod którym można skontaktować się z firmą.
Mimo obszerności niniejszego tekstu stanowi on zaledwie pobieżny
przegląd możliwości procmaila i przetwarzania poczty przy jego
pomocy. Dokładnych informacji jak zwykle należy szukać w dokumentacji
programu, osiągalnej w Unixie przy pomocy komend:
Jarosław Rafa 1999.
Tekst udostępniony na licencji Creative Commons (uznanie autorstwa -
użycie niekomercyjne - bez utworów zależnych). Kliknij tutaj, aby dowiedzieć się, co to oznacza i co
możesz z tym tekstem zrobić. W razie jakichkolwiek wątpliwości
licencyjnych bądź w celu uzyskania zgody na rozpowszechnianie wykraczające
poza warunki licencji proszę o kontakt e-mailem: raj@ap.krakow.pl.
Wersja HTML opracowana 16.03.99, uzupełnienia 17.04.2001.
Powrót do wykazu artykułów o Internecie
|
Statystyka
|