Mbox2Rt
This is a piece of code i use to import unix-style mailboxes ( mbox , or whatever you may call them ) into an RT database and keep the threaded nature of the mail in the mailbox, unfortunately it doesn't work very well in importing all email in mailboxes; sometimes (failed in investigating when and why exactly), it only imports parts of a mailbox.... :(
Prerequisites:
- Mail::Box perl-module
- an installed RT (at least the 'lib' dir from a RT distribution)
- a user that can read RT_SiteConfig.pm (otherwise RT will complain)
Caveats:
- I'm quite new to RT internals, most of this code is inspired on the Gateway-subroutine in RT::Interface::Email.pm, so your mileage may vary
- if the queue you use this on has an autoreply on create, every ticket that will be created will generate an autoreply
#!/usr/bin/perl
use strict;
use Getopt::Std;
use Mail::Box::Manager;
#TODO change this to your local RT lib
use lib qw(/usr/local/rt34/lib);
use RT;
RT::LoadConfig();
RT::Init();
RT::ConnectToDatabase();
my %opts;
getopts('m:q:fh',\%opts);
if ($opts{'h'}) {
print <<"";
Usage: $0 -m <mailbox-file> -q <rt-queue-id> [-f] [-v] [-h]
-m <mbox> : mailbox file to parse
-q <rt-queue id> : numeric ID for the queue where you want to load the mailbox
-f : force, get rid of the interactive notices
-v : verbose
-h : this message
}
die "can't open mailbox $opts{'m'} (option -m)" unless (-r $opts{'m'});
die "need a queue-id (option -q)" unless ($opts{'q'});
# check if this is a valid queue
my $queue = RT::Queue->new( $RT::SystemUser );
$queue->Load( $opts{'q'} ); #this loads a queue by Id
die "'$opts{'q'}' is not a valid queue id (option -q)" unless ($queue->Id);
my $mgr = Mail::Box::Manager->new();
my $folder = $mgr->open(
$opts{'m'}
);
my $threads = $mgr->threads($folder);
foreach my $thread ($threads->all() ) {
if ($opts{'v'}) {
print "**new thread**\n";
print $thread->threadToString();
}
my @msgs = $thread->threadMessages;
my $first = shift @msgs;
my $ticket = process_first_msg($first);
foreach my $rest ( @msgs ) {
process_rest_msg($rest,$ticket);
}
}
sub process_first_msg {
my ($msg) = @_;
if ($opts{'v'}) {
print "\n**first-msg**\n". $msg->decoded ."\n****\n";
}
if ($opts{'v'} || !$opts{'f'}) {
print "\n**email-addrs**\n". join("\n", map {$_->format} $msg->to, $msg->cc,$msg->from,$msg->sender);
print "\n";
}
if (! $opts{'f'}) {
print "\n**subject**\n". $msg->head->get('subject');
print "\n";
print "Are you sure to process this msg? Enter 'y' to verify, other to cancel\n";
my $yes = <STDIN>;
chomp($yes);
return undef unless ($yes eq 'y');
}
my $Ticket = new RT::Ticket( $RT::SystemUser );
my ( $ticket_id, $Transaction, $ErrStr ) = $Ticket->Create(
Queue => $queue->Id,
Subject => $msg->head->get('Subject'),
Requestor => [ map {$_->format} $msg->from ],
Cc => [ map {$_->format} $msg->cc ],
MIMEObj => mailbox_to_rt($msg),
);
return $Ticket;
}
sub process_rest_msg {
my ($msg,$ticket) = @_;
if ($opts{'v'}) {
print "\n**follow-up**\n". $msg->decoded ."\n****\n";
}
if ($opts{'v'} || !$opts{'f'}) {
print "\n**email-addrs**\n". join("\n", map {$_->format} $msg->to, $msg->cc,$msg->from,$msg->sender);
print "\n";
}
if (! $opts{'f'}) {
print "\n**subject**\n". $msg->head->get('subject');
print "\n";
print "Are you sure to process this msg? Enter 'y' to verify, other to cancel\n";
my $yes = <STDIN>;
chomp($yes);
return undef unless ($yes eq 'y');
}
my ($status,$retmsg) = $ticket->Correspond(
CommitScrips => 0, #saw this in source code
MIMEObj => mailbox_to_rt($msg),
);
print "Status: $status\n";
print "Retmsg: $retmsg\n";
}
sub mailbox_to_rt {
my ($msg) = @_;
my $parser = RT::EmailParser->new();
$parser->SmartParseMIMEEntityFromScalar( Message => $msg->string );
return $parser->Entity();
}
When used with HideGlobalScrips, I would get errors from this script (crit: Can't locate RT/QueueDeactivatedScrip.pm). The fix in my case was to add local/lib.
--- mbox2rt.pl 2005/08/15 15:15:13 1.1 +++ mbox2rt.pl 2005/08/15 15:16:05 @@ -6,7 +6,7 @@ use Mail::Box::Manager; #TODO change this to your local RT lib -use lib qw(/usr/local/rt34/lib); +use lib qw(/usr/local/rt34/lib /usr/local/rt34/local/lib); use RT; RT::LoadConfig();
When using Ubuntu, you'll have to update the path. Below is what i've used to get it to work:
use lib ("/usr/share/request-tracker3.4/lib", "/usr/local/share/request-tracker3.4/lib");
Somehow the subject of the mail is not imported properly. For example, it results in this in RT after importation : =?iso-8859-1?q?Qu=E9bec_dans_l=27intranet?= This could be solved using the MIME::WordDecoder.