[Rt-commit] r3094 - in rt/branches/3.4-RELEASE: . bin html/REST/1.0/NoAuth lib/RT/Interface lib/RT/Interface/Email/Auth lib/t/regression

kevinr at bestpractical.com kevinr at bestpractical.com
Wed Jun 8 18:44:40 EDT 2005


Author: kevinr
Date: Wed Jun  8 18:44:39 2005
New Revision: 3094

Modified:
   rt/branches/3.4-RELEASE/   (props changed)
   rt/branches/3.4-RELEASE/bin/rt-mailgate.in
   rt/branches/3.4-RELEASE/html/REST/1.0/NoAuth/mail-gateway
   rt/branches/3.4-RELEASE/lib/RT/Interface/Email.pm
   rt/branches/3.4-RELEASE/lib/RT/Interface/Email/Auth/MailFrom.pm
   rt/branches/3.4-RELEASE/lib/t/regression/06mailgateway.t
Log:
 r4080 at sad-girl-in-snow:  kevinr | 2005-06-08 18:35:07 -0400
 * Applied Ruslan Zakirov's ext-mailgate patch, which allows you to take or 
 resolve tickets by e-mail.


Modified: rt/branches/3.4-RELEASE/bin/rt-mailgate.in
==============================================================================
--- rt/branches/3.4-RELEASE/bin/rt-mailgate.in	(original)
+++ rt/branches/3.4-RELEASE/bin/rt-mailgate.in	Wed Jun  8 18:44:39 2005
@@ -72,7 +72,6 @@
     die "$0 invoked improperly\n\nNo $_ provided to mail gateway!\n" unless $opts{$_};
 }
 
-undef $/;
 my $ua      = LWP::UserAgent->new();
 $ua->cookie_jar( { file => $opts{jar} } );
 
@@ -83,7 +82,7 @@
 );
 
 # Read the message in from STDIN
-$args{'message'} = <>;
+$args{'message'} = do { local (@ARGV, $/); <> };
 
 unless ( $args{message} =~ /\S/ ) {
     print STDERR "$0: no message passed on STDIN!\n";
@@ -156,7 +155,7 @@
 
 Usual invocation (from MTA):
 
-    rt-mailgate --action (correspond|comment) --queue queuename
+    rt-mailgate --action (correspond|comment|...) --queue queuename
                 --url http://your.rt.server/
                 [ --debug ]
                 [ --extension (queue|action|ticket) ]
@@ -172,7 +171,16 @@
 
 =item C<--action>
 
-Specifies whether this is a correspondence or comment address.
+Specifies what action this would be.
+Basic actions: C<correspond>, C<comment>, C<take> and C<resolve>.
+Also you can use two or more actions with C<-> separated list,
+for example you can use C<take-comment> or C<correspond-resolve> actions.
+
+Note that C<take> and C<resolve> actions ignore message text if use them
+alone, so use with C<comment> or C<correspond> actions if you want RT
+write message.
+
+Default action is C<correspond>.
 
 =item C<--queue>
 

Modified: rt/branches/3.4-RELEASE/html/REST/1.0/NoAuth/mail-gateway
==============================================================================
--- rt/branches/3.4-RELEASE/html/REST/1.0/NoAuth/mail-gateway	(original)
+++ rt/branches/3.4-RELEASE/html/REST/1.0/NoAuth/mail-gateway	Wed Jun  8 18:44:39 2005
@@ -47,7 +47,6 @@
 inherit => undef # inhibit UTF8 conversion done in /autohandler
 </%flags>
 <%ARGS>
-$message
 $queue => 1
 $action => "correspond"
 $ticket => undef

Modified: rt/branches/3.4-RELEASE/lib/RT/Interface/Email.pm
==============================================================================
--- rt/branches/3.4-RELEASE/lib/RT/Interface/Email.pm	(original)
+++ rt/branches/3.4-RELEASE/lib/RT/Interface/Email.pm	Wed Jun  8 18:44:39 2005
@@ -182,7 +182,7 @@
 =cut
 
 sub IsRTAddress {
-    my $address = shift;
+    my $address = shift || '';
 
     # Example: the following rule would tell RT not to Cc 
     #   "tickets at noc.example.com"
@@ -206,13 +206,7 @@
 =cut
 
 sub CullRTAddresses {
-    my @addresses = (@_);
-    my @addrlist;
-
-    foreach my $addr( @addresses ) {
-      push (@addrlist, $addr) unless IsRTAddress($addr);
-    }
-    return (@addrlist);
+    return (grep { IsRTAddress($_) } @_);
 }
 
 # }}}
@@ -498,14 +492,15 @@
     my %args = %$argsref;
 
     # Set some reasonable defaults
-    $args{'action'} = 'correspond' unless ( $args{'action'} );
-    $args{'queue'}  = '1'          unless ( $args{'queue'} );
+    $args{'action'} ||= 'correspond';
+    $args{'queue'}  ||= '1';
 
     # Validate the action
-    unless ( $args{'action'} =~ /^(comment|correspond|action)$/ ) {
+    my ($status, @actions) = IsCorrectAction( $args{'action'} );
+    unless ( $status ) {
 
         # Can't safely loc this. What object do we loc around?
-        $RT::Logger->crit("Mail gateway called with an invalid action paramenter '".$args{'action'}."' for queue '".$args{'queue'}."'");
+        $RT::Logger->crit("Mail gateway called with an invalid action paramenter '".$actions[0]."' for queue '".$args{'queue'}."'");
 
         return ( -75, "Invalid 'action' parameter", undef );
     }
@@ -528,7 +523,7 @@
     my $Message = $parser->Entity();
     my $head    = $Message->head;
 
-    my ( $CurrentUser, $AuthStat, $status, $error );
+    my ( $CurrentUser, $AuthStat, $error );
 
     # Initalize AuthStat so comparisons work correctly
     $AuthStat = -9999999;
@@ -592,22 +587,28 @@
             }
         }
 
-        ( $CurrentUser, $NewAuthStat ) = $Code->(
-            Message     => $Message,
-            RawMessageRef => \$args{'message'},
-            CurrentUser => $CurrentUser,
-            AuthLevel   => $AuthStat,
-            Action      => $args{'action'},
-            Ticket      => $SystemTicket,
-            Queue       => $SystemQueueObj
-        );
+	foreach my $action ( @actions ) {
+
+            ( $CurrentUser, $NewAuthStat ) = $Code->(
+                Message     => $Message,
+                RawMessageRef => \$args{'message'},
+                CurrentUser => $CurrentUser,
+                AuthLevel   => $AuthStat,
+                Action      => $action,
+                Ticket      => $SystemTicket,
+                Queue       => $SystemQueueObj
+            );
+
 
+            # If a module returns a "-1" then we discard the ticket, so.
+            $AuthStat = -1 if $NewAuthStat == -1;
 
-        # If a module returns a "-1" then we discard the ticket, so.
-        $AuthStat = -1 if $NewAuthStat == -1;
+            # You get the highest level of authentication you were assigned.
+            $AuthStat = $NewAuthStat if $NewAuthStat > $AuthStat;
+
+            last if $AuthStat == -1;
+	}
 
-        # You get the highest level of authentication you were assigned.
-        $AuthStat = $NewAuthStat if $NewAuthStat > $AuthStat;
         last if $AuthStat == -1;
     }
 
@@ -730,7 +731,8 @@
     my $Ticket = RT::Ticket->new($CurrentUser);
 
     # {{{ If we don't have a ticket Id, we're creating a new ticket
-    if ( !$SystemTicket || !$SystemTicket->Id) {
+    if ( (!$SystemTicket || !$SystemTicket->Id) && 
+           grep /^(comment|correspond)$/, @actions ) {
 
         # {{{ Create a new ticket
 
@@ -762,74 +764,115 @@
             $RT::Logger->error("Create failed: $id / $Transaction / $ErrStr ");
             return ( 0, "Ticket creation failed", $Ticket );
         }
+	# strip comments&corresponds from the actions we don't need record twice
+	@actions = grep !/^(comment|correspond)$/, @actions;
+	$args{'ticket'} = $id;
 
         # }}}
     }
 
-    # }}}
-
-    #   If the action is comment, add a comment.
-    elsif ( $args{'action'} =~ /^(comment|correspond)$/i ) {
-        $Ticket->Load( $args{'ticket'} );
-        unless ( $Ticket->Id ) {
-            my $message = "Could not find a ticket with id " . $args{'ticket'};
-            MailError(
-                To          => $ErrorsTo,
-                Subject     => "Message not recorded",
-                Explanation => $message,
-                MIMEObj     => $Message
-            );
+    $Ticket->Load( $args{'ticket'} );
+    unless ( $Ticket->Id ) {
+        my $message = "Could not find a ticket with id " . $args{'ticket'};
+        MailError(
+            To          => $ErrorsTo,
+            Subject     => "Message not recorded",
+            Explanation => $message,
+            MIMEObj     => $Message
+        );
+    
+        return ( 0, $message );
+    }
 
-            return ( 0, $message );
+    # }}}
+    foreach my $action( @actions ) {
+        #   If the action is comment, add a comment.
+        if ( $action =~ /^(comment|correspond)$/i ) {
+            my ( $status, $msg );
+            if ( $action =~ /^correspond$/i ) {
+                ( $status, $msg ) = $Ticket->Correspond( MIMEObj => $Message );
+            }
+            else {
+                ( $status, $msg ) = $Ticket->Comment( MIMEObj => $Message );
+            }
+            unless ($status) {
+    
+                #Warn the sender that we couldn't actually submit the comment.
+                MailError(
+                    To          => $ErrorsTo,
+                    Subject     => "Message not recorded",
+                    Explanation => $msg,
+                    MIMEObj     => $Message
+                );
+                return ( 0, "Message not recorded", $Ticket );
+            }
         }
-
-        my ( $status, $msg );
-        if ( $args{'action'} =~ /^correspond$/ ) {
-            ( $status, $msg ) = $Ticket->Correspond( MIMEObj => $Message );
+        elsif ( $action =~ /^take$/i ) {
+            my ( $status, $msg ) = $Ticket->SetOwner( $CurrentUser->id );
+            unless ($status) {
+    
+                #Warn the sender that we couldn't actually submit the comment.
+                MailError(
+                    To          => $ErrorsTo,
+                    Subject     => "Ticket not taken",
+                    Explanation => $msg,
+                    MIMEObj     => $Message
+                );
+                return ( 0, "Ticket not taken", $Ticket );
+            }
         }
-        else {
-            ( $status, $msg ) = $Ticket->Comment( MIMEObj => $Message );
+        elsif ( $action =~ /^resolve$/i ) {
+            my ( $status, $msg ) = $Ticket->SetStatus( 'resolved' );
+            unless ($status) {
+                #Warn the sender that we couldn't actually submit the comment.
+                MailError(
+                    To          => $ErrorsTo,
+                    Subject     => "Ticket not resolved",
+                    Explanation => $msg,
+                    MIMEObj     => $Message
+                );
+                return ( 0, "Ticket not resolved", $Ticket );
+            }
         }
-        unless ($status) {
-
-            #Warn the sender that we couldn't actually submit the comment.
+    
+        else {
+    
+            #Return mail to the sender with an error
             MailError(
                 To          => $ErrorsTo,
-                Subject     => "Message not recorded",
-                Explanation => $msg,
-                MIMEObj     => $Message
+                Subject     => "RT Configuration error",
+                Explanation => "'"
+                  . $args{'action'}
+                  . "' not a recognized action."
+                  . " Your RT administrator has misconfigured "
+                  . "the mail aliases which invoke RT",
+                MIMEObj => $Message
+            );
+            $RT::Logger->crit( $args{'action'} . " type unknown for $MessageId" );
+            return (
+                -75,
+                "Configuration error: "
+                  . $args{'action'}
+                  . " not a recognized action",
+                $Ticket
             );
-            return ( 0, "Message not recorded", $Ticket );
+    
         }
     }
 
-    else {
-
-        #Return mail to the sender with an error
-        MailError(
-            To          => $ErrorsTo,
-            Subject     => "RT Configuration error",
-            Explanation => "'"
-              . $args{'action'}
-              . "' not a recognized action."
-              . " Your RT administrator has misconfigured "
-              . "the mail aliases which invoke RT",
-            MIMEObj => $Message
-        );
-        $RT::Logger->crit( $args{'action'} . " type unknown for $MessageId" );
-        return (
-            -75,
-            "Configuration error: "
-              . $args{'action'}
-              . " not a recognized action",
-            $Ticket
-        );
-
-    }
-
     return ( 1, "Success", $Ticket );
 }
 
+sub IsCorrectAction
+{
+	my $action = shift;
+	my @actions = split /-/, $action;
+	foreach ( @actions ) {
+		return (0, $_) unless /^(?:comment|correspond|take|resolve)$/;
+	}
+	return (1, @actions);
+}
+
 
 eval "require RT::Interface::Email_Vendor";
 die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email_Vendor.pm});

Modified: rt/branches/3.4-RELEASE/lib/RT/Interface/Email/Auth/MailFrom.pm
==============================================================================
--- rt/branches/3.4-RELEASE/lib/RT/Interface/Email/Auth/MailFrom.pm	(original)
+++ rt/branches/3.4-RELEASE/lib/RT/Interface/Email/Auth/MailFrom.pm	Wed Jun  8 18:44:39 2005
@@ -122,6 +122,36 @@
             }
 
         }
+        elsif ( $args{'Action'} =~ /^take$/i ) {
+
+            # check to see whether "Everybody" or "Unprivileged users" can correspond on tickets
+            unless ( $everyone->PrincipalObj->HasRight(Object => $args{'Queue'},
+                                                       Right  => 'OwnTicket'
+                     )
+                     || $unpriv->PrincipalObj->HasRight(
+                                                       Object => $args{'Queue'},
+                                                       Right  => 'OwnTicket'
+                     )
+              ) {
+                return ( $args{'CurrentUser'}, 0 );
+            }
+
+        }
+        elsif ( $args{'Action'} =~ /^resolve$/i ) {
+
+            # check to see whether "Everybody" or "Unprivileged users" can correspond on tickets
+            unless ( $everyone->PrincipalObj->HasRight(Object => $args{'Queue'},
+                                                       Right  => 'ModifyTicket'
+                     )
+                     || $unpriv->PrincipalObj->HasRight(
+                                                       Object => $args{'Queue'},
+                                                       Right  => 'ModifyTicket'
+                     )
+              ) {
+                return ( $args{'CurrentUser'}, 0 );
+            }
+
+        }
         else {
             return ( $args{'CurrentUser'}, 0 );
         }

Modified: rt/branches/3.4-RELEASE/lib/t/regression/06mailgateway.t
==============================================================================
--- rt/branches/3.4-RELEASE/lib/t/regression/06mailgateway.t	(original)
+++ rt/branches/3.4-RELEASE/lib/t/regression/06mailgateway.t	Wed Jun  8 18:44:39 2005
@@ -51,7 +51,8 @@
 
 =cut
 
