[rt-devel] rt3 enhanced-mailgate patch

Matthew J. Draper matthewd at staff.airnet.com.au
Sun Jun 8 12:43:29 EDT 2003


Hi!

Unfortunately, I haven't been reading the RT lists lately (lousy days
only having 24 hours! :), so apologies if someone has already posted
something similar to this...

I can almost guarantee it won't work for HTML email; I don't use HTML
mail, so I haven't tested it.

Basically, this will make your standard mailgate accept quasi-headers
like "Status: resolved" in the top of the body, up to the first blank
line. It also has some fairly rudimentary support for named custom
fields... Enough for me, but you may wish to extend it somewhat,
depending upon your requirements. 

I'm about 110% sure that this is not the best way to do what we're
doing, but it appears to work, and that's quite sufficient, as far as
I'm concerned.

I've put it through a full several minutes of testing, and deemed it
ready to roll into production... Anyone who significantly values their
RT installation may want to be a little more cautious. :)

The most significant thing you may wish to review would probably be the
changes to RT::Interface::Email::Auth::MailFrom, which just grant
everyone level '2' access, rather than level '1'. This shouldn't be an
issue, as, in all my tests so far, RT's permissions have still stopped
the user from successfully changing anything they shouldn't. The only
major disadvantage is that if a random person inadvertently puts
something like "status: foo" on the first line of their email, they'll
get back a nasty error message -- whereas they would not if they only
had level '1' authentication status.

Matthew

---

diff -bC3 Ticket_Overlay.pm Ticket_Local.pm
*** Ticket_Overlay.pm	Thu Jun  5 06:52:36 2003
--- Ticket_Local.pm	Mon Jun  9 01:26:36 2003
***************
*** 904,917 ****
  
      # die "updaterecordobject is a webui thingy";
      my @results;
  
      foreach my $attribute (@attribs) {
          my $value = $ticketargs{$attribute};
  
!         if ( $value ne $self->$attribute() ) {
  
              my $method = "Set$attribute";
              my ( $code, $msg ) = $self->$method($value);
  
              push @results, $self->loc($attribute) . ': ' . $msg;
  
--- 904,919 ----
  
      # die "updaterecordobject is a webui thingy";
      my @results;
+ 	my $ok = 1;
  
      foreach my $attribute (@attribs) {
          my $value = $ticketargs{$attribute};
  
!         if ( ( defined $value ) and ( $value ne $self->$attribute() )
) {
  
              my $method = "Set$attribute";
              my ( $code, $msg ) = $self->$method($value);
+             $ok = $code unless $ok < $code;
  
              push @results, $self->loc($attribute) . ': ' . $msg;
  
***************
*** 924,930 ****
          $ChownType = "Force" if ( $ticketargs{'ForceOwnerChange'} );
  
          my ( $val, $msg ) = $self->SetOwner( $ticketargs{'Owner'},
$ChownType );
!         push ( @results, $msg );
      }
  
      # }}}
--- 926,933 ----
          $ChownType = "Force" if ( $ticketargs{'ForceOwnerChange'} );
  
          my ( $val, $msg ) = $self->SetOwner( $ticketargs{'Owner'},
$ChownType );
!         push ( @results, $self->loc('Owner') . ': ' . $msg );
!         $ok = $val unless $ok < $val;
      }
  
      # }}}
***************
*** 940,959 ****
   
   foreach my $type qw(Requestor Cc AdminCc) {
  
!         # If we've been given a number of delresses to del, do it.
                  foreach my $address (@{$ticketargs{'Del'.$type}}) {
                  my ($id, $msg) = $self->DelWatcher( Type => $type,
Email => $address);
!                 push (@results, $msg) ;
                  }
  
          # If we've been given a number of addresses to add, do it.
                  foreach my $address (@{$ticketargs{'Add'.$type}}) {
                  $RT::Logger->debug("Adding $address as a $type");
                  my ($id, $msg) = $self->AddWatcher( Type => $type,
Email => $address);
!                 push (@results, $msg) ;
  
          }
  
  
  }
  
--- 943,999 ----
   
   foreach my $type qw(Requestor Cc AdminCc) {
  
!         # If we've been given a number of addresses to del, do it.
                  foreach my $address (@{$ticketargs{'Del'.$type}}) {
                  my ($id, $msg) = $self->DelWatcher( Type => $type,
Email => $address);
!                 push (@results, 'Delete ' . $type . ': ' . $msg) ;
!                 $ok = $id unless $ok < $id;
                  }
  
          # If we've been given a number of addresses to add, do it.
                  foreach my $address (@{$ticketargs{'Add'.$type}}) {
                  $RT::Logger->debug("Adding $address as a $type");
                  my ($id, $msg) = $self->AddWatcher( Type => $type,
Email => $address);
!                 push (@results, 'Add ' . $type . ': ' . $msg) ;
!                 $ok = $id unless $ok < $id;
  
          }
  
+         # Attempt to do custom fields
+         my $cfs = $self->QueueObj->CustomFields();
+         while (my $cf = $cfs->Next) {
+             my $name = lc($cf->Name);
+             $name =~ s/-//g;
+ 
+             foreach my $op ('clear', 'del', '', 'add') {
+                 if ( defined $args{$op . $name} ) {
+                     if ( $op eq 'clear' ) {
+                         my $vals = $self->CustomFieldValues($cf->id);
+                         while (my $val = $vals->Next) {
+                             my ($code, $msg) =
$self->DeleteCustomFieldValue( Field => $cf, Value => $val->Content );
+                             if ($ok > $code) {  # Only push the
message if it's affecting our return value, as this was an implicit
action
+                                 push ( @results, 'Clear ' . $cf->Name
. ': ' . $msg );
+                                 $ok = $code;
+                             }
+                         }
+                     }
+ 
+                     foreach my $entry ( ref($args{$op . $name}) ?
@{$args{$op . $name}} : ($args{$op . $name}) ) {
+                         if ($op eq 'del' or $entry eq 'undef') {
+                             my ($code, $msg) =
$self->DeleteCustomFieldValue( Field => $cf, Value => $entry );
+                             push ( @results, 'Delete ' . $cf->Name .
': ' . $msg );
+                             $ok = $code unless $ok < $code;
+                         } elsif ($entry ne 'undef') {
+                             my ($code, $msg) =
$self->AddCustomFieldValue( Field => $cf, Value => $entry );
+                             push ( @results, 'Add ' . $cf->Name . ': '
. $msg );
+                             $ok = $code unless $ok < $code;
+                         }
+                     }
+                 }
+             }
+         }
+ 
+         return ( $ok, join("\n", @results) );
  
  }
  
***************
*** 981,988 ****
              my $tag   = lc($1);
  
              $tag =~ s/-//g;
!             if ( defined( $args{$tag} ) )
!             {    #if we're about to get a second value, make it an
array
                  $args{$tag} = [ $args{$tag} ];
              }
              if ( ref( $args{$tag} ) )
--- 1021,1028 ----
              my $tag   = lc($1);
  
              $tag =~ s/-//g;
!             if ( defined( $args{$tag} ) and not ref( $args{$tag} ) )
!             {    #if we're about to get a second value, make it an
array (as long as it isn't already an array!)
                  $args{$tag} = [ $args{$tag} ];
              }
              if ( ref( $args{$tag} ) )


diff -bC3 Interface/Email.pm Interface/Email_Local.pm
*** Interface/Email.pm	Mon Jun  9 01:25:14 2003
--- Interface/Email_Local.pm	Mon Jun  9 01:47:15 2003
***************
*** 574,579 ****
--- 574,590 ----
              return ( 0, "Ticket creation failed", $Ticket );
          }
  
+ 		# enhanced-mailgate functionality
+ 		if ($AuthStat >= 2) {
+ 			my $newTicket = RT::Ticket->new($CurrentUser);
+ 			$newTicket->Load($id);
+ 			if ( $newTicket->Id ) {
+ 				my $body = $Message->body_as_string;
+ 				$body =~ s/\010\013/\n/g;
+ 				$Ticket->UpdateFrom822($body),
+ 			}
+ 		}
+ 
          # }}}
      }
  
***************
*** 599,612 ****
          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 );
          }
      }
  
