Thu Jun 18 09:18:16 EDT 2015 Slept OK. Supposed to be another 80 degree day. Had a manager meeting this morning. Got in a good walk at lunch despite the heat. Goals: Work: - Get spam report into testing Done. - Work on cabling book Yes. Home: - Work on Traveller character generator A little. - Go see Mad Max: Fury Road Done. Worthwhile. Questions: - How do I prevent Outlooks from screwing with the line breaks in a plain text email? http://stackoverflow.com/questions/136052/how-do-i-format-a-string-in-an-email-so-outlook-will-print-the-line-breaks Adding three spaces at the end of lines seems to work. - I set Firefox to use the Dejavu fonts, but Unicode emoji don't render. How do I fix that? sudo apt-get install ttf-ancient-fonts The spam reporting script: #!/usr/bin/env perl # Read a mail log, and generate reports for users showing blocked mail. # It should be run from the 'prerotate' section of logrotate, like: # # prerotate # /bin/cat /var/log/mail.log | /usr/local/bin/reportblockedmail # endscript # # Paul Gorman, 17 July 2015 use strict; my $test = 1; # Zero turns testing mode off, and send reports to everyone. my $test_recipient = 'paulgorman@example.com'; my $re_date = '^[A-Z][a-z][a-z]\s+\d{1,2}\s+\d{2}:\d{2}'; my $re_blocked = '(NOQUEUE:|Blocked SPAM)'; my $re_from_to = '(from=<(.+@.+)> to=<(.+\@example\.com)> proto|<(.+@.+)> -> <(.+\@example\.com)>, quarantine)'; my $re_unknown_recipient = '.+User unknown in relay recipient table.+'; my %messages; my $count = 0; # Truncate for neatness of reporting. sub shorten(@) { return substr($_[0], 0, 40); } # Truncate from right to left. sub shorten_rl(@) { return substr($_[0], -60); } # Add commas to number. sub comma { my $text = reverse $_[0]; $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g; return scalar reverse $text } # Parse each line. Populate blocked messages into %messages, with the # to/recipient as the key, and the hash value holding an array of messages, # like: %messages = { 'paulgorman@example.com' => ['msg1', 'msg2', 'etc'] } my $first_line = 1; my $start_date; while (<>) { next if ($_ =~ $re_unknown_recipient); if ($_ =~ m/^($re_date).+ $re_blocked .+ $re_from_to/) { $count++; my $date = $1; if ($first_line eq 1) { $start_date = $date; $first_line = 0; } my $to = lc $5; next if ($to eq ''); my $from = $4 ? $4 : $6; my $msg = "$date " . shorten_rl($from); if (exists $messages{$to}) { push(@{$messages{$to}}, $msg); } else { $messages{$to} = [$msg]; } } } $count = comma($count); # Generate reports: foreach my $recipient (keys %messages) { my $rcnt = comma(scalar @{$messages{$recipient}}); my $report = "We have blocked $rcnt email messages to you as spam " . "since $start_date.\n\n$count messages were blocked for " . "everyone in the company during the same period.\n\nIf you believe " . "any of these messages should have been delivered as legitimate " . "email, please contact the IT department.\n\nThank you.\n\r\n"; if ($test eq 1) { if ($recipient eq $test_recipient) { foreach(@{$messages{$recipient}}) { $report .= "$_ \r\n"; } open(MAIL, "|/usr/sbin/sendmail -t"); print MAIL "To: $test_recipient\n"; print MAIL "From: it\@example.com\n"; print MAIL "Subject: Blocked Spam Report\n\n"; print MAIL $report; close(MAIL); } else { print "$rcnt" . "\t $recipient\n"; } } else { # Not testing; sent real reports to users. foreach(@{$messages{$recipient}}) { $report .= "$_ \r\n"; } open(MAIL, "|/usr/sbin/sendmail -t"); print MAIL "To: $recipient\n"; print MAIL "From: it\@example.com\n"; print MAIL "Subject: Blocked Spam Report\n\n"; print MAIL $report; close(MAIL); } }