[Rt-commit] rt branch, 4.4/multiple-reply-to, repushed

? sunnavy sunnavy at bestpractical.com
Wed Nov 5 07:19:02 EST 2014


The branch 4.4/multiple-reply-to was deleted and repushed:
       was bb9337cdac4aba19b22c0ca00b888993d98707be
       now 395e0ca730b634f50c8227576fa1620aafbb8eb2

 1:  15a0c3b =  1:  15a0c3b RT::Interface::Email doesn't need to be an Exporter
 2:  9b135a2 =  2:  9b135a2 Reorder functions to more obviously split sending and receiving mail
 3:  670a057 =  3:  670a057 Adjust POD headers to reflect split
 4:  5dfc009 =  4:  5dfc009 Update MailPlugins to only reference existant modules
 5:  b9ed3c2 =  5:  b9ed3c2 Move MailPlugins documentation out of rt-mailgate, where is is mostly irrelevant
 6:  e3d18e3 =  6:  e3d18e3 Remove duplicate ParseCcAddressesFromHead in RT::EmailParser
 7:  a93449c =  7:  a93449c Use Scope::Upper to allow returns from Gateway from nested subs
 8:  f993bae =  8:  f993bae Add a base email plugin role, which provides TMPFAIL/FAILURE/SUCCESS
 9:  c2e65a5 =  9:  c2e65a5 Check if each named mail plugin DOES the mail plugin role
