--- a/mail2db Sun Jul 20 21:37:00 2008 +0000
+++ b/mail2db Mon Jul 21 07:34:30 2008 +0000
@@ -36,10 +36,10 @@
sub decode_headers($$);
MAIN: {
- openlog("mail2db", LOG_PID | (-t STDERR ? LOG_PERROR: 0), LOG_MAIL);
+ openlog( "mail2db", LOG_PID | ( -t STDERR ? LOG_PERROR: 0 ), LOG_MAIL );
- if (-f ($_ = "/etc/mail2db.conf")) {
- open(X, $_) or die "Can't open $_: $!\n";
+ if ( -f ( $_ = "/etc/mail2db.conf" ) ) {
+ open( X, $_ ) or die "Can't open $_: $!\n";
unshift @ARGV, map { chomp; $_ } <X>;
}
GetOptions(
@@ -51,16 +51,16 @@
"n|dry" => \$opt_dry,
) or pod2usage();
- pod2usage(-verbose => 1, -exitval => 0) if $opt_help;
- pod2usage(-verbose => 2, -exitval => 0) if $opt_man;
+ pod2usage( -verbose => 1, -exitval => 0 ) if $opt_help;
+ pod2usage( -verbose => 2, -exitval => 0 ) if $opt_man;
$DBH =
- DBI->connect($opt_dsn, $opt_dbuser, $opt_dbpass,
- { RaiseError => 1, FetchHashKeyName => "NAME_lc", AutoCommit => 0 })
+ DBI->connect( $opt_dsn, $opt_dbuser, $opt_dbpass,
+ { RaiseError => 1, FetchHashKeyName => "NAME_lc", AutoCommit => 0 } )
or die;
- my ($tmpfile, $message) = get_message();
- decode_headers($message, $OUTPUT_CHARSET);
+ my ( $tmpfile, $message ) = get_message();
+ decode_headers( $message, $OUTPUT_CHARSET );
# $message->print;
@@ -92,32 +92,35 @@
# first insert the message and get the database message id
my $msg_id;
{
- seek($tmpfile, 0, 0);
+ seek( $tmpfile, 0, 0 );
local $/ = undef;
$insert_message->execute(<$tmpfile>);
- $msg_id = $DBH->last_insert_id(undef, undef, message => "id");
- syslog(LOG_DEBUG, "message id: $msg_id");
+ $msg_id = $DBH->last_insert_id( undef, undef, message => "id" );
+ syslog( LOG_DEBUG, "message id: $msg_id" );
}
# now insert the message headers
- foreach my $tag (map { lc } $message->head->tags) {
- for (my $idx = 0 ;
- my $header = $message->head->get($tag, $idx) ; ++$idx)
+ foreach my $tag ( map { lc } $message->head->tags ) {
+ for (
+ my $idx = 0 ;
+ my $header = $message->head->get( $tag, $idx ) ;
+ ++$idx
+ )
{
$header =~ s/\s*$//;
- syslog(LOG_DEBUG, "$tag\[$idx]\n");
+ syslog( LOG_DEBUG, "$tag\[$idx]\n" );
# first we'll give it a try, but it may fail, because the
# header_field.id is missing
eval {
local $insert_message_header->{PrintError} = 0;
- $insert_message_header->execute($msg_id, $tag, $idx, $header);
+ $insert_message_header->execute( $msg_id, $tag, $idx, $header );
};
# if there was a problem, we'll try to insert the header_field
if ($@) {
$insert_header_id->execute($tag);
- $insert_message_header->execute($msg_id, $tag, $idx, $header);
+ $insert_message_header->execute( $msg_id, $tag, $idx, $header );
}
}
}
@@ -131,45 +134,46 @@
# we'll create a tmp file containing the complete message
# if speed matters we should use a ram disk.
# unfortunely the MIME::Parser may temporary files too
- my $tmpfile = new File::Temp(TEMPLATE => "mail2db-XXXXXX");
+ my $tmpfile = new File::Temp( TEMPLATE => "mail2db-XXXXXX" );
local $_ = <>;
- if (!/^From\s/) {
+ if ( !/^From\s/ ) {
my $nl = /\r?\n$/;
print {$tmpfile} "From - @{[scalar localtime]}$nl", $_;
}
$/ = undef;
print {$tmpfile} $_, <>;
$tmpfile->autoflush(1);
- seek($tmpfile, 0, 0);
+ seek( $tmpfile, 0, 0 );
my $parser = new MIME::Parser or die "internal error";
$parser->output_to_core(1);
my $msg = $parser->parse($tmpfile);
- return ($tmpfile, $msg);
+ return ( $tmpfile, $msg );
}
{
my %converter;
sub decode_headers($$) {
- my ($msg, $charset) = @_;
+ my ( $msg, $charset ) = @_;
$msg->head->unfold;
my %converter;
- foreach my $tag (map { lc } $msg->head->tags) {
- for (my $i = 0 ; my $h = $msg->head->get($tag, $i) ; ++$i) {
+ foreach my $tag ( map { lc } $msg->head->tags ) {
+ for ( my $i = 0 ; my $h = $msg->head->get( $tag, $i ) ; ++$i ) {
my $line = "";
- foreach my $w (decode_mimewords $h) {
- if (!defined $w->[1]) {
+ foreach my $w ( decode_mimewords $h) {
+ if ( !defined $w->[1] ) {
$line .= $w->[0];
next;
}
- $converter{ $w->[1] } ||= new Text::Iconv($w->[1], $charset)
+ $converter{ $w->[1] } ||=
+ new Text::Iconv( $w->[1], $charset )
or die "Can't create converter $w->[1] => $charset\n";
- $line .= $converter{ $w->[1] }->convert($w->[0]);
+ $line .= $converter{ $w->[1] }->convert( $w->[0] );
}
- $msg->head->replace($tag, $line, $i);
+ $msg->head->replace( $tag, $line, $i );
}
}
}
@@ -187,22 +191,22 @@
$msg->head->unfold;
# go through all header fields
- foreach my $tag (map { lc } $msg->head->tags) {
+ foreach my $tag ( map { lc } $msg->head->tags ) {
# but we may have more than one...
- foreach my $t ($msg->head->get_all($tag)) {
+ foreach my $t ( $msg->head->get_all($tag) ) {
push @{ $header{$tag} }, "";
my $current = \$header{$tag}[-1];
- foreach my $w (decode_mimewords $t) {
- if (!defined $w->[1]) {
+ foreach my $w ( decode_mimewords $t) {
+ if ( !defined $w->[1] ) {
$$current .= $w->[0];
next;
}
$converter{ $w->[1] } ||=
- new Text::Iconv($w->[1], $OUTPUT_CHARSET)
+ new Text::Iconv( $w->[1], $OUTPUT_CHARSET )
or die
"Can't create converter $w->[1] => $OUTPUT_CHARSET\n";
- $$current .= $converter{ $w->[1] }->convert($w->[0]);
+ $$current .= $converter{ $w->[1] }->convert( $w->[0] );
}
$$current =~ s/\s+$//;
}
@@ -257,9 +261,12 @@
=head1 DATABASE LAYOUT
+Beside having transactions and real support for foreign keys, the
+database has the following layout:
+
header_field
-------------------
- id: int, unique
+ id: int, unique, autoincrement
name: char(255)
message_header
@@ -271,7 +278,7 @@
message
------------------
- id: int, autoincrement
+ id: int, unique, autoincrement
timestamp: timestamp -- date of insertion
content: text -- complete message (incl. all headers)
@@ -282,6 +289,8 @@
idx: int
content: text
+All foreign key constraints use "ON DELETE CASCADE" to remove unwanted
+stuff automagically.
If you want to see the message headers in a nice form, you may use the view above or just
use the following statement: