mail_to_db.pl
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:8k
源码类别:

模拟服务器

开发平台:

C/C++

  1. #!/usr/bin/perl
  2. # Copyright Abandoned 1998 TCX DataKonsult AB & Monty Program KB & Detron HB
  3. # This file is public domain and comes with NO WARRANTY of any kind
  4. #
  5. # This program is brought to you by Janne-Petteri Koilo with the 
  6. # administration of Michael Widenius.
  7. # This program takes your mails and puts them into your database. It ignores
  8. # messages with the same from, date and message text.
  9. # You can use mail-files that are compressed or gzipped and ends with
  10. # -.gz or -.Z.
  11. use DBI;
  12. use Getopt::Long;
  13. $VER = "1.5";
  14. $opt_db = "test";
  15. $opt_table = "mails";
  16. $opt_max_mail_size = 65536;
  17. $opt_db_engine = "mysql";
  18. $opt_host = "localhost";
  19. $opt_user = $opt_password = "";
  20. $opt_help = $opt_version = 0;
  21. GetOptions("help","version","user=s","password=s",
  22.    "db_engine=s","db=s","host=s","max_mail_size=s") || usage();
  23. usage($VER) if ($opt_help || $opt_version || !$ARGV[0]);
  24. %months= ('Jan' => 1, 'Feb' => 2, 'Mar' => 3, 'Apr' => 4, 'May' => 5,
  25.   'Jun' => 6, 'Jul' => 7, 'Aug' => 8, 'Sep' => 9, 'Oct' => 10,
  26.   'Nov' => 11, 'Des' => 12);
  27. $count_no_from = $count_no_txt = $count_too_big = 0;
  28. $count_forwarded_msgs = $count_duplicates = $no_subject = 0;
  29. $inserted_mails = 0;
  30. $dbh = DBI->connect("DBI:$opt_db_engine:$opt_db:$opt_host",$opt_user,
  31.     $opt_password,{ PrintError => 0}) || die $DBI::errstr;
  32. create_table_if_needed($dbh);
  33. foreach (@ARGV)
  34. {
  35.   if (/^(.*).(gz|Z)$/) #checks if the file is compressed or gzipped
  36.   {
  37.     open(FILE, "zcat $_ |");
  38.     process_mail_file($dbh,$1);
  39.   }
  40.   else
  41.   {
  42.     open(FILE,$_);
  43.     process_mail_file($dbh,$_);
  44.   }
  45. }
  46. $ignored = $count_no_from + $count_no_txt + $count_too_big + $count_duplicates + $no_subject;
  47. print "Mails inserted:ttt$inserted_mailsn";
  48. print "Mails ignored:ttt$ignoredn";
  49. print "Mails without "From:" -field:t$count_no_fromn";
  50. print "Mails without message:tt$count_no_txtn";
  51. print "Too big mails (> $opt_max_mail_size):t$count_too_bign";
  52. print "Duplicate mails:tt$count_duplicatesn";
  53. print "Forwarded mails:tt$count_forwarded_msgsn";
  54. print "Mails altogether:tt"; 
  55. print $inserted_mails+$ignored;
  56. print "n";
  57. exit(0);
  58. sub usage
  59. {  
  60.   my($VER)=@_;
  61.   
  62.   $0 =~ s/./(.+)/$1/;
  63.   if ($opt_version)
  64.   {
  65.     print "$0 version $VERn";
  66.   } 
  67.   else
  68.   {
  69.     print <<EOF;
  70. $0 version $VER
  71. Usage: $0 [options] file1 [file2 file3 ...]
  72. Description: Inserts mails from file(s) into a database
  73. Options:
  74. --help             show this help and exit
  75. --version          shows the version of the program
  76. --db_engine=...    database server (default: $opt_db_engine)
  77. --db=...           database to be used (default: $opt_db)
  78. --host=...         hostname to be used (default: $opt_host)
  79. --password=...     user password for the db server
  80. --user=...         username for the db server
  81. --max_mail_size=#  max size of a mail to be inserted into the db.
  82.                    mail will be ignored if it exceeds this size
  83.                    (default $opt_max_mail_size)
  84. EOF
  85.   }
  86.   exit(0);
  87. }
  88. sub create_table_if_needed
  89. {
  90.   my ($dbh)=@_;
  91.   my ($sth,$create);
  92.   
  93.   $sth = $dbh->prepare("select count(*) from $opt_table") or die $dbh->errstr;
  94.   if (!$sth->execute)
  95.   {
  96.     $create = "CREATE TABLE $opt_table (msg_nro mediumint unsigned not null ";
  97.     $create .= "auto_increment, date DATETIME NOT NULL, time_zone CHAR(6) ";
  98.     $create .= "NOT NULL, mail_from char(120) not null, reply char(120), ";
  99.     $create .= "mail_to TEXT, cc TEXT, sbj char(200), txt MEDIUMTEXT NOT ";
  100.     $create .= "NULL, file char(32) noT NULL, hash INT NOT NULL, key ";
  101.     $create .= "(msg_nro), primary key (mail_from, date, time_zone, hash))";
  102.     $sth = $dbh->prepare($create) or die $dbh->errstr;
  103.     $sth->execute() or die $dbh->errstr;
  104.   }  
  105. }
  106. sub process_mail_file
  107. {
  108.   my ($dbh,$file_name)= @_;
  109.   my (%values,$type,$check);
  110.   %values=(); $type="";
  111.   $check=0;
  112.   while (<FILE>)
  113.   {
  114.     chop;
  115.     if ($type ne "message")
  116.     { 
  117.       if (/^Reply-To: (.*)/i)  # finding different fields from file
  118.       {
  119. $type="reply";
  120. $values{$type}= $1;
  121.       }
  122.       elsif (/^From: (.*)/i)
  123.       {
  124. $type="from";
  125. $values{$type}= $1;
  126.       }
  127.       elsif (/^To: (.*)/i)
  128.       {
  129. $type="to";
  130. $values{$type}= $1;
  131.       }
  132.       elsif (/^Cc: (.*)/i)
  133.       {
  134. $type="cc";
  135. $values{$type}= $1;
  136.       }
  137.       elsif (/^Subject: (.*)/i)
  138.       {
  139. $type="subject";
  140. $values{$type}= $1;
  141.       }
  142.       elsif (/^Date: (.*)/i)
  143.       {
  144. date_parser($1,%values);
  145. $type="rubbish";
  146.       }
  147.       elsif (/^[wW-]+:s/)
  148.       {
  149. $type="rubbish";  
  150.       }
  151.       elsif ($_ eq "")
  152.       { 
  153. $type="message";
  154. $values{$type}="";
  155.       }
  156.       else
  157.       {
  158. s/^s*/ /;
  159. $values{$type}.= $_;
  160.       }
  161.     }
  162.     elsif ($check!=0 && $_ ne "") # in case of forwarded messages
  163.     {
  164.       $values{$type}.= "n" . $_;
  165.       $check--;
  166.     }
  167.     elsif (/^From .* dd:dd:ddsdddd$/)
  168.     {
  169.       $values{'hash'}= checksum("$values{'message'}");
  170.       update_table($dbh,$file_name,%values);
  171.       %values=(); $type="";
  172.       $check=0;
  173.     }
  174.     elsif (/-* forwarded message .*-*/i) # in case of forwarded messages
  175.     {
  176.       $values{$type}.= "n" . $_;
  177.       $check++;
  178.       $count_forwarded_msgs++;
  179.     }
  180.     else
  181.     {
  182.       $values{$type}.= "n" . $_;
  183.     }
  184.   }
  185.   $values{'hash'}= checksum("$values{'message'}");
  186.   update_table($dbh,$file_name,%values);
  187. }
  188. ########
  189. # converts date to the right form
  190. sub date_parser
  191. {
  192.   my ($date_raw,$values)=@_;
  193.   $date_raw =~ /.*?(d{1,2}?) (.+?) (d{2,4}?) (dd:dd:dd?) ([w-+]{3,5})/;
  194.   $values->{'date'}=$3 . "-" . $months{$2} . "-" . "$1 $4";
  195.   $values->{'time_zone'}=$5;
  196. }
  197. #########
  198. # this is runned when the whole mail is gathered.
  199. # this actually puts the mail to the database.
  200. sub update_table
  201. {
  202.   my($dbh,$file_name,$values)=@_;
  203.   my($query);
  204.   if (! defined($values->{'subject'}) || !defined($values->{'to'}) || !defined)
  205.   {
  206.     $no_subject++;
  207.     return; # Ignore these
  208.   }
  209.   $values->{'message'} =~ s/^s*//; #removes whitespaces from the beginning 
  210.   $values->{'message'} =~ s/s*$//; #removes whitespaces from the end
  211.   $query = "insert into $opt_table values ('" . "NULL','" . $values->{'date'};
  212.   $query .= "','" . $values->{'time_zone'} . "',";
  213.   $query .= (defined($values->{'from'}) ? $dbh->quote($values->{'from'}) : "NULL") . ",";
  214.   $query .= (defined($values->{'reply'}) ? $dbh->quote($values->{'reply'}) : "NULL") . ",";
  215.   $query .= (defined($values->{'to'}) ? $dbh->quote($values->{'to'}) : "NULL") . ","; 
  216.   $query .= (defined($values->{'cc'}) ? $dbh->quote($values->{'cc'}) : "NULL") . ","; 
  217.   $query .= $dbh->quote($values->{'subject'}) . ",";
  218.   $query .= $dbh->quote($values->{'message'}) . "," . $dbh->quote($file_name);
  219.   $query .= ",'" . $values->{'hash'} . "')";
  220.   
  221.   if (length($values->{'message'}) > $opt_max_mail_size) #disables big message
  222.   {
  223.     $count_too_big++;
  224.   }
  225.   elsif ($values->{'from'} eq "") #disables mails with no from field
  226.   {
  227.     $count_no_from++;
  228.   }
  229.   elsif ($values->{'message'} eq "") #disables mails with no message text
  230.   {
  231.     $count_no_msg_text++;
  232.   }
  233.   elsif ($dbh->do($query))
  234.   {
  235.     $inserted_mails++;
  236.   }
  237.   elsif (!($dbh->errstr =~ /^Duplicate entry /)) #disables duplicates
  238.   {
  239.       print "Aborting: Got error '$dbh->errstr' for query: '$query'n";
  240.   }
  241.   else
  242.   {
  243.     $count_duplicates++;    
  244.   }
  245.   $query="";
  246. }
  247. ##########
  248. # In case you have two identical messages we wanted to identify them
  249. # and remove additionals;  We do this by calculating a hash number of the
  250. # message and ignoring messages with the same from, date and hash.
  251. # This function calculates a simple 32 bit hash value for the message.
  252. sub checksum
  253. {
  254.   my ($txt)= @_;
  255.   my ($crc,$i,$count);
  256.   $count = length($txt);
  257.   for ($crc = $i = 0; $i < $count ; $i++)
  258.   {
  259.     $crc = (($crc << 1) + (ord (substr ($txt, $i, 1)))) +
  260.       (($crc & (1 << 30)) ? 1 : 0);
  261.     $crc &= ((1 << 31) -1);
  262.   }
  263.   return $crc;
  264. }