Mbox2Rt

From Request Tracker Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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.