Sztuczki z pocztą, cz.2:
procmail

W poprzedniej części tego tekstu omówiony został m.in. sposób filtrowania poczty elektronicznej za pomocą programu filter, wchodzącego w skład pakietu elm. Prostota tego programu z jednej strony ułatwia opanowanie go osobom początkującym, z drugiej jednakże strony stanowi wadę, uniemożliwiającą wykorzystanie go w bardziej skomplikowanych zastosowaniach.

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.

Co potrafi procmail

Procmail jest najczęściej obecnie używanym - i zarazem najbardziej zaawansowanym - narzędziem do manipulacji przychodzącą pocztą elektroniczną. Przy jego pomocy można zrobić z pocztą właściwie wszystko: od prostego rozsortowywania listów do różnych folderów, poprzez wzajemne autoforwardy pomiędzy kilkoma kontami, przesyłanie poczty na telefony komórkowe czy pagery, automatyczne odpowiadanie na listy, obsługę pocztowego serwera plików (automatyczne wysyłanie użytkownikom określonych plików w odpowiedzi na listy zawierające specjalne komendy), aż po obsługę list dyskusyjnych! - w Internecie dostępny jest, zrealizowany w postaci skryptów dla procmaila, pakiet SmartList, realizujący zarządzanie listami dyskusyjnymi w sposób analogiczny do programów typu LISTSERV.

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.

Wywołanie programu

Na wielu serwerach procmail może być zainstalowany jako domyślny systemowy program dostarczający pocztę do skrzynek pocztowych użytkowników (local mailer); w takim przypadku jest on wywoływany automatycznie, ilekroć otrzymujemy jakiś list, i skorzystanie z jego możliwości wymaga tylko zapisania odpowiednich reguł filtrowania w pliku .procmailrc w swoim katalogu macierzystym. Jeżeli takie postępowanie nie przynosi pożądanego efektu, oznacza to, że procmail nie jest mailerem systemowym i oprócz pliku .procmailrc do jego uaktywnienia niezbędne jest jeszcze jawne wywołanie programu w pliku .forward. Dokonujemy tego podobnie jak w przypadku programu filter:

     "|/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"


Składnia reguł filtrowania

Najistotniejszą rzeczą dla działania procmaila są jednak reguły filtrowania, umieszczone w pliku .procmailrc. Za zwiększone możliwości programu płacimy większą trudnością jego użycia - składnia tych reguł nie jest już tak łatwa, jak w programie filter. Przykładowa reguła dla programu filter:

     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


Semafory

Uważni czytelnicy zapewne zauważyli, że w niektórych spośród powyżej przytoczonych przykładów reguł w pierwszym wierszu występuje dodatkowy znak dwukropka (oprócz pierwszego rozpoczynającego wiersz), w innych zaś nie. Dodatkowy dwukropek w pierwszym wierszu oznacza, że program ma stosować przy przetwarzaniu danej reguły tzw. semafor, i zasadniczo jest niezbędny zawsze wówczas, gdy w wyniku wykonania polecenia ma nastąpić zmodyfikowanie zawartości jakiegoś pliku (np. dopisanie do niego nowego listu). Może się bowiem zdarzyć, że otrzymamy równocześnie kilka listów spełniających ten sam warunek (np. w uprzednio omawianych regułach - listów z listy dyskusyjnej). Ponieważ dla każdego listu wywoływana jest oddzielna kopia procmaila, w takiej sytuacji kilka programów równocześnie próbowałoby zapisywać "swoje" listy do tego samego pliku, co prawie na pewno spowodowałoby zniekształcenie jego zawartości. Użycie semafora zapobiega takiej sytuacji; program, który pierwszy rozpocznie zapis do pliku, "opuszcza" semafor, blokując pozostałym programom dostęp do tego pliku aż do chwili, gdy zapis zostanie zakończony i semafor "podniesiony".

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


Postać warunków

Zajmijmy się teraz bliżej warunkami, które zapisywać możemy w regułach dla procmaila. Warunki te najczęściej mają postać tzw. wyrażeń regularnych - wystąpień tych wyrażeń program będzie poszukiwał w nagłówku listu (domyślnie; można nakazać poszukiwanie również w treści listu). Składnia wyrażeń regularnych jest dość skomplikowana; omówimy tu jedynie jej podstawowe elementy (na marginesie warto wspomnieć, że wyrażenia regularne obsługuje również program filter; jeżeli w warunku dla tego programu znak równości zastąpimy znakiem "~", możemy poszukiwać w nagłówkach wyrażeń regularnych).

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.

