jBiff, my IMAP-to-XMPP thingee, comes in. I've even taken to using the web interfaces instead of Thunderbird on occasion. All is well in the world.But there's a problem.
Lists. Lists and filters. Filtering lists. ( That makes it one problem again. )
I'm used to using
slocal or procmail on Unix machines to filter as the mail comes in. I'm not nearly as happy with the interface to filtering in Gmail, but I do love the result, which is a cleaner inbox.My work mail has filtering that's enabled when you use the web interface. I don't use the web interface often, and when I have all my filters in Thunderbird, nothing is filtered when I use the web. What I needed is a means to write my filters outside of a mail client and have them run regularly, so that the state of the inbox is always as it should be.
So, I wrote
imap_filter.pl. It needs to be cleaned up a bit, and it is not feature-complete, but I'm able to move mail based on many good things, so I'm at a done point.#!/usr/bin/perl
use 5.010 ;
use strict ;
use warnings ;
use lib '/home/jacoby/bin' ;
use Carp ;
use Data::Dumper ;
use Getopt::Long ;
use IO::Socket::SSL ;
use IO::Interactive qw{interactive} ;
use Mail::IMAPClient ;
use IdentConf ':all' ;
use subs qw{ imap_part xmpp_part } ;
$Data::Dumper::Indent = 1 ;
my $debug ;
my $imap_identity ;
#methods
my @from ;
my @to ;
my @cc ;
my @subject ;
my @to_or_cc ; # don't use or yet.
my $age = 0 ;
#actions
my $move ; #move to dir
my $forward ; #forward to this address
my $delete ; #delete this file
my $read ;
my $unread ;
GetOptions(
'imap=s' => \$imap_identity,
'from=s' => \@from,
'to=s' => \@to,
'cc=s' => \@cc,
'or=s' => \@to_or_cc,
'subject=s' => \@subject,
'age=i' => \$age,
'move=s' => \$move ,
'delete' => \$delete ,
'read' => \$read ,
) or exit( 1 ) ;
exit if !defined $imap_identity ;
exit if length $imap_identity < 1 ;
for my $a ( @to_or_cc ) {
push @to, $a ;
push @cc, $a ;
}
my $filter ;
$filter->{ from } = \@from ;
$filter->{ subject } = \@subject ;
$filter->{ to } = \@to ;
$filter->{ cc } = \@cc ;
$filter->{ age } = $age ;
$filter->{ move } = $move ;
$filter->{ read } = $read ;
$filter->{ delete } = $delete ;
imap_part $filter ;
exit ;
# ====================================================================
#
# connect to and search your mail server via IMAP
#
# ====================================================================
sub imap_part {
my ( $filter ) = @_ ;
say { interactive } Dumper $filter ;
my %creds = get_credentials( 'imap', $imap_identity ) ;
my $socket = IO::Socket::SSL->new( PeerAddr => $creds{ server },
PeerPort => $creds{ port },
) or die "socket(): $@" ;
my $client = Mail::IMAPClient->new( Socket => $socket,
User => $creds{ username },
Password => $creds{ password },
) or die "new(): $@" ;
if ( $client->IsAuthenticated() ) {
$client->select( $creds{ directory } )
or die "Select '$creds{directory}' error: ",
$client->LastError, "\n" ;
my $i = 1 ;
for my $msg ( reverse $client->messages ) {
my $flag = 0 ;
my $from = $client->get_header( $msg, 'From' ) ;
my $sender = $client->get_header( $msg, 'Sender' ) ;
my $date = $client->date( $msg ) ;
my $to = $client->get_header( $msg, 'To' ) ;
my $cc = $client->get_header( $msg, 'Cc' ) ;
my $subject = $client->subject( $msg ) ;
my @flags = $client->flags( $msg ) ;
my $seen = 0 ; $seen = 1 if grep m{/Seen}mx , @flags ;
next if grep m{\Deleted}mx , @flags ;
# Subject
if ( scalar @{ $filter->{ subject } } > 0 ) {
for my $f ( $filter->{ subject } ) {
my $ff = $$f[ 0 ] ;
$subject =~ m{($ff)}mix ;
say $1 if defined $1 ;
$flag++ unless defined $1 ;
}
}
# From
if ( scalar @{ $filter->{ from } } > 0 ) {
for my $f ( $filter->{ from } ) {
my $ff = $$f[ 0 ] ;
$from =~ m{($ff)}mix ;
$flag++ unless defined $1 ;
}
}
# To
if ( scalar @{ $filter->{ to } } > 0 && ! defined $to ) {
$flag++ ;
}
if ( scalar @{ $filter->{ to } } > 0 && defined $to ) {
for my $f ( $filter->{ to } ) {
my $ff = $$f[ 0 ] ;
$to =~ m{($ff)}mix ;
$flag++ unless defined $1 ;
}
}
# Cc
if ( scalar @{ $filter->{ cc } } > 0 && ! defined $cc ) {
$flag++ ;
}
if ( scalar @{ $filter->{ cc } } > 0 && defined $cc ) {
for my $f ( $filter->{ cc } ) {
my $ff = $$f[ 0 ] ;
$cc =~ m{($ff)}mix ;
$flag++ unless defined $1 ;
}
}
# Age
#GOT NADA
next if $flag ;
if ( 1 ) {
my $title = 'New mail from ' . $from ;
my $body = $subject ;
$body = join q{"}, '', $body, '' ;
#say { interactive } "$title - $body" ;
say { interactive } $i++ . "\t" . '=' x 40 ;
say { interactive } $subject;
say { interactive } 'From: ' . $from ;
say { interactive } ' Sender: ' . $sender if $sender ;
say { interactive } ' To: ' . $to if $to ;
say { interactive } ' Cc: ' . $cc if $cc ;
say { interactive } ' Date: ' . $date ;
say { interactive } join ' ' , ' ' , @flags ;
if ( $filter->{ move } ) {
my $move = $filter->{ move } ;
say { interactive } ' Move: ' . $move ;
my $newUid = $client->move( $move , $msg )
or die "Could not move: $@\n";
}
say { interactive } '' ;
}
}
$client->logout() ;
}
else {
say { interactive } 'FAIL ' . $! ;
}
}
# --------------------------------------------------------------------
No comments:
Post a Comment