Use SpamAssassin Message.pm module to fetch email attachment 

Here is a little script I wrote to fetch email attachment. If user got spam and forward it as attachment to me, I could use this script to rip the attachment and feeds it to sa-learn, the bayes learning engine of SA.

#!/usr/bin/perl
use strict;
use warnings;

use Mail::SpamAssassin::Message;

my $fh;
open $fh, "<", shift or die "Could not open message file:$!";
my @message = <$fh>;

my $msg = Mail::SpamAssassin::Message->new(
{
'message' => \@message,
}
) || die "Message error?";

#my $msg = Mail::SpamAssassin::Message->new() || die "Message error?";

#foreach my $p ($msg->find_parts(qr/^(text|image|application)\b/i, 1)) {
foreach my $p ($msg->find_parts(qr/^message\b/i, 0)) {
eval {
no warnings ;
my $type = $p->{'type'};
my $attachname = $p->{'name'};
print "Content type is: $type\n";
print "write file name: $attachname\n";
open my $out, ">", "$attachname" || die "Can't write file $attachname:$!";
binmode $out;
print $out $p->decode();
};
# warn $@ if $@;
}
[ add comment ] permalink ( 3.1 / 81 )
Re-queueing quarantined spam 

I happen to know that one amavisd user misfiltered 10000 emails as spam, and want to release them. How that could be achieved. Here is the relevant discussion link:
http://marc.theaimsgroup.com/?l=amavis- ... 84&w=2

The following both solutions are that we get mail_id from the quarantined *.gz file itself, typical file like this : spam-*******.gz, the '*******' is the mail_id.

The config in amavisd.conf should be:

-------------
$policy_bank{'AM.PDP-SOCK'} = {
protocol => 'AM.PDP', # Amavis policy delegation protocol
auth_required_release => 0, # don't require secret_id for
amavisd-release
};

$interface_policy{'SOCK'} = 'AM.PDP-SOCK';
----------------------


Scenario 1:
If the mail log is in MySQL, and spam are quarantined as *.gz file, we just pipe the mail_id to amavisd-release

Use the on-liner perl:

perl -e 'opendir(my $dir, "/var/amavis/quarantine"); \
print "$_\n" for map { /spam-(.*?)\.gz/ } readdir($dir); ' |
amavisd-release -

Scenario 2:
If the mail log is not in MySQL and spam are quarantined in *.gz, amavisd-release needs the full quarantine file name, not just mail_id, so we use different one-liner perl

perl -e 'opendir(my $dir, "/var/amavis/quarantine");\
print "$_\n" for grep { /^spam/} readdir($dir); ' | amavisd-release -
[ add comment ] permalink ( 3 / 71 )
Amavisd-2.3.3 and SA's sa-update 

If system are running on Amavisd-new-2.3.3 and SA version older than 3.1.5. the rules updated by sa-update will not accessed by amavisd unless add one line code to Mail::SpamAssassin->new( LOCAL_STATE_DIR => '/var/lib',). The relevant discussion link:
http://www.mail-archive.com/amavis-user ... 05859.html

[ add comment ] permalink ( 3 / 81 )
P0f - Passive OS fingerprinting tool 

I normally use nmap to profile a remote system, but I found a lightweight sniffing tool p0f - passive os fingering tool http://lcamtuf.coredump.cx/p0f.shtml which gather all kinds of profiling information about a remote system. Here is how I run it on my email server to profile all the remote system connecting to my smtp port

p0f -d -o /var/log/p0f.log -t -U -i en1 -l '(dst host my emailserver and tcp dst port 25)'

change the network interface en1 to eth0 if you are on Linux.

It will capture some interesting information like below:

<Mon Sep 25 14:00:07 2006> 137.82.45.4:33785 - Solaris 9.1 (up: 645 hrs) -> my emailserver:25 (distance 4, link: ethernet/modem)

<Mon Sep 25 14:00:26 2006> 201.227.187.11:1296 - Windows XP SP1+, 2000 SP3 -> my emailserver:25 (distance 21, link: ethernet/modem)