10:  a997949 = 10:  a997949 Return values of ApplyBeforeDecode plugins' GetCurrentUser are irrelevant
11:  588a509 = 11:  588a509 Push bounce short-circuiting down into _HandleMachineGeneratedMail
12:  1887b21 = 12:  1887b21 $IsALoop is now unused in Gateway
13:  314ad1b = 13:  314ad1b Stop moving RT-Squelch-Replies-To aside
14:  19607b9 = 14:  19607b9 Simplify _HandleMachineGeneratedMail logic
15:  531b96b = 15:  531b96b Use different method names rather than an ApplyBeforeDecode method
16:  70daad9 = 16:  70daad9 Use FAILURE to abort from GetCurrentUser, rather than a magic -1 value
17:  5a0942b = 17:  5a0942b Remove the unused $error variable
18:  8cabccc = 18:  8cabccc Move $Right to where it is used
19:  52e24c3 = 19:  52e24c3 Move SystemTicket definition to where it is first used
20:  6f62839 = 20:  6f62839 Move NewSubject to where it is used
21:  6d715aa = 21:  6d715aa Remove CreateUser, merging to form a more featureful LoadOrCreateByEmail
22:  e9e5e8b = 22:  e9e5e8b Always create the user; this simplifies ACL checking greatly
23:  e82d433 = 23:  e82d433 Split authentication from authorization
24:  d1c4c8b = 24:  d1c4c8b Remove no-longer-used _NoAuthorizedUserFound
25:  afadc73 = 25:  afadc73 Remove now-unused $Right variable, previously used by _NoAuthorizedUserFound
26:  73f1c62 = 26:  73f1c62 Fail if the first action is unauthenticated
27:  a5fc795 = 27:  a5fc795 Notify the owner on common mis-configurations
28:  6163947 = 28:  6163947 Remove extra error in mail-gateway
29:  87b474c = 29:  87b474c Add back a warning that is now lacking
30:  c9d8ab4 = 30:  c9d8ab4 Stop passing mail plugins around; load them lazily in one Plugins() method
31:  60d8040 = 31:  60d8040 Split action handling into plugin classes
32:  b707acb = 32:  b707acb It is possible that plugins will alter @actions; ensure that we have a valid action before calling it
33:  82c43c3 = 33:  82c43c3 Split default authentication from default authorization
34:  3430b59 = 34:  3430b59 Local'ize MailErrors to avoid having to pass $ErrorsTo everywhere
35:  a3b032a = 35:  a3b032a Remove the warning about the deprecated Auth::GnuPG/Auth::SMIME plugins
36:  8127768 = 36:  8127768 Allow lazy adding of Auth::MailFrom if no other GetCurrentUser plugins exist
37:  dae5c31 = 37:  dae5c31 There is no reason to not always enable Auth::Crypt
38:  3c0d075 = 38:  3c0d075 Make Crypt not an Auth:: plugin, but hardcoded
39:  ddd76e6 = 39:  ddd76e6 Move RejectOnUnencrypted to being a mail plugin
40:  7df59ef = 40:  7df59ef Merge ParseAddressFromHeader and RT::EmailParser->ParseEmailAddress
41:  0910b6f = 41:  0910b6f Fix callsites of ParseSenderAddressFromHead to be slightly less incomprehensible
42:  6b3c173 = 42:  6b3c173 $MessageId is only used in IsMachineGeneratedMail; move it in there
43:  48a5394 = 43:  48a5394 Merge CheckForSuspiciousSender, CheckForAutoGenerated, and CheckForBounce
44:  e211446 = 44:  e211446 Reduce repetition by making MailError handle throwing the FAILURE, as well
45:  2f7826f = 45:  2f7826f Move ACL checking for Take and Resolve into their own plugins
46:  d4dd6ec = 46:  d4dd6ec Update POD for new methods and functionality
47:  b020c8f = 47:  b020c8f Add pointers to SUCCESS/FAILURE/TMPFAIL in "writing mail plugins" docs
48:  bb657e9 = 48:  bb657e9 simple test for multiple reply-to addresses
49:  bb9337c ! 49:  395e0ca take into account multiple sender's addresses
    @@ -18,7 +18,11 @@
              RawMessageRef => \$args{message},
              Ticket        => $SystemTicket,
     @@
    -     CheckACL(
    + 
    +     # We only care about ACLs on the _first_ action, as later actions
    +     # may have gotten rights by the time they happen.
    +-    CheckACL(
    ++    my $CurrentUser = CheckACL(
              Action        => $actions[0],
              Message       => $Message,
     -        CurrentUser   => $CurrentUser,
    @@ -26,12 +30,6 @@
              Ticket        => $SystemTicket,
              Queue         => $SystemQueueObj,
          );
    - 
    --    my $Ticket = RT::Ticket->new($CurrentUser);
    -+    my $Ticket = RT::Ticket->new($CurrentUsers[0]);
    -     $Ticket->Load( $SystemTicket->Id );
    - 
    -     for my $action (@actions) {
     @@
      
      Dispatches to the C<@MailPlugins> to find one the provides
    @@ -43,11 +41,11 @@
      
      The default GetCurrentUser authenticator simply looks at the From:
     -address, and loads or creates a user accordingly; see
    -+address, and loads users or creates a user accordingly; see
    ++address, and loads or creates users accordingly; see
      L<RT::Interface::Email::Auth::MailFrom>.
      
     -Returns the current user; on failure of any plugin to do so, stops
    -+Returns a current user list; on failure of any plugin to do so, stops
    ++Returns a list of possible CurrentUsers; on failure of any plugin to do so, stops
      processing with a permanent failure and sends a generic "Permission
      Denied" mail to the user.
      
    @@ -72,7 +70,7 @@
      }
      
     -=head3 CheckACL Action => C<action>, CurrentUser => C<user>, Ticket => C<ticket>, Queue => C<queue>
    -+=head3 CheckACL Action => C<action>, CurrentUser => [C<user>], Ticket => C<ticket>, Queue => C<queue>
    ++=head3 CheckACL Action => C<action>, CurrentUser => [C<user>] or C<user>, Ticket => C<ticket>, Queue => C<queue>
      
     -Checks that the currentuser can perform a particular action.  While RT's
     +Checks that the currentusers can perform a particular action.  While RT's
    @@ -80,30 +78,32 @@
      or more limited restrictions on the email gateway.
      
     @@
    -         @_,
    -     );
    - 
    --    for my $Code ( Plugins( Method => "CheckACL" ) ) {
    + Aborts processing, sending a "Permission Denied" mail to the user with
    + the last plugin's failure message, on failure.
    + 
    ++Returns the first user that passed the check.
    ++
    + =cut
    + 
    + sub CheckACL {
    +@@
    +     );
    + 
    +     for my $Code ( Plugins( Method => "CheckACL" ) ) {
     -        return if $Code->(
     -            Message       => $args{Message},
     -            CurrentUser   => $args{CurrentUser},
     -            Action        => $args{Action},
     -            Ticket        => $args{Ticket},
     -            Queue         => $args{Queue},
    --        );
    -+    while ( @{ $args{CurrentUser} } ) {
    -+        my $CurrentUser = $args{CurrentUser}->[0];
    -+        for my $Code ( Plugins( Method => "CheckACL" ) ) {
    -+            return
    -+              if $Code->(
    -+                Message     => $args{Message},
    -+                CurrentUser => $CurrentUser,
    -+                Action      => $args{Action},
    -+                Ticket      => $args{Ticket},
    -+                Queue       => $args{Queue},
    -+              );
    -+        }
    -+        shift @{$args{CurrentUser}};
    ++        my $CurrentUser = $Code->(
    ++            Message     => $args{Message},
    ++            CurrentUser => $args{CurrentUser},
    ++            Action      => $args{Action},
    ++            Ticket      => $args{Ticket},
    ++            Queue       => $args{Queue},
    +         );
    ++        return $CurrentUser if $CurrentUser;
          }
      
          # Nobody said yes, and nobody said FAILURE; fail closed
    @@ -123,6 +123,7 @@
     +=head2 ParseSenderAddressesFromHead HEAD
     +
     +Takes a MIME::Header object. Returns ([list of addreses], errors)
    ++where the addresses are found in C<Reply-To>, C<From> and C<Sender>.
     +
     +=cut
     +
    @@ -130,22 +131,81 @@
          my $head = shift;
          my @errors;  # Accumulate any errors
      
    ++    my @addr;
          foreach my $header ( 'Reply-To', 'From', 'Sender' ) {
              my $addr_line = $head->get($header) || next;
     -        my ($addr) = RT::EmailParser->ParseEmailAddress( $addr_line );
     -        return ($addr->address, $addr->phrase, @errors) if $addr;
    -+        my (@addr) = RT::EmailParser->ParseEmailAddress( $addr_line );
    -+        return (\@addr, @errors) if @addr;
    - 
    -         chomp $addr_line;
    -         push @errors, "$header: $addr_line";
    ++        push @addr, RT::EmailParser->ParseEmailAddress( $addr_line );
    + 
    +-        chomp $addr_line;
    +-        push @errors, "$header: $addr_line";
    ++        unless ( @addr ) {
    ++            chomp $addr_line;
    ++            push @errors, "$header: $addr_line";
    ++        }
          }
      
     -    return (undef, undef, @errors);
    ++    return (\@addr, @errors) if @addr;
     +    return (undef, @errors);
      }
      
      =head3 ParseErrorsToAddressFromHead HEAD
    +
    +diff --git a/lib/RT/Interface/Email/Action/Resolve.pm b/lib/RT/Interface/Email/Action/Resolve.pm
    +--- a/lib/RT/Interface/Email/Action/Resolve.pm
    ++++ b/lib/RT/Interface/Email/Action/Resolve.pm
    +@@
    +         );
    +     }
    + 
    +-    my $principal = $args{CurrentUser}->PrincipalObj;
    +-    return 1 if $principal->HasRight( Object => $args{'Ticket'}, Right  => 'ModifyTicket' );
    +-
    +-    my $email = $args{CurrentUser}->UserObj->EmailAddress;
    ++    my @emails;
    ++    for my $CurrentUser ( ref $args{CurrentUser} eq 'ARRAY' ? @{ $args{CurrentUser} } : $args{CurrentUser} ) {
    ++        my $principal = $CurrentUser->PrincipalObj;
    ++        return $CurrentUser if $principal->HasRight( Object => $args{'Ticket'}, Right => 'ModifyTicket' );
    ++        push @emails, $CurrentUser->UserObj->EmailAddress;
    ++    }
    +     my $qname = $args{Queue}->Name;
    +     my $tid   = $args{Ticket}->id;
    +     MailError(
    +         Subject     => "Permission Denied",
    +-        Explanation => "$email has no right to own ticket $tid in queue $qname",
    ++        Explanation => (@emails == 1 ? "@emails has" : join(", ", @emails) . " have") . " no right to own ticket $tid in queue $qname",
    +         FAILURE     => 1,
    +     );
    + }
    +
    +diff --git a/lib/RT/Interface/Email/Action/Take.pm b/lib/RT/Interface/Email/Action/Take.pm
    +--- a/lib/RT/Interface/Email/Action/Take.pm
    ++++ b/lib/RT/Interface/Email/Action/Take.pm
    +@@
    +         );
    +     }
    + 
    +-    my $principal = $args{CurrentUser}->PrincipalObj;
    +-    return 1 if $principal->HasRight( Object => $args{'Ticket'}, Right  => 'OwnTicket' );
    ++    my @emails;
    ++    for my $CurrentUser ( ref $args{CurrentUser} eq 'ARRAY' ? @{ $args{CurrentUser} } : $args{CurrentUser} ) {
    ++        my $principal = $CurrentUser->PrincipalObj;
    ++        return $CurrentUser if $principal->HasRight( Object => $args{'Ticket'}, Right  => 'OwnTicket' );
    ++        push @emails, $CurrentUser->UserObj->EmailAddress;
    ++    }
    + 
    +-    my $email = $args{CurrentUser}->UserObj->EmailAddress;
    +     my $qname = $args{Queue}->Name;
    +     my $tid   = $args{Ticket}->id;
    +     MailError(
    +         Subject     => "Permission Denied",
    +-        Explanation => "$email has no right to own ticket $tid in queue $qname",
    ++        Explanation => (@emails == 1 ? "@emails has" : join(", ", @emails) . " have") . " no right to own ticket $tid in queue $qname",
    +         FAILURE     => 1,
    +     );
    + }
     
     diff --git a/lib/RT/Interface/Email/Auth/MailFrom.pm b/lib/RT/Interface/Email/Auth/MailFrom.pm
     --- a/lib/RT/Interface/Email/Auth/MailFrom.pm
    @@ -159,9 +219,8 @@
     -checking of the identity of the user, and trusts the headers of the
     -incoming email.
     +This plugin reads addresses found in the C<Reply-To>, C<From>, and C<Sender>
    -+headers, and loads users or creates a new user for the first address. It
    -+performs no checking of the identity of the user, and trusts the headers of
    -+the incoming email.
    ++headers, and loads or creates users accordingly. It performs no checking of
    ++the identity of the users, and trusts the headers of the incoming email.
      
      =cut
      
    @@ -194,26 +253,21 @@
     +        my $CurrentUser = RT::CurrentUser->new;
     +        $CurrentUser->LoadByEmail( $addr->address );
     +        $CurrentUser->LoadByName( $addr->address ) unless $CurrentUser->Id;
    -+        if ( $CurrentUser->Id ) {
    -+            $RT::Logger->debug("$addr belongs to user #". $CurrentUser->Id );
    -+            push @CurrentUsers, $CurrentUser;
    -+        }
    -     }
    - 
    -+    unless ( @CurrentUsers ) {
    -+        my $first_addr = $addresses->[ 0 ];
    -+        my $user       = RT::User->new( RT->SystemUser );
    -+        $user->LoadOrCreateByEmail(
    -+            RealName     => $first_addr->phrase,
    -+            EmailAddress => $first_addr->address,
    -+            Comments     => 'Autocreated on ticket submission',
    -+        );
    -+
    -+        my $CurrentUser = RT::CurrentUser->new;
    -+        $CurrentUser->Load( $user->id );
    ++        unless ( $CurrentUser->Id ) {
    ++            my $user = RT::User->new( RT->SystemUser );
    ++            $user->LoadOrCreateByEmail(
    ++                RealName     => $addr->phrase,
    ++                EmailAddress => $addr->address,
    ++                Comments     => 'Autocreated on ticket submission',
    ++            );
    ++
    ++            $CurrentUser = RT::CurrentUser->new;
    ++            $CurrentUser->Load( $user->id );
    ++        }
     +        push @CurrentUsers, $CurrentUser;
    -+    }
    - 
    +     }
    + 
    +-
     -    my $user = RT::User->new( RT->SystemUser );
     -    $user->LoadOrCreateByEmail(
     -        RealName     => $Name,
    @@ -229,3 +283,91 @@
      }
      
      1;
    +
    +diff --git a/lib/RT/Interface/Email/Authz/Default.pm b/lib/RT/Interface/Email/Authz/Default.pm
    +--- a/lib/RT/Interface/Email/Authz/Default.pm
    ++++ b/lib/RT/Interface/Email/Authz/Default.pm
    +@@
    +         @_,
    +     );
    + 
    +-    my $principal = $args{CurrentUser}->PrincipalObj;
    +-    my $email     = $args{CurrentUser}->UserObj->EmailAddress;
    +-    my $qname     = $args{'Queue'}->Name;
    ++    my @emails;
    ++    for my $CurrentUser ( ref $args{CurrentUser} eq 'ARRAY' ? @{ $args{CurrentUser} } : $args{CurrentUser} ) {
    ++        my $principal = $CurrentUser->PrincipalObj;
    ++        push @emails, $CurrentUser->UserObj->EmailAddress;
    ++
    ++        if ( $args{'Ticket'} && $args{'Ticket'}->Id ) {
    ++            if ( $args{'Action'} =~ /^comment$/i ) {
    ++                return $CurrentUser if $principal->HasRight( Object => $args{'Ticket'}, Right => 'CommentOnTicket' );
    ++            }
    ++            elsif ( $args{'Action'} =~ /^correspond$/i ) {
    ++                return $CurrentUser if $principal->HasRight( Object => $args{'Ticket'}, Right => 'ReplyToTicket' );
    ++            }
    ++            else {
    ++                $RT::Logger->warning("Action '". ($args{'Action'}||'') ."' is unknown");
    ++                return;
    ++            }
    ++        }
    ++
    ++        # We're creating a ticket
    ++        elsif ( $args{'Action'} =~ /^(comment|correspond)$/i ) {
    ++            return $CurrentUser if $principal->HasRight( Object => $args{'Queue'}, Right => 'CreateTicket' );
    ++        }
    ++        else {
    ++            $RT::Logger->warning( "Action '" . ( $args{'Action'} || '' ) . "' is unknown with no ticket" );
    ++            return;
    ++        }
    ++    }
    + 
    +     my $msg;
    ++    my $email = join ", ", @emails;
    ++    my $qname = $args{'Queue'}->Name;
    +     if ( $args{'Ticket'} && $args{'Ticket'}->Id ) {
    +-        my $tid   = $args{'Ticket'}->id;
    ++        my $tid = $args{'Ticket'}->id;
    + 
    +         if ( $args{'Action'} =~ /^comment$/i ) {
    +-            return 1 if $principal->HasRight( Object => $args{'Ticket'}, Right => 'CommentOnTicket' );
    +-            $msg = "$email has no right to comment on ticket $tid in queue $qname";
    ++            $msg = (@emails ? "$email has" : "$email have") . " no right to comment on ticket $tid in queue $qname";
    +         }
    +         elsif ( $args{'Action'} =~ /^correspond$/i ) {
    +-            return 1 if $principal->HasRight( Object => $args{'Ticket'}, Right  => 'ReplyToTicket' );
    +-            $msg = "$email has no right to reply to ticket $tid in queue $qname";
    ++            $msg = (@emails ? "$email has" : "$email have") . " no right to reply to ticket $tid in queue $qname";
    + 
    +             # Also notify the owner
    +             MailError(
    +@@
    + EOT
    +             );
    +         }
    +-        else {
    +-            $RT::Logger->warning("Action '". ($args{'Action'}||'') ."' is unknown");
    +-            return;
    +-        }
    +     }
    +-
    +     # We're creating a ticket
    +     elsif ( $args{'Action'} =~ /^(comment|correspond)$/i ) {
    +-        return 1 if $principal->HasRight( Object => $args{'Queue'}, Right  => 'CreateTicket' );
    +-        $msg = "$email has no right to create tickets in queue $qname";
    ++        $msg = (@emails ? "$email has" : "$email have") . " no right to create tickets in queue $qname";
    + 
    +         # Also notify the owner
    +         MailError(
    +@@
    + EOT
    +         );
    +     }
    +-    else {
    +-        $RT::Logger->warning("Action '". ($args{'Action'}||'') ."' is unknown with no ticket");
    +-        return;
    +-    }
    +-
    + 
    +     MailError(
    +         Subject     => "Permission Denied",



More information about the rt-commit mailing list