Liczenie punktów

Jak wspomniałem na wstępie, poza klasycznymi warunkami logicznymi typu "tak-nie" procmail umożliwia definiowanie "inteligentnych" reguł opartych na zliczaniu punktów. Oto przykład reguły wykorzystującej tę możliwość. Reguła ta skasuje z naszej skrzynki pocztowej wszystkie listy, w których treści więcej niż trzy razy występuje słowo "money":

     :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.

Zastosowania

Przykłady prostych zastosowań procmaila - typu rozsortowywanie poczty do odpowiednich folderów, czy eliminowanie listów spełniających określone warunki - były już przedstawiane powyżej. Jako praktyczną ilustrację tych możliwości chciałem tu przedstawić fragment własnego pliku .procmailrc, realizujący tego typu zadania. Na co dzień używam dwóch kont e-mail - jedno z nich znajduje się na serwerze sieci Novell Netware, drugie na komputerze Unixowym. Gdy jestem w pracy lub w domu, wygodniej mi korzystać z tego pierwszego konta; na to konto przychodzi do mnie większość korespondencji, w tym także z szeregu list dyskusyjnych. Z konta na serwerze sieci Novell nie da się jednak - poza ściąganiem poczty przez POP3 - korzystać zdalnie; toteż gdy potrzebuję dostępu do poczty poza miejscem pracy lub domem (np. podczas delegacji) korzystam z konta Unixowego, na które mogę zalogować się przez telnet skądkolwiek. Na to konto dostaję również bezpośrednio część korespondencji, przychodzą na nie też listy adresowane na jeszcze inny adres - alias, przeznaczony do obsługi prowadzonej przeze mnie listy providerów Internetu w Polsce (można ją znaleźć pod adresem http://www.wsp.krakow.pl/providers/providers.html lub na dołączonym do MI CD-ROMie).

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


Precz ze spamem!

W tym i poprzednim tekście kilkakrotnie już wspominałem o możliwości filtrowania poczty w celu eliminowania tzw. spamu - czyli niechcianych listów reklamowych przysyłanych na nasz adres e-mail. Zdecydowana większość takich listów reklamuje serwery pornograficzne lub oferuje nam złudną możliwość dużego zarobku poprzez udział w jakimś "łańcuszku" czy "piramidzie" pieniężnej. Eliminowanie takich listów nie jest łatwe: proste wykrywanie obecności pewnych słów kluczowych - jak np. "money" - w temacie lub treści listu bywa niewystarczające, autorzy takich listów często zadają sobie bowiem trud sformułowania ich w taki sposób, aby te charakterystyczne słowa nie występowały w nich w sposób jawny. Równocześnie istnieje niebezpieczeństwo, że eliminując wszystkie listy zawierające słowa takie jak np. "business" możemy przypadkowo skasować całkiem poważną ofertę współpracy w interesach.

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.

Usuwanie duplikatów

Jedną z ciekawszych, a zarazem stosunkowo prostych reguł dla procmaila, która może być przydatna w praktyce, jest wspomniana już uprzednio reguła służąca do eliminacji ze skrzynki pocztowej duplikatów 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.

Z e-maila na komórkę

Od chwili pojawienia się w Polsce sieci telefonii komórkowej GSM dużym zainteresowaniem cieszy się wśród użytkowników Internetu, będących równocześnie posiadaczami takich telefonów, możliwość przekazywania poczty elektronicznej na telefon GSM w postaci krótkich wiadomości tekstowych (SMS). Na początku do tego celu wykorzystywane były - nie zawsze działające - zagraniczne bramki e-mail->SMS; od momentu uruchomienia przez sieć Plus GSM własnej bramki tego typu to ona właśnie jest najczęściej wykorzystywana do przesyłania poczty na "komórkę" (przynajmniej przez abonentów Plusa).

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:

Autoresponder

Na koniec tego - choć obszernego, to i tak bardzo skrótowego - przeglądu możliwości procmaila wrócimy do tematu automatycznych odpowiedzi na listy. Tym razem jednak będą to odpowiedzi trochę innego rodzaju, niż generowane przez program vacation.

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:


* Strona już nie istnieje.


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