diff options
Diffstat (limited to 'rt/lib/RT/EmailParser.pm')
-rw-r--r-- | rt/lib/RT/EmailParser.pm | 163 |
1 files changed, 118 insertions, 45 deletions
diff --git a/rt/lib/RT/EmailParser.pm b/rt/lib/RT/EmailParser.pm index 3a99e5a5e..8ed810c56 100644 --- a/rt/lib/RT/EmailParser.pm +++ b/rt/lib/RT/EmailParser.pm @@ -1,8 +1,8 @@ -# BEGIN BPS TAGGED BLOCK {{{ +# {{{ BEGIN BPS TAGGED BLOCK # # COPYRIGHT: # -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC # <jesse@bestpractical.com> # # (Except where explicitly superseded by other copyright notices) @@ -42,7 +42,7 @@ # works based on those contributions, and sublicense and distribute # those contributions and any derivatives thereof. # -# END BPS TAGGED BLOCK }}} +# }}} END BPS TAGGED BLOCK package RT::EmailParser; @@ -77,7 +77,6 @@ ok(require RT::EmailParser); =head2 new -Returns a new RT::EmailParser object =cut @@ -90,12 +89,96 @@ sub new { } -# {{{ sub SmartParseMIMEEntityFromScalar + +# {{{ sub debug + +sub debug { + my $val = shift; + my ($debug); + if ($val) { + $RT::Logger->debug( $val . "\n" ); + if ($debug) { + print STDERR "$val\n"; + } + } + if ($debug) { + return (1); + } +} + +# }}} + +# {{{ sub CheckForLoops + +sub CheckForLoops { + my $self = shift; + + my $head = $self->Head; + + #If this instance of RT sent it our, we don't want to take it in + my $RTLoop = $head->get("X-RT-Loop-Prevention") || ""; + chomp($RTLoop); #remove that newline + if ( $RTLoop =~ /^\Q$RT::rtname\E/o ) { + return (1); + } + + # TODO: We might not trap the case where RT instance A sends a mail + # to RT instance B which sends a mail to ... + return (undef); +} + +# }}} + +# {{{ sub CheckForSuspiciousSender + +sub CheckForSuspiciousSender { + my $self = shift; + + #if it's from a postmaster or mailer daemon, it's likely a bounce. + + #TODO: better algorithms needed here - there is no standards for + #bounces, so it's very difficult to separate them from anything + #else. At the other hand, the Return-To address is only ment to be + #used as an error channel, we might want to put up a separate + #Return-To address which is treated differently. + + #TODO: search through the whole email and find the right Ticket ID. + + my ( $From, $junk ) = $self->ParseSenderAddressFromHead(); + + if ( ( $From =~ /^mailer-daemon/i ) or ( $From =~ /^postmaster/i ) ) { + return (1); + + } + + return (undef); + +} + +# }}} + +# {{{ sub CheckForAutoGenerated +sub CheckForAutoGenerated { + my $self = shift; + my $head = $self->Head; + + my $Precedence = $head->get("Precedence") || ""; + if ( $Precedence =~ /^(bulk|junk)/i ) { + return (1); + } + else { + return (undef); + } +} + +# }}} + =head2 SmartParseMIMEEntityFromScalar { Message => SCALAR_REF, Decode => BOOL } Parse a message stored in a scalar from scalar_ref + =cut sub SmartParseMIMEEntityFromScalar { @@ -140,16 +223,8 @@ sub SmartParseMIMEEntityFromScalar { } -# }}} - # {{{ sub ParseMIMEEntityFromSTDIN -=head2 ParseMIMEEntityFromSTDIN - -Parse a message from standard input - -=cut - sub ParseMIMEEntityFromSTDIN { my $self = shift; my $postprocess = (@_ ? shift : 1); @@ -158,8 +233,6 @@ sub ParseMIMEEntityFromSTDIN { # }}} -# {{{ ParseMIMEEntityFromScalar - =head2 ParseMIMEEntityFromScalar $message Takes either a scalar or a reference to a scalr which contains a stringified MIME message. @@ -168,6 +241,7 @@ Parses it. Returns true if it wins. Returns false if it loses. + =cut sub ParseMIMEEntityFromScalar { @@ -177,7 +251,6 @@ sub ParseMIMEEntityFromScalar { $self->_ParseMIMEEntity($message,'parse_data', $postprocess); } -# }}} # {{{ ParseMIMEEntityFromFilehandle *FH @@ -212,8 +285,8 @@ sub ParseMIMEEntityFromFile { } # }}} - -# {{{ _ParseMIMEEntity +# +# {{{ _ParseMIMEEntity { sub _ParseMIMEEntity { my $self = shift; my $message = shift; @@ -241,6 +314,7 @@ sub _ParseMIMEEntity { } + # }}} # {{{ _PostProcessNewEntity @@ -256,17 +330,12 @@ sub _PostProcessNewEntity { #Now we've got a parsed mime object. - # Unfold headers that are have embedded newlines - # Better do this before conversion or it will break - # with multiline encoded Subject (RFC2047) (fsck.com #5594) - - $self->Head->unfold; - - # try to convert text parts into utf-8 charset RT::I18N::SetMIMEEntityToEncoding($self->{'entity'}, 'utf-8'); + # Unfold headers that are have embedded newlines + $self->Head->unfold; } @@ -277,10 +346,17 @@ sub _PostProcessNewEntity { sub ParseTicketId { my $self = shift; - $RT::Logger->warnings("RT::EmailParser->ParseTicketId deprecated. You should be using RT::Interface::Email"); - require RT::Interface::Email; - RT::Interface::Email::ParseTicketId(@_); + my $Subject = shift; + + if ( $Subject =~ s/\[\Q$RT::rtname\E\s+\#(\d+)\s*\]//i ) { + my $id = $1; + $RT::Logger->debug("Found a ticket ID. It's $id"); + return ($id); + } + else { + return (undef); + } } # }}} @@ -317,10 +393,10 @@ sub ParseCcAddressesFromHead { my $Address = $AddrObj->address; my $user = RT::User->new($RT::SystemUser); $Address = $user->CanonicalizeEmailAddress($Address); - next if ( lc $args{'CurrentUser'}->EmailAddress eq lc $Address ); - next if ( lc $args{'QueueObj'}->CorrespondAddress eq lc $Address ); - next if ( lc $args{'QueueObj'}->CommentAddress eq lc $Address ); - next if ( $self->IsRTAddress($Address) ); + next if ( $args{'CurrentUser'}->EmailAddress =~ /^$Address$/i ); + next if ( $args{'QueueObj'}->CorrespondAddress =~ /^$Address$/i ); + next if ( $args{'QueueObj'}->CommentAddress =~ /^$Address$/i ); + next if ( IsRTAddress($Address) ); push ( @Addresses, $Address ); } @@ -413,7 +489,7 @@ sub ParseAddressFromHeader { # {{{ IsRTAddress -=head2 IsRTaddress ADDRESS +=item IsRTaddress ADDRESS Takes a single parameter, an email address. Returns true if that address matches the $RTAddressRegexp. @@ -447,7 +523,7 @@ sub IsRTAddress { # {{{ CullRTAddresses -=head2 CullRTAddresses ARRAY +=item CullRTAddresses ARRAY Takes a single argument, an array of email addresses. Returns the same array with any IsRTAddress()es weeded out. @@ -468,10 +544,7 @@ sub CullRTAddresses { my @addrlist; foreach my $addr( @addresses ) { - # We use the class instead of the instance - # because sloppy code calls this method - # without a $self - push (@addrlist, $addr) unless RT::EmailParser->IsRTAddress($addr); + push (@addrlist, $addr) unless IsRTAddress("", $addr); } return (@addrlist); } @@ -495,7 +568,7 @@ sub CullRTAddresses { # template for the rejection message. -=head2 LookupExternalUserInfo +=item LookupExternalUserInfo LookupExternalUserInfo is a site-definable method for synchronizing incoming users with an external data source. @@ -508,12 +581,12 @@ sub CullRTAddresses { It returns (FoundInExternalDatabase, ParamHash); - FoundInExternalDatabase must be set to 1 before return if the user - was found in the external database. + FoundInExternalDatabase must be set to 1 before return if the user was + found in the external database. - ParamHash is a Perl parameter hash which can contain at least the - following fields. These fields are used to populate RT's users - database when the user is created. + ParamHash is a Perl parameter hash which can contain at least the following + fields. These fields are used to populate RT's users database when the user + is created EmailAddress is the email address that RT should use for this user. Name is the 'Name' attribute RT should use for this user. @@ -568,7 +641,6 @@ sub Entity { } # }}} - # {{{ _SetupMIMEParser =head2 _SetupMIMEParser $parser @@ -614,6 +686,7 @@ sub _SetupMIMEParser { # Temp files should never be recycled, especially when running under perl taint checking $parser->tmp_recycling(0); + } |