[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