--- 610,633 ----
          else {
              ( $status, $msg ) = $Ticket->Comment( MIMEObj => $Message
);
          }
+ 
+ 		# enhanced-mailgate functionality
+ 		my $errSubject = 'Message not recorded';
+ 		if ( ( $status ) and ( $AuthStat >= 2 ) ) {
+ 			$errSubject = 'Metadata changes not applied';
+ 			my $body = $Message->body_as_string;
+ 			$body =~ s/\010\013/\n/g;
+ 			( $status, $msg ) =
$Ticket->UpdateFrom822($body),
+ 		}
+ 
          unless ($status) {
  
              #Warn the sender that we couldn't actually submit the
comment.
              MailError( To          => $ErrorsTo,
!                        Subject     => $errSubject,
                         Explanation => $msg,
                         MIMEObj     => $Message );
!             return ( 0, $errSubject, $Ticket );
          }
      }
  
***************
*** 629,638 ****
  
  return ( 1, "Success", $Ticket );
  }
- 
- eval "require RT::Interface::Email_Vendor";
- die $@ if ($@ && $@ !~ qr{^Can't locate
RT/Interface/Email_Vendor.pm});
- eval "require RT::Interface::Email_Local";
- die $@ if ($@ && $@ !~ qr{^Can't locate RT/Interface/Email_Local.pm});
  
  1;
--- 650,654 ----


diff -bC3 Interface/Email/Auth/MailFrom.pm
Interface/Email/Auth/MailFrom_Local.pm
*** Interface/Email/Auth/MailFrom.pm	Thu Jun  5 06:52:36 2003
--- Interface/Email/Auth/MailFrom_Local.pm	Mon Jun  9 00:57:52 2003
***************
*** 45,51 ****
      }
  
      if ( $CurrentUser->Id ) {
!         return ( $CurrentUser, 1 );
      }
      
  
--- 45,51 ----
      }
  
      if ( $CurrentUser->Id ) {
!         return ( $CurrentUser, 2 );
      }
      
  
***************
*** 120,131 ****
  
      $CurrentUser = CreateUser( undef, $Address, $Name,
$args{'Message'} );
  
!     return ( $CurrentUser, 1 );
  }
- 
- eval "require RT::Interface::Email::Auth::MailFrom_Vendor";
- die $@ if ($@ && $@ !~ qr{^Can't locate
RT/Interface/Email/Auth/MailFrom_Vendor.pm});
- eval "require RT::Interface::Email::Auth::MailFrom_Local";
- die $@ if ($@ && $@ !~ qr{^Can't locate
RT/Interface/Email/Auth/MailFrom_Local.pm});
  
  1;
--- 120,126 ----
  
      $CurrentUser = CreateUser( undef, $Address, $Name,
$args{'Message'} );
  
!     return ( $CurrentUser, 2 );
  }
  
  1;



More information about the Rt-devel mailing list