diff options
Diffstat (limited to 'rt/lib/RT/Interface/Email.pm')
-rwxr-xr-x | rt/lib/RT/Interface/Email.pm | 119 |
1 files changed, 71 insertions, 48 deletions
diff --git a/rt/lib/RT/Interface/Email.pm b/rt/lib/RT/Interface/Email.pm index de125f5..dfbd4ae 100755 --- a/rt/lib/RT/Interface/Email.pm +++ b/rt/lib/RT/Interface/Email.pm @@ -1,38 +1,40 @@ # BEGIN BPS TAGGED BLOCK {{{ -# +# # COPYRIGHT: -# -# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC +# +# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC # <jesse@bestpractical.com> -# +# # (Except where explicitly superseded by other copyright notices) -# -# +# +# # LICENSE: -# +# # This work is made available to you under the terms of Version 2 of # the GNU General Public License. A copy of that license should have # been provided with this software, but in any event can be snarfed # from www.gnu.org. -# +# # This work is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -# +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 or visit their web page on the internet at +# http://www.gnu.org/copyleft/gpl.html. +# +# # CONTRIBUTION SUBMISSION POLICY: -# +# # (The following paragraph is not intended to limit the rights granted # to you to modify and distribute this software under the terms of # the GNU General Public License and is only of importance to you if # you choose to contribute your changes and enhancements to the # community by submitting them to Best Practical Solutions, LLC.) -# +# # By intentionally submitting any modifications, corrections or # derivatives to this work, or any other work intended for use with # Request Tracker, to Best Practical Solutions, LLC, you confirm that @@ -41,7 +43,7 @@ # royalty-free, perpetual, license to use, copy, create derivative # works based on those contributions, and sublicense and distribute # those contributions and any derivatives thereof. -# +# # END BPS TAGGED BLOCK }}} package RT::Interface::Email; @@ -219,7 +221,7 @@ Returns the same array with any IsRTAddress()es weeded out. =cut sub CullRTAddresses { - return ( grep { IsRTAddress($_) } @_ ); + return grep !IsRTAddress($_), @_; } # }}} @@ -242,14 +244,16 @@ sub MailError { level => $args{'LogLevel'}, message => $args{'Explanation'} ); + # the colons are necessary to make ->build include non-standard headers my $entity = MIME::Entity->build( Type => "multipart/mixed", From => $args{'From'}, Bcc => $args{'Bcc'}, To => $args{'To'}, Subject => $args{'Subject'}, - Precedence => 'bulk', - 'X-RT-Loop-Prevention' => $RT::rtname, + 'Precedence:' => 'bulk', + 'X-RT-Loop-Prevention:' => $RT::rtname, + 'In-Reply-To:' => $args{'MIMEObj'} ? $args{'MIMEObj'}->head->get('Message-Id') : undef ); $entity->attach( Data => $args{'Explanation'} . "\n" ); @@ -297,7 +301,6 @@ sub CreateUser { unless ($Val) { # Deal with the race condition of two account creations at once - # if ($Username) { $NewUser->LoadByName($Username); } @@ -393,12 +396,15 @@ sub ParseSenderAddressFromHead { my $head = shift; #Figure out who's sending this message. - my $From = $head->get('Reply-To') - || $head->get('From') - || $head->get('Sender'); - return ( ParseAddressFromHeader($From) ); -} + foreach my $header ('Reply-To', 'From', 'Sender') { + my $From = $head->get($header); + my ($addr, $name) = ParseAddressFromHeader($From); + # only return if the address is not empty + return ($addr, $name) if $addr; + } + return (undef, undef); +} # }}} # {{{ ParseErrorsToAdddressFromHead @@ -442,11 +448,12 @@ Takes an address from $head->get('Line') and returns a tuple: user@host, friendl sub ParseAddressFromHeader { my $Addr = shift; + # Some broken mailers send: ""Vincent, Jesse"" <jesse@fsck.com>. Hate + $Addr =~ s/\"\"(.*?)\"\"/\"$1\"/g; my @Addresses = Mail::Address->parse($Addr); - my $AddrObj = $Addresses[0]; - - unless ( ref($AddrObj) ) { + my ($AddrObj) = grep ref $_, @Addresses; + unless ( $AddrObj ) { return ( undef, undef ); } @@ -568,6 +575,22 @@ sub Gateway { #Pull apart the subject line my $Subject = $head->get('Subject') || ''; chomp $Subject; + + # {{{ Lets check for mail loops of various sorts. + my ($should_store_machine_generated_message, $IsALoop, $result); + ( $should_store_machine_generated_message, $ErrorsTo, $result, $IsALoop ) = + _HandleMachineGeneratedMail( + Message => $Message, + ErrorsTo => $ErrorsTo, + Subject => $Subject, + MessageId => $MessageId + ); + + # Do not pass loop messages to MailPlugins, to make sure the loop + # is broken, unless $RT::StoreLoops is set. + if ($IsALoop && !$should_store_machine_generated_message) { + return ( 0, $result, undef ); + } $args{'ticket'} ||= ParseTicketId($Subject); @@ -643,6 +666,10 @@ sub Gateway { $skip_action{$action}++ if $AuthStat == -2; } + # strip actions we should skip + @actions = grep !$skip_action{$_}, @actions if $AuthStat == -2; + last unless @actions; + last if $AuthStat == -1; } # {{{ If authentication fails and no new user was created, get out. @@ -679,22 +706,11 @@ sub Gateway { ); } - # {{{ Lets check for mail loops of various sorts. - my ($continue, $result); - ( $continue, $ErrorsTo, $result ) = _HandleMachineGeneratedMail( - Message => $Message, - ErrorsTo => $ErrorsTo, - Subject => $Subject, - MessageId => $MessageId - ); - unless ($continue) { + unless ($should_store_machine_generated_message) { return ( 0, $result, undef ); } - # strip actions we should skip - @actions = grep !$skip_action{$_}, @actions; - # if plugin's updated SystemTicket then update arguments $args{'ticket'} = $SystemTicket->Id if $SystemTicket && $SystemTicket->Id; @@ -724,7 +740,7 @@ sub Gateway { if ( $id == 0 ) { MailError( To => $ErrorsTo, - Subject => "Ticket creation failed", + Subject => "Ticket creation failed: $Subject", Explanation => $ErrStr, MIMEObj => $Message ); @@ -736,20 +752,23 @@ sub Gateway { @actions = grep !/^(comment|correspond)$/, @actions; $args{'ticket'} = $id; - } else { + } elsif ( $args{'ticket'} ) { $Ticket->Load( $args{'ticket'} ); unless ( $Ticket->Id ) { my $error = "Could not find a ticket with id " . $args{'ticket'}; MailError( To => $ErrorsTo, - Subject => "Message not recorded", + Subject => "Message not recorded: $Subject", Explanation => $error, MIMEObj => $Message ); return ( 0, $error ); } + $args{'ticket'} = $Ticket->id; + } else { + return ( 1, "Success", $Ticket ); } # }}} @@ -764,7 +783,7 @@ sub Gateway { #Warn the sender that we couldn't actually submit the comment. MailError( To => $ErrorsTo, - Subject => "Message not recorded", + Subject => "Message not recorded: $Subject", Explanation => $msg, MIMEObj => $Message ); @@ -856,6 +875,7 @@ EOT ); # Also notify the requestor that his request has been dropped. + if ($args{'Requestor'} ne $RT::OwnerEmail) { MailError( To => $args{'Requestor'}, Subject => "Could not load a valid user", @@ -867,6 +887,7 @@ EOT MIMEObj => $args{'Message'}, LogLevel => 'error' ); + } } =head2 _HandleMachineGeneratedMail @@ -877,7 +898,8 @@ Takes named params: Subject Checks the message to see if it's a bounce, if it looks like a loop, if it's autogenerated, etc. -Returns a triple of ("Should we continue (boolean)", "New value for $ErrorsTo", "Status message"); +Returns a triple of ("Should we continue (boolean)", "New value for $ErrorsTo", "Status message", +"This message appears to be a loop (boolean)" ); =cut @@ -905,7 +927,7 @@ sub _HandleMachineGeneratedMail { # Warn someone if it's a loop, before we drop it on the ground if ($IsALoop) { - $RT::Logger->crit("RT Recieved mail (".$args{MessageId}.") from itself."); + $RT::Logger->crit("RT Received mail (".$args{MessageId}.") from itself."); #Should we mail it to RTOwner? if ($RT::LoopsToRTOwner) { @@ -918,7 +940,7 @@ sub _HandleMachineGeneratedMail { } #Do we actually want to store it? - return ( 0, $ErrorsTo, "Message Bounced" ) unless ($RT::StoreLoops); + return ( 0, $ErrorsTo, "Message Bounced", $IsALoop ) unless ($RT::StoreLoops); } # Squelch replies if necessary @@ -942,7 +964,7 @@ sub _HandleMachineGeneratedMail { $head->add( 'RT-Squelch-Replies-To', $Sender ); $head->add( 'RT-DetectedAutoGenerated', 'true' ); } - return ( 1, $ErrorsTo, "Handled machine detection" ); + return ( 1, $ErrorsTo, "Handled machine detection", $IsALoop ); } =head2 IsCorrectAction @@ -953,7 +975,8 @@ Returns a list of valid actions we've found for this message sub IsCorrectAction { my $action = shift; - my @actions = split /-/, $action; + my @actions = grep $_, split /-/, $action; + return ( 0, '(no value)' ) unless @actions; foreach (@actions) { return ( 0, $_ ) unless /^(?:comment|correspond|take|resolve)$/; } |