The purpose of this patch is to process In-Reply-To headers in incoming email, to attach to an existing replied-to ticket even if the subject line has changed. This is a help when, for instance, someone CC's the RT system to create a ticket, and then other people on the CC list reply to all. Normally this would create a new ticket each time, because the original email doesn't have the RT subject header magic, but with this patch they're all added to the same ticket.
This is most useful when used in conjunction with a scrip that adds all users in the Cc header to the ticket's Cc list, as you can then give the Cc users permissions to update the ticket instead of giving Everyone the ReplyTo right.
Specifically, this patch first checks for the RT subject line, and only checks for the In-Reply-To field if that's not found. If neither method pulls up a ticket number, a new ticket is created.
--- /usr/share/request-tracker3.4/lib/RT/Interface/Email.pm 2005-08-25 12:53:40.000000000 -0700
+++ /usr/local/share/request-tracker3.4/lib/RT/Interface/Email.pm 2007-02-28 19:18:25.000000000 -0800
@@ -434,13 +434,12 @@
sub ParseTicketId {
my $Subject = shift;
- my $id;
my $test_name = $RT::EmailSubjectTagRegex || qr/\Q$RT::rtname\E/;
if ( $Subject =~ s/\[$test_name\s+\#(\d+)\s*\]//i ) {
my $id = $1;
- $RT::Logger->debug("Found a ticket ID. It's $id");
+ $RT::Logger->debug("Found a ticket ID using Subject header. It's $id");
return ($id);
}
else {
@@ -451,6 +450,36 @@
# }}}
+# {{{ sub ParseInReplyTo
+
+sub ParseInReplyTo {
+ my $MessageId = shift;
+ $MessageId =~ s/<(.+)>/$1/;
+
+ if ($MessageId eq '') {
+ return (undef);
+ }
+
+ my $query = "SELECT ObjectId" .
+ " FROM Transactions JOIN Attachments" .
+ " ON Attachments.TransactionId = Transactions.id" .
+ " WHERE ObjectType = 'RT::Ticket'" .
+ " AND MessageId = '" . $MessageId . "';";
+
+ my @result = $RT::Handle->FetchResult($query);
+
+ if ( $result[0] =~ /\d+/ ) {
+ my $id = $result[0];
+ $RT::Logger->debug("Found a ticket ID using In-Reply-To header. It's $id");
+ return ($id);
+ }
+ else {
+ return (undef);
+ }
+}
+# }}}
+
+
=head2 Gateway ARGSREF
@@ -538,7 +567,12 @@
my $Subject = $head->get('Subject') || '';
chomp $Subject;
+ #Pull apart the in-reply-to line
+ my $MessageId = $head->get('In-Reply-To') || '';
+ chomp($MessageId);
+
$args{'ticket'} ||= ParseTicketId($Subject);
+ $args{'ticket'} ||= ParseInReplyTo($MessageId);
my $SystemTicket;
my $Right = 'CreateTicket';
This was very useful. I made a few mods to the code to avoid having one variable hide another (RT 3.6.6). See diff below. We also found that we needed a new index on our mysql database in order to make the database search efficient. The command was:
alter table Attachments add index Attachments4(MessageId(25));
This also required the following mysql parameters had to be at least this large: innodb_buffer_pool_size: 256M; innodb_log_buffer_size: 4M; innodb_log_file_size: 64M
Here's my diff:
--- lib/RT/Interface/Email.pm 2007-12-26 13:01:11.000000000 -0800
+++ local/lib/RT/Interface/Email.pm 2008-04-16 14:12:43.000000000 -0700
@@ -477,7 +477,7 @@
if ( $Subject =~ s/\[$test_name\s+\#(\d+)\s*\]//i ) {
my $id = $1;
- $RT::Logger->debug("Found a ticket ID. It's $id");
+ $RT::Logger->debug("Found a ticket ID using Subject header. It's $id");
return ($id);
} else {
return (undef);
@@ -486,6 +486,36 @@
# }}}
+# {{{ sub ParseInReplyTo
+
+sub ParseInReplyTo {
+ my $MessageId = shift;
+ $MessageId =~ s/<(.+)>/$1/;
+
+ if ($MessageId eq '') {
+ return (undef);
+ }
+
+ my $query = "SELECT ObjectId" .
+ " FROM Transactions JOIN Attachments" .
+ " ON Attachments.TransactionId = Transactions.id" .
+ " WHERE ObjectType = 'RT::Ticket'" .
+ " AND MessageId = '" . $MessageId . "';";
+
+ my @result = $RT::Handle->FetchResult($query);
+
+ if ( $result[0] =~ /\d+/ ) {
+ my $id = $result[0];
+ $RT::Logger->debug("Found a ticket ID using In-Reply-To header. It's $id");
+ return ($id);
+ }
+ else {
+ return (undef);
+ }
+}
+# }}}
+
+
=head2 Gateway ARGSREF
@@ -592,7 +622,12 @@
return ( 0, $result, undef );
}
+ # try to pull out the in-reply-to message id
+ my $ReplyMessageId = $head->get('In-Reply-To') || '';
+ chomp($ReplyMessageId);
+
$args{'ticket'} ||= ParseTicketId($Subject);
+ $args{'ticket'} ||= ParseInReplyTo($ReplyMessageId);
$SystemTicket = RT::Ticket->new($RT::SystemUser);
$SystemTicket->Load( $args{'ticket'} ) if ( $args{'ticket'} ) ;