Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1461198
  • 博文数量: 408
  • 博客积分: 10036
  • 博客等级: 上将
  • 技术积分: 4440
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-06 13:57
文章分类

全部博文(408)

文章存档

2011年(1)

2010年(2)

2009年(1)

2008年(3)

2007年(7)

2006年(394)

我的朋友

分类:

2006-04-12 15:12:30

Sieve - A Mail Filtering Language

von


1. Einführung

Sieve ist ein Sprache, die es erlaubt E-Mail Filter zu schreiben. Es gibt keine Bindung an ein spezielles Betriebssystem oder E-Mail Architektur. Die einzige Bedingung ist die Benutzung von RFC822 konformen E-Mail Systemen.

In dem wird die Sprache Sieve definiert, dessen einzige Aufgabe darin besteht einen Mailfilter zu schreiben. Die Sprache ist nicht "Turing-Complete", d.h. es gibt weder Schleifen, noch Funktionen, noch Variablen und keine Möglichkeit externe Programme aufzurufen. Diese Eigenschaft macht Sieve in der Zeit der E-Mail Viren zu einer relativ sicheren Filtersprache, die sich gut zum serverseitigen Einsatz verwenden lässt.

Man kann Sieve am einfachsten als eine "test-and-action" Skriptsprache bezeichnen, denn sie macht auch nichts anderes. Für jede E-Mail wird das Skript einmal aufgerufen und nach dem Abarbeiten aller definierten Tests gibt es eine oder mehrere Aktionen, die mit der E-Mail verbunden sind. Bei den Aktionen beschränkt man sich wieder auf die wesentlichen.

keep behalten
discard ignorieren/löschen
redirect weiterleiten
reject ablehnen
fileinto in einer Mailbox ablegen
vacation eine Abwesenheit anzeigen (nicht in RFC3028 definiert)

Weitere Aktionen können in anderen RFC's definiert werden. Als Beispiele kann man hier die Bearbeitung von IMAP Flags oder die Benutzung von regulären Ausdrücken nennen. Die Aktion "vacation" ist eigentlich als eine Erweiterung definiert, dennoch ist sie in fast allen Implementierungen standardmäßig vorhanden. Weiterhin sei noch zu erwähnen, das "reject" und "fileinto" auch Erweiterungen sind, welche aber im RFC3028 schon definiert sind.


2. Repräsentation von Daten

In Sieve gibt es nur drei unterschiedliche Datentypen. Diese sind Nummern, Zeichenketten und Listen von Zeichenketten. Die Nummern hierbei sind einfache positive ganze Zahlen, die aber einen angehängten Multiplikator in Form eines Buchstaben besitzen dürfen. In der aktuellen Spezifikation sind die drei Multiplikatoren "K", "M" und "G" definiert. Hierbei steht "K" für "kibi-" oder 1.024 (2^10), "M" für "mebi-" oder 1.048.576 (2^20) und "G" für "tebi-" oder 1.073.741.824 (2^30).

25
100K
12M    # Als Größenangabe würde es 12 Megabyte entsprechen

