+Patch to add References and In-Reply-To parsing and handling to OTRS.
+
+ Created 2004-01-09 by Petter Reinholdtsen <pere@hungry.com>
+
+--- Kernel/Config/Defaults.pm.orig 2003-07-13 21:23:21.000000000 +0200
++++ Kernel/Config/Defaults.pm 2004-01-09 15:21:43.000000000 +0100
+@@ -714,6 +714,8 @@
+ 'Mailing-List',
+ 'X-Loop',
+ 'X-No-Loop',
++ 'References',
++ 'In-Reply-To',
+ 'X-OTRS-Loop',
+ 'X-OTRS-Info',
+ 'X-OTRS-Priority',
+--- Kernel/System/PostMaster.pm.orig 2003-06-22 20:37:36.000000000 +0200
++++ Kernel/System/PostMaster.pm 2004-01-09 16:57:48.000000000 +0100
+@@ -221,23 +221,91 @@
+ my $Self = shift;
+ my %Param = @_;
+ my $Subject = $Param{Subject} || '';
+- if (my $Tn = $Self->{TicketObject}->GetTNByString($Subject)) {
+- my $TicketID = $Self->{TicketObject}->CheckTicketNr(Tn => $Tn);
++ my $Tn;
++ my $TicketID;
++ if ($Tn = $Self->{TicketObject}->GetTNByString($Subject)) {
++ $TicketID = $Self->{TicketObject}->CheckTicketNr(Tn => $Tn);
+ if ($Self->{Debug} > 1) {
+ $Self->{LogObject}->Log(
+ Priority => 'debug',
+ Message => "CheckFollowUp: Tn: $Tn found or forward!",
+ );
+ }
+- if ($TicketID) {
+- if ($Self->{Debug} > 1) {
+- $Self->{LogObject}->Log(
++ } else {
++ # Based on info from <URL:http://www.jwz.org/doc/threading.html>
++ my @msgids = ();
++
++ # Extract Message-id(s) from References and In-Reply-to
++ my $references = $Param{References};
++ my $inreplyto = $Param{'In-Reply-To'}; # XXX Check capitalisation
++
++ push(@msgids, split(/\s+/, $references)) if ($references);
++
++ if ($inreplyto) {
++ if ($inreplyto =~ m/(<[^>]+>)/) {
++ push(@msgids, $1);
++ } else {
++ $Self->{LogObject}->Log(
++ Priority => 'debug',
++ Message => "CheckFollowUp: Unhandled In-Reply-To: '$inreplyto'",
++ );
++ }
++ }
++
++ # Look up Message-id(s) using Article::ArticleMsgIdLookup
++ my @ids = ();
++ my %checked;
++ my $msgid;
++ for $msgid (@msgids) {
++ next if $checked{$msgid};
++ my @ArticleIDs =
++ $Self->{TicketObject}->ArticleMsgIdLookup(MessageID => $msgid);
++ my @TicketIDs;
++ my $aid;
++ for $aid (@ArticleIDs) {
++ my %data =
++ $Self->{TicketObject}->GetArticle(ArticleID => $aid);
++ my $tn = $Self->{TicketObject}->GetTNOfId(ID => $data{TicketID});
++ push(@TicketIDs, $tn);
++ }
++ push(@ids, @TicketIDs) if (@TicketIDs);
++ $checked{$msgid} = 1;
++ }
++
++ # Reduce list of IDs to unique IDs only
++ my $id;
++ my %idhash;
++ for $id (sort @ids) {
++ $idhash{$id} = 1;
++ }
++ @ids = sort keys %idhash;
++
++ # If the Message-id(s) are already in the database, use their
++ # ticked-id
++ if (1 < @ids) {
++ if ($Self->{Debug} > 1) {
++ $Self->{LogObject}->Log(
++ Priority => 'debug',
++ Message => "CheckFollowUp: Several possible ticket ids",
++ );
++ }
++ }
++
++ # Just pick the first. Not sure how we should handle several
++ # ticket ids
++ if (@ids) {
++ $Tn = $ids[0];
++ $TicketID = $Self->{TicketObject}->CheckTicketNr(Tn => $Tn);
++ }
++ }
++ if ($TicketID) {
++ if ($Self->{Debug} > 1) {
++ $Self->{LogObject}->Log(
+ Priority => 'debug',
+- Message => "CheckFollowUp: ja, it's a follow up ($Tn/$TicketID)",
++ Message => "CheckFollowUp: yes, it's a follow up ($Tn/$TicketID)",
+ );
+- }
+- return ($Tn, $TicketID);
+- }
++ }
++ return ($Tn, $TicketID);
+ }
+ return;
+ }
+--- Kernel/System/Ticket/Article.pm.orig 2003-06-19 00:40:35.000000000 +0200
++++ Kernel/System/Ticket/Article.pm 2004-01-09 15:21:15.000000000 +0100
+@@ -621,5 +621,35 @@
+ return %Data;
+ }
+ # --
++sub ArticleMsgIdLookup {
++ my $Self = shift;
++ my %Param = @_;
++ my @Index = ();
++ # --
++ # check needed stuff
++ # --
++ if (!$Param{MessageID}) {
++ $Self->{LogObject}->Log(Priority => 'error', Message => "Need MessageID!");
++ return;
++ }
++ # --
++ # sql query
++ # --
++ my $SQL = "SELECT id" .
++ " FROM " .
++ " article " .
++ " WHERE " .
++ " a_message_id = '$Param{MessageID}' " .
++ " ORDER BY incoming_time";
++ $Self->{DBObject}->Prepare(SQL => $SQL);
++ while (my @Row = $Self->{DBObject}->FetchrowArray()) {
++ push (@Index, $Row[0]);
++ }
++ # --
++ # return data
++ # --
++ return @Index;
++}
++# --
+
+ 1;