#!/usr/bin/perl

# rewritefishurl - Replace URLs in spam-mail by a redirect to visnet.uvt.nl
# Casper Gielen, 2015, GPLv2+
#
#
# usage: rewritefishurl -f sender recipients < email

use Email::Date::Format qw(email_date);
use Sys::Hostname;
use URI::Encode;
use IPC::Open3;
use IO::Select;
use Symbol qw(gensym);

use strict;
use warnings;

# Exit codes from <sysexits.h>
my $EX_TEMPFAIL=75;
my $EX_UNAVAILABLE=69;
my $ret = $EX_TEMPFAIL;

# Config

# Sendmail command. NEVER NEVER NEVER use "-t" here.
our @sendmail = qw(/usr/sbin/sendmail -G -i);
# only activate if SpamAssassin assigned at least this score 
our $maxscore = 20;
# URL to redirect spam-URLs to
our $redirecturl = "https://visnet.uvt.nl/?orig_uri=";

require ($ENV{rewritefishurl_config} // '/etc/rewritefishurl.cfg');

push(@sendmail, @ARGV);

my $uri = URI::Encode->new( { encode_reserved => 0 } );

my $pid;
my $selector;

eval {
	my ($sendmail_in, $sendmail_out, $sendmail_err);
	$sendmail_err = gensym();
	$pid = open3($sendmail_in, $sendmail_out, $sendmail_err, @sendmail)
		or die "cannot open sendmail: $!";

	$selector = IO::Select->new();
	$selector->add($sendmail_err, $sendmail_out);


	my $header = 1;
	my $spamscore = -9999;
	my $received_printed = 0;
	while (my $line = <STDIN>) {
		if ($header && $line =~ m/^$/) {
			$header = 0;
		} elsif ($header && $line =~ m/^X-Spam-Score: (.+)/) {
			$spamscore = $1 if $1 > $spamscore;
		} elsif (!$received_printed && $line =~ m/Received:/) {
			print $sendmail_in "Received: from localhost by " . hostname() . " (rewritefishurl);" . email_date() . "\n"
				or die $!;
			$received_printed = 1;
		} elsif ($spamscore > $maxscore && $line =~ m#(.*?)((?:https?://|www\.)+[^\s>"']*)(.*)#ais) {
#			print "    1: $1\n    2: $2\n    3: $3\n";
			$line = $1.$redirecturl.$uri->encode($2).$3;
		}
#		print $line;
		print $sendmail_in $line
			or die $!;
	}

	close($sendmail_in);
	$ret = $?;

	while (my @ready = $selector->can_read) {
		foreach my $fh (@ready) {
			print "fh undef!\n" unless defined $fh;
			print "sendmail_err undef!\n" unless defined $sendmail_err;
			if (fileno($fh) == fileno($sendmail_err)) {print STDERR <$sendmail_err>}
			else                                      {print STDOUT <$sendmail_out>}
			$selector->remove($fh) if eof($fh);
		}
	}
	close($sendmail_out);
	close($sendmail_err);

	$SIG{CHLD} = sub {
		print "rewritefishurl reaper: status $? on $pid\n" if waitpid($pid, 0) > 0;
		exit $EX_TEMPFAIL;
	};

	exit $ret;
};

if($@) {
	warn $@;
	exit $EX_TEMPFAIL;
}


exit( $? >> 8 );

__END__
=head1 NAME

rewritefishurl - Replace URLs in spam-mail by a redirect to visnet.uvt.nl

=head1 SYNOPSIS

Rewritefishurl is a content filter for Postfix that rewrites every URL in the
mail to point to our anti-phishing-page if SpamAssassin classified the mail
as spam.

=head1 USAGE

This script is inteded to be called by Postfix as a content_filter.

 rewritefishurl -f sender recipients < email

=head1 CONFIGURATION

Zet de volgende regels in je Postfix master.cf:

    rewritefishurl    unix  -       n       n       -       10      pipe
        flags=Rq user=rewritefishurl null_sender=
        argv=/usr/bin/rewritefishurl -f \${sender} -- \${recipient}

Voeg dan een content_filter toe aan het juist transport. Dit content_filter
moet pas na SpamAssassin draaien, bv de queue waarnaar Amavis  mail aflevert:

    -o content_filter=myfirstfilter:dummy

=head1 AUTHOR

Casper Gielen 2015 cgielen@uvt.nl

=head1 ID

# $URL: https://svn.uvt.nl/its-id/trunk/sources/rewritefishurl/rewritefishurl $
# $Id: rewritefishurl 43827 2015-09-08 12:22:41Z cgielen $
=cut
