Doručenky: sieve přesměrování + skript v perlu (přes aliasy) místo milteru.
authorFrantišek Kučera <franta-hg@frantovo.cz>
Wed, 30 Nov 2011 15:44:34 +0100
changeset 21a5c8edf14f82
parent 20 2a00ee0b740a
child 22 0eca162a758c
Doručenky: sieve přesměrování + skript v perlu (přes aliasy) místo milteru.
doručenky/aliases
doručenky/dorucenky.pl
doručenky/doručenky.sieve
doručenky/global.sieve
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/doručenky/aliases	Wed Nov 30 15:44:34 2011 +0100
     1.3 @@ -0,0 +1,3 @@
     1.4 +# /etc/aliases
     1.5 +
     1.6 +dorucenky: |/usr/local/bin/dorucenky.pl
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/doručenky/dorucenky.pl	Wed Nov 30 15:44:34 2011 +0100
     2.3 @@ -0,0 +1,93 @@
     2.4 +#!/usr/bin/env perl
     2.5 +
     2.6 +use strict;
     2.7 +use MIME::Parser;
     2.8 +use Net::SMTP;
     2.9 +
    2.10 +# K doručenkám typu:
    2.11 +#	Content-Type: multipart/report; report-type=delivery-status; ~ Delivery Status Notification (DSN)
    2.12 +# doplňujeme hlavičku References, 
    2.13 +# aby si je e-mailový klient mohl zařadit do vlákna pod zprávu, ke které doručenka patří.
    2.14 +
    2.15 +# viz http://search.cpan.org/~dskoll/MIME-tools-5.502/lib/MIME/Entity.pm
    2.16 +# viz http://search.cpan.org/~dskoll/MIME-tools-5.502/lib/MIME/Head.pm
    2.17 +# viz http://search.cpan.org/~gbarr/libnet-1.21/Net/SMTP.pm
    2.18 +
    2.19 +
    2.20 +# Nastavení --------------------------------------------------------------------
    2.21 +my $komu = 'noreply@example.com'; # adresa správce – sem pošleme zprávy, pokud nevíme, kam je poslat (chybí Delivered-To), nebo máme podezření na zacyklení
    2.22 +# ------------------------------------------------------------------------------
    2.23 +
    2.24 +my $znacka = "X-DSN-Pridej-References"; # hlavička, kterou si poznačíme, že zpráva prošla tímto programem
    2.25 +my $stav = "chyba - nedefinovano"; # výchozí hodnota naší hlavičky
    2.26 +
    2.27 +
    2.28 +# Načteme zprávu
    2.29 +my $parser = new MIME::Parser;
    2.30 +$parser->output_to_core(1);
    2.31 +my $dorucenka = $parser->parse(\*STDIN);
    2.32 +
    2.33 +
    2.34 +# Kontrola, že se zpráva nezacyklila (chybí naše značka)
    2.35 +if ($dorucenka->head->count($znacka) == 0) {
    2.36 +	
    2.37 +	# Podle hlavičky Delivered-To zjistíme, kam máme zprávu poslat zpátky	
    2.38 +	my $deliveredTo = $dorucenka->head->get("Delivered-To", 1); # [0] = adresa tohoto skriptu, [1] = předchozí adresa – původní příjemce doručenky 
    2.39 +	if ($deliveredTo) {
    2.40 +		$deliveredTo =~ s/\s+$//; # zbavíme se přebytečného konce řádku
    2.41 +		$komu = $deliveredTo;
    2.42 +		$dorucenka->head->delete("Delivered-To", 1); # aby si poštovní server nemyslel, že se zpráva zacyklila 
    2.43 +		
    2.44 +		# Pokud hlavička References chybí, doplníme ji
    2.45 +		if ($dorucenka->head->count("References") == 0) {
    2.46 +			
    2.47 +			# Zjistíme Message-ID původní zprávy
    2.48 +			my $messageID;
    2.49 +			my @casti = $dorucenka->parts;
    2.50 +			for my $cast (@casti) {
    2.51 +				if ($cast->mime_type eq "text/rfc822-headers") {
    2.52 +					my @radky = $cast->bodyhandle->as_lines;
    2.53 +					for my $radek (@radky) {
    2.54 +						if ($radek =~ /^Message-ID:\s*(<.*>)$/) {
    2.55 +							$messageID = $1;
    2.56 +						}
    2.57 +					}
    2.58 +				}			
    2.59 +			}		
    2.60 +			
    2.61 +			# Nastavíme nalezené Message-ID do References hlavičky
    2.62 +			if ($messageID) {
    2.63 +				$stav = "ok";
    2.64 +				$dorucenka->head->add("References", $messageID);
    2.65 +			} else {
    2.66 +				$stav = "chyba - Message-ID nenalezeno";
    2.67 +			}
    2.68 +			
    2.69 +		} else {
    2.70 +			$stav = "hlavicka References uz byla nastavena drive";
    2.71 +		}		
    2.72 +	} else {
    2.73 +		$stav = "chyba - nevime, kam zpravu poslat zpet";
    2.74 +	}	
    2.75 +} else {
    2.76 +	# Zpráva se zacyklila → pouze přidáme svoji značku
    2.77 +	# a pošleme správci (nezměníme $komu)
    2.78 +	$stav = "chyba - cyklus";
    2.79 +}
    2.80 +
    2.81 +
    2.82 +$stav .= " [pid=$$,uid=$>]"; # přidáme PID a UID
    2.83 +$dorucenka->head->add($znacka, $stav);
    2.84 +
    2.85 +# Výpis (nepotřebujeme, jen pro ladění)
    2.86 +#$dorucenka->print(\*STDOUT);
    2.87 +#print "Pošleme komu: $komu\n";
    2.88 +
    2.89 +# Odeslání přes SMTP (pro ostrý provoz):
    2.90 +my $smtp = Net::SMTP->new("localhost");
    2.91 +$smtp->mail('<>');
    2.92 +$smtp->to($komu);
    2.93 +$smtp->data();
    2.94 +$dorucenka->print($smtp);
    2.95 +$smtp->dataend();
    2.96 +$smtp->quit;
     3.1 --- a/doručenky/doručenky.sieve	Wed Nov 30 15:40:16 2011 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,7 +0,0 @@
     3.4 -require ["fileinto"];
     3.5 -# rule:[doručenky]
     3.6 -if anyof (header :contains "Content-Type" "report-type=disposition-notification;", header :contains "Content-Type" "report-type=delivery-status;")
     3.7 -{
     3.8 -        fileinto "Sent";
     3.9 -        stop;
    3.10 -}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/doručenky/global.sieve	Wed Nov 30 15:44:34 2011 +0100
     4.3 @@ -0,0 +1,21 @@
     4.4 +# Kompilace:
     4.5 +# sievec global.sieve
     4.6 +
     4.7 +require ["fileinto"];
     4.8 +
     4.9 +# rule:[doručenky]
    4.10 +if allof (
    4.11 +		not exists "X-DSN-Pridej-References",
    4.12 +		header :contains "Content-Type" "report-type=delivery-status;"
    4.13 +	)
    4.14 +{
    4.15 +	redirect "dorucenky@example.com";
    4.16 +	stop;
    4.17 +}
    4.18 +elsif anyof (
    4.19 +		header :contains "Content-Type" "report-type=disposition-notification;",
    4.20 +		header :contains "Content-Type" "report-type=delivery-status;"
    4.21 +	)
    4.22 +{
    4.23 +	fileinto "Sent";
    4.24 +}