<Mon Sep 25 14:00:55 2006> 65.17.242.10:3853 - FreeBSD 4.6-4.9 (up: 3512 hrs) -> my emailserver:25 (distance 14, link: ethernet/modem)

The you can make this information available to SpamAssassin through Amavisd's p0f feature and add spam score based on spammer's OS and hop distance. Following statistics quote from Amavisd-new-2.4.2 RELEASE_NOTES:

-----------------------
Some statistics collected from our logs in February 2006:
p0f OS guess ham : spam
-----------------------------
Windows-XP 0.7 % : 99.3 %
Windows-2000 5.8 % : 94.2 %
UNKNOWN 16.5 % : 83.5 %
Linux 58.8 % : 41.2 %
Unix 80.3 % : 19.7 %
(Unix+Linux 66.5 % : 33.5 %)
(ham: mail with score below 3, spam: score above 6)
-----------------------------------

[ add comment ] permalink ( 3 / 110 )
Run free webserver and email server at home  

I have beening running webserver at my home linux computer for two years http://pingpongit.homelinux.com . I am using DynDNS http://www/dyndns.com free dynamic dns services to resolve my home dynamic IP.

I need to run a dynmaic dns update client to update the record once my IP changed. I am having problem using the popular ddclient, it just won't update for some reason. It is written in Perl, I am comfortable with Perl, but just could not figure out why. I ended up with another update client called addns.pl http://www.funtaff.com/software/addns.pl/ which works for me. but one side effect is that addns.pl does not have http ssl support which is recommended to encrypt the communication. so I modified the addns.pl to support http ssl, here is the patch I added:

--- addns.orig 2006-09-24 13:52:08.699253528 -0700
+++ addns 2006-09-24 13:54:22.933846768 -0700
@@ -7,7 +7,7 @@
# Version 1.2
# www.funtaff.com

-use IO::Socket;
+use IO::Socket::SSL;
use Sys::Hostname;
use integer;
use English;
@@ -288,7 +288,7 @@

chomp( $coded = encode_base64("$uname:$passwd") );

- $msg = "GET http://$server_host/nic/update?";
+ $msg = "GET https://$server_host/nic/update?";
$msg .= "system=$system_type";
$msg .= "&hostname=$updt_host";

@@ -311,25 +311,18 @@
$msg .= "\r\n";

#tcp code
- my ( $proto, $iaddr, $sin, @return );
- my $socket_type = 'tcp';
-
- $proto = getprotobyname($socket_type);
- socket( UpdaTe, PF_INET, SOCK_STREAM, $proto ) || die "socket: $!";
- $iaddr = gethostbyname($connect_host);
- $sin = sockaddr_in( $port, $iaddr );
-
- connect( UpdaTe, $sin ) || die "connect: $!";
- output( "$curr_host: performing update, ip=$ip", 1, 1 );
-
- if ( $debug > 1 ) {
- print "\n--Client Request--\n";
- print "$msg\n";
+ my $sock = IO::Socket::SSL->new(
+ PeerAddr => $connect_host,
+ PeerPort => $port,
+ Proto => 'tcp',
+ );
+ defined $sock or output("cannot connect to $connect_host:$port socket: $@");
+ my @return;
+ if ( defined $sock ) {
+ syswrite $sock, $msg;
}
-
- send( UpdaTe, $msg, 0 );
- @return = <UpdaTe>;
- close(UpdaTe);
+ @return = <$sock>;
+ $sock->close;

if ( $debug > 1 ) {
print "--Server Response--\n";


--- addns.conf.orig 2006-09-24 14:24:18.617861304 -0700
+++ addns.conf 2006-09-24 13:48:46.059059520 -0700
@@ -13,8 +13,9 @@
iface = "eth0"
username = "user"
password = "password"
- server_port = 80
+ server_port = 443
server_host = members.dyndns.org
+ mx_host = my mx host
}

I also added my mx host so that I could relay my registed dyndns subdomain and have my email address as vincent at pingpongit.homelinux.com.
[ add comment ] permalink ( 3 / 90 )

Back Next