-use Test::More qw/no_plan/;
+use strict;
+use Test::More tests => 77;
 use RT;
 RT::LoadConfig();
 RT::Init();
@@ -74,7 +75,7 @@
 
 # {{{ Test new ticket creation by root who is privileged and superuser
 
-ok(open(MAIL, "|$RT::BinPath/rt-mailgate  --debug --url $RT::WebURL --queue general --action correspond"), "Opened the mailgate - $@");
+ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $RT::WebURL --queue general --action correspond"), "Opened the mailgate - $@");
 print MAIL <<EOF;
 From: root\@localhost
 To: rt\@example.com
@@ -419,8 +420,75 @@
 ($val,$msg) = $g->PrincipalObj->RevokeRight(Right => 'CreateTicket');
 ok ($val, $msg);
 
+# {{{ Check take and resolve actions
 
-1;
+# create ticket that is owned by nobody
+use RT::Ticket;
+$tick = RT::Ticket->new($RT::SystemUser);
+my ($id) = $tick->Create( Queue => 'general', Subject => 'test');
+ok( $id, 'new ticket created' );
+is( $tick->Owner, $RT::Nobody->Id, 'owner of the new ticket is nobody' );
 
-1;
+ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $RT::WebURL --queue general --action take"), "Opened the mailgate - $@");
+print MAIL <<EOF;
+From: root\@localhost
+Subject: [example.com \#$id] test
+
+EOF
+close (MAIL);
+is ($? >> 8, 0, "The mail gateway exited normally");
+
+$tick = RT::Ticket->new($RT::SystemUser);
+$tick->Load( $id );
+is( $tick->Id, $id, 'load correct ticket');
+is( $tick->OwnerObj->EmailAddress, 'root at localhost', 'successfuly take ticket via email');
+
+# check that there is no text transactions writen
+is( $tick->Transactions->Count, 2, 'no superfluous transactions');
+
+my $status = '';
+($status, $msg) = $tick->SetOwner( $RT::Nobody->Id, 'Force' );
+ok( $status, 'successfuly changed owner: '. ($msg||'') );
+is( $tick->Owner, $RT::Nobody->Id, 'set owner back to nobody');
+
+
+ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $RT::WebURL --queue general --action take-correspond"), "Opened the mailgate - $@");
+print MAIL <<EOF;
+From: root\@localhost
+Subject: [example.com \#$id] correspondence
 
+test
+EOF
+close (MAIL);
+is ($? >> 8, 0, "The mail gateway exited normally");
+
+$tick = RT::Ticket->new($RT::SystemUser);
+$tick->Load( $id );
+is( $tick->Id, $id, 'load correct ticket');
+is( $tick->OwnerObj->EmailAddress, 'root at localhost', 'successfuly take ticket via email');
+my $txns = $tick->Transactions;
+$txns->Limit( FIELD => 'Type', VALUE => 'Correspond');
+is( $txns->Last->Subject, "[example.com \#$id] correspondence", 'successfuly add correspond within take via email' );
+# +1 because of auto open
+is( $tick->Transactions->Count, 6, 'no superfluous transactions');
+
+ok(open(MAIL, "|$RT::BinPath/rt-mailgate --url $RT::WebURL --queue general --action resolve"), "Opened the mailgate - $@");
+print MAIL <<EOF;
+From: root\@localhost
+Subject: [example.com \#$id] test
+
+EOF
+close (MAIL);
+is ($? >> 8, 0, "The mail gateway exited normally");
+
+DBIx::SearchBuilder::Record::Cachable->FlushCache;
+
+$tick = RT::Ticket->new($RT::SystemUser);
+$tick->Load( $id );
+is( $tick->Id, $id, 'load correct ticket');
+is( $tick->Status, 'resolved', 'successfuly resolved ticket via email');
+is( $tick->Transactions->Count, 7, 'no superfluous transactions');
+
+# }}}
+
+1;


More information about the Rt-commit mailing list