Eine Zeichenkette ist eine Folge von Buchstaben, die zwischen zwei Anführungszeichen (") eingeschlossen ist. Um das Zeichen " darzustellen muss es mit einem Backslash (\) maskiert werden. Der Backslash selber wird dann wiederrum mit einem zweiten Backslash maskiert.

"marcel@holtmann.org"     # Als Beispiel für eine E-Mail Adresse
"Dies ist ein \"Test\""   # Das Wort "Test"
"Ein Backslash (\\)"      # Der Backslash an sich

Der dritte Datentyp ist die Liste von Zeichenketten. Hierbei wird einfach eine Menge von Zeichenketten durch Kommata getrennt zwischen zwei eckigen Klammern gestellt. Wenn man nur eine Zeichenkette in der Liste hat, kann man die eckigen Klammern auch weglassen. Somit ist eine Liste mit einem Element genau das gleiche wie eine Zeichenkette. Mit Hilfe der Listen können sehr komplexe Vergleiche einfach dargestellt werden. In den meisten Vergleichen kann man die Listen als "oder" Verknüpfungen ansehen.

["marcel@holtmann.org", "info@holtman.org"]   # Liste von E-Mail Adressen
["XXX", "Porn", "Sex", "Adult" ]              # Liste von Subject's
"webmaster@holtmann.org"                      # Ist auch eine Liste


3. Die Aktionen im Detail

Die Aktionen "keep" und "discard" sind die elementaren Aktionen. Mit "keep" wird die E-Mail in der Mailbox behalten, wie es auch ohne Filterskript ist. Mit der Aktion "discard" erfolgt eine sofortige Löschung der E-Mail ohne das sie vorher in der Mailbox abelegt wird. Die Auslieferung endet dann im "Mail Delivery Agent" (MDA) ohne das der Absender eine Benachrichtigung darüber bekommt.

Syntax:   keep

Syntax:   discard

Mit der "redirect" Aktion kann man eine E-Mail an eine andere Mailadresse weiterleiten. Hierbei wird kein Text der Nachricht verändert. Es kann aber passieren, das der "Mail Transfer Agent" (MTA) der Weiterleitungsadresse zusätzliche Header der Mail hinzufügt.

Syntax:   redirect 

Mit einem einzelnen "redirect" kann man jede ankommende Mail weiterleiten. Will man die E-Mails aber zusätzlich auch noch lokal ablegen, so muss man explizit ein "keep" mit angeben. Soll eine E-Mail an mehrere Adressen weitergeleitet werden, muss jede Adresse mit einer eigenen "redirect" Anweisung angegeben werden. Hierbei muss man natürlich aufpassen, das man keine Mailschleifen erzeugt.

redirect "marcel@holtmann.org";
keep;

Mit Hilfe von "reject" kann man eine E-Mail zurückweisen und dem Absender mitteilen, warum man diese nicht angenommen hat. Hierbei wird dann eine "Message Disposition Notification" (MDN) zurückgesendet, welche den Grund der Ablehnung beinhalten sollte. Diesen Grund gibt man einfach als Parameter beim Aufruf mit an.

Syntax:   reject 

Man kann die Aktion "reject" als eine Erweiterung von "discard" sehen. Während bei "discard" keine Anforderungen an den "Mail Delivery Agent" (MDA) gestellt wurden, muss bei "reject" dieser aber "Message Disposition Notification" (MDN) unterstützen. Darum wurde die Aktion "reject" auch als optionales Feature deklariert und muss mit "require" angemeldet werden (siehe nächsten Abschnitt).

require "reject";

reject "I am not taking mail from you!";

Man sollte bei "reject" darauf achten, das man nicht falsche Leute mit solchen Antworten verärgert. Meistens ist ein "discard" die bessere Lösung. Weiterhin sollte man darauf achten den Grund in englische Sprache anzugeben, oder wenigsten eine englische Übersetzung mit anfügen.

Wenn man einen IMAP Server benutzt, der mehrere Unterordner in der Mailbox unterstützt, ist es sinnvoll die E-Mails in verschiedene Ordner zu vorsortieren. So kann man zum Beispiel die Nachrichten einer Mailingliste in einem Ordner zusammenfassen und die Liste somit besser verfolgen. Bei Sieve gibt es hierfür die Aktion "fileinto".

Syntax:   fileinto 

Als Parameter wird der Ordner angeben, in dem die E-Mail abgelegt werden soll. Hierbei ist zu beachten, das man sich an die Namenskonvention des IMAP Server halten muss, da ansonsten nur Fehler bei der Ausführung des Skriptes entstehen.

require "fileinto";

fileinto "INBOX.Spam;

Auch die Aktion "fileinto" ist als Erweiterung definiert, weil man nicht davon ausgehen kann, das Sieve immer auf einem IMAP Server eingesetzt wird. Dennoch macht diese Aktion die Sprache erst so richtig mächtig. Wer einmal mit auf dem Server vorsortierten Nachrichten gearbeitet hat, möchte dieses nicht mehr missen!


4. Verschiedene Arten von Kommandos

Es gibt drei verschiedenen Datentypen und es gibt auch drei verschiedene Arten von Kommandos. Als erstes sind hier die schon erwähnten Aktionen zu nennen und dann gibt es noch Tests und Kontrollkommandos. Bei den Kontrollkommandos handelt es sich im wesentlichen um drei Stück.

Das Kommando "require" darf nur am Anfang eines Skriptes stehen. Hiermit wird dem Interpreter mitgeteilt welche zusätzlichen Funktionalitäten man benutzen möchte.

Syntax:   require 

Als einzigen Paramter hat das "require" Kommando eine Liste von sogenannten "capabilities". Es können auch mehrere "require" Anweisungen hintereinander benutzt werden. Somit können die Parameter als Liste angegeben werden, oder man benutzt für jeden Parameter eine eigene "require" Anweisung.

require ["fileinto", "reject"];
require "vacation";

Mit dem Kommando "stop" wird jeder Abarbeitung des Skriptes beendet. Wurde keine Aktion ausgeührt wird die Aktion "keep" als letztes Kommando angenommen. Die gleiche Funktionalität gilt für das Ende eines Skriptes. Somit ist die "keep" Aktionen die Voreinstellung, bis sie durch eine andere Aktion abgelöst wird.

Das dritte wichtige Kommando ist die aus allen Programmiersprachen bekannte "if-elsif-else" Bedingung. Hiermit können Aktionen in Abhängigkeit von dem Ausgang eines Tests ausgeführt werden. Diese Kontrollstruktur ist die einzige, die aus den Programmiersprachen mit übernommen wurde, denn Schleifen oder ähnliches gibt es nicht.

Syntax:   if  

Syntax:   elsif  

Syntax:   else 

Auf die Definition von "test" geht der nächste Abschnitt genauer ein. Die "block" Struktur ist eine einfache Ansammlung von Aktionen, weiteren "if-elsif-else" Strukturen und/oder dem Kommando "stop". Die einzelnen Einträge müssen mit einem Semikolon beendet werden. Die ganze Gruppe wird in geschweifte Klammern gestellt.

if size :over 1M {
  discard;
  stop;
}
else {
  keep;
  stop;
}

Hierbei ist zu beachten, das "if", "elsif" und "else" bei der Definition der Sprache getrennte Kommandos sind. Dennoch darf ein "elsif" bzw. "else" nur auf eine "if" oder "elsif" Anweisung folgen.


5. Tests und deren Aufbau

Die Tests sind die elementaren Entscheidungen und das Wichtigste.


6. Die Benutzung von "vacation"

Mit der "vacation" Erweiterung wird ein Autoresponder implementiert, der eine Benachrichtigung an den Absender eine E-Mail zurück senden kann, um zum Beispiel eine Abwesenheit mitzuteilen. Diese Erweiterung ist analog zu dem unter Unix verfügbaren Programm vacation und fordert in der einfachen Form nur die Angabe eines Textes, der ähnlich wie bei "reject" dem Absender der E-Mail zurück gesandt wird.

Syntax:   vacation [":days" number] [":addresses" string-list]
          [":subject" string] [":mime"] 

Mit dem ":days" Parameter wird angegeben, in welchem Zeitraum der Absender eine Benarichtigung erhält. Auf jede weitere Meldung in diesem Zeitraum folgt dann keine automatische Antwort. Erst nach verstreichen dieser Zeit kann es zu einer zweiten Nachricht kommen. Der Standardwert entspricht hier sieben Tagen, also einer Woche. Das Minimum ist 1 Tag und das Maximum sollte nicht 30 Tage überschreiten.

Mit dem ":addresses" Parameter kann der Benutzer verschiedene E-Mail Adressen angegeben auf die kontrolliert werden soll. Das "vacation" Kommando wird dann nur ausgeführt wenn sich eine dieser E-Mail Adressen in den Headerzeilen "To:", "Cc:" oder "Bcc:" befindet. Wenn ein Benutzer zum Beispiel zwei E-Mail Adressen hat, die er zu einer Mailbox weiterleiten lässt auch hierauf Rücksicht nehmen.

require "vacation";

vacation :days 7 :addresses "marcel@holtmann.org"
  "Ich bin außer Haus und werde Ihre E-mail erst in einer Woche lesen.
   Wenden Sie sich in dringenden Fällen bitte an ...";

Normalerweise enthält die zurückgesendete E-Mail das gleiche Subject wie die ursprüngliche E-Mail, nur das sie um den Präfix "Re:" ergänzt wurde, falls dieser noch nicht vorhanden war. Mit dem Parameter ":subject" kann nun dieses Verhalten gesteuert werden und ein beliebiges Subject angegeben werden.

Mit dem vierten Parameter kann man angeben, ob die zurückzusendende Nachricht reiner Text ist, oder ob sie ein MIME Teil einer Nachricht mit den dazugehörenden Headerzeilen ist.

require "vacation";

vacation :subject "Ich bin im Urlaub :-)" :mime
  "MIME-Version: 1.0
   Content-type: text/plain; charset=us-ascii

   Eine Nachricht mit Header ...";


7. Ein ausführliches Beispiel

# Example Sieve Filter
# Declare any optional features or extension used by the script
require ["fileinto", "reject"];

# Reject any large messages
if size :over 1M {
  reject "Please do not send me large attachments.";
  stop;
}

# Handle messages from known mailing lists 
# Move messages from IETF filter discussion list to filter folder
if header :is "Sender" "owner-ietf-mta-filters@imc.org" {
  fileinto "filter";
  # move to "filter" folder
}


8. Erweiterungen von Sieve









9. Links

(auf Englisch)
(von der IETF Seite)



(auf Englisch)


阅读(1252) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~