[Rt-commit] rt branch, 4.4-trunk, updated. rt-4.4.1-84-g00f6d2e

Shawn Moore shawn at bestpractical.com
Wed Jul 20 13:32:30 EDT 2016


The branch, 4.4-trunk has been updated
       via  00f6d2e0fc383b2b8f0a97cc74b6d3685c4df9a4 (commit)
       via  0206ec7470b2995f1a909f946ffe4b158a2d3468 (commit)
       via  a457a44a89d7e16878ff9f545bdaac005a8ac730 (commit)
       via  6a2063b812b31bf47476a836abc5e84e4c3e49be (commit)
       via  03290531c157f9a26a73bc2c915e672c12e2ed80 (commit)
       via  e588dbcf58ead4345ffb6f95fec8be3b01ccf173 (commit)
       via  a7342b463fd88bf354678edc0c144cee9804fcbe (commit)
       via  564b9de7f3d9610fcdb3d0a46e63044623bc05d7 (commit)
       via  8e6309999c44313baafc0472e6cc6889976d5412 (commit)
       via  ac152958c6475fdbb067a031e13fe7efeec37bad (commit)
       via  5d01baa9207ac93e02a7078c5da777f3d7805389 (commit)
       via  fce4f0831afd4ea8c7f82bfed105db876407675e (commit)
       via  0a408adb24ada26229bea91f6b08a13258e0d2dc (commit)
       via  7d6f9d6b408efa4c767fecf3418c04e267db0acf (commit)
       via  1e9287ae1dd235b9426524c00cebe7898251db46 (commit)
       via  037839bc7e05a3fcaa9bd9bf9e8efb0d06f9549b (commit)
       via  aea531f3f5383a53b3ef8114b501b75c7fa7e84e (commit)
       via  a8b281e18e04197f2ac7206129d7fba26e44ae8a (commit)
       via  a8bf0f391208c8429feb66fad34dcd71f16d47a5 (commit)
       via  1bf5be6a07cd1c72b7a95e4898da698860c41a87 (commit)
       via  5cb918e1eefe00f76cc3cddc45955e07aad77dfd (commit)
       via  4e7e6522f946518c570956af66eb3e4dc8372a42 (commit)
       via  8af43727056536676d481c56a72320c7399b9987 (commit)
       via  b4d8eb4de5d063ed34a5bd9b769309190f63e401 (commit)
       via  ef97ff148ce80aa3002c1d28711a57c172df3b35 (commit)
       via  c050da1e30cefe841a528114429a9656c1c1ac32 (commit)
       via  973e702f46a5ca6e612a9354da6588579df453d2 (commit)
       via  f591697117e5bccc26732e6d82325ab27746cf9e (commit)
       via  bd44290c51ba1a0cc5381e9b71525987ff6878d0 (commit)
       via  41292a38961bb617aca432039ac5ef69c4674497 (commit)
       via  a92e8587388065b4a3874fc7bc6bbf8de73641bc (commit)
       via  a4f66b1a1f9698ca9c735c22bb131689b37c555a (commit)
       via  3e98fa121833ba8bccc5d292f7143b51a205fe5e (commit)
       via  f2be6f6234be12de5ebe99ccdd56a4b09c46b241 (commit)
       via  ab169c273aa112092ff99bbae69cec406868562a (commit)
       via  e5e5e3d026d9cb90d4a1b2487809dd2e7e1c42c2 (commit)
       via  be78dc8a29ff7bad70a5be2927b0371e1161b2a4 (commit)
       via  1cac7d3a64b1b3513610069f7b3895e359585475 (commit)
       via  3b8ae5b6697ffd26734c9db46b30002af9460193 (commit)
       via  50dea853e373a5c3d3fafe3f201d8b726fda1099 (commit)
      from  6bb6e0fb86533c14cebe8f7c5ed6277715299a7b (commit)

Summary of changes:
 docs/UPGRADING-4.2                              |   6 +
 etc/RT_Config.pm.in                             |  21 +-
 lib/RT/Attribute.pm                             | 270 +++++++++++++++++++++++-
 lib/RT/Config.pm                                |  70 ++++--
 lib/RT/EmailParser.pm                           |   3 +-
 lib/RT/Group.pm                                 |  37 +++-
 lib/RT/Interface/Email.pm                       |   3 +-
 lib/RT/Migrate/Importer.pm                      |  25 ++-
 lib/RT/Migrate/Importer/File.pm                 |   2 +-
 lib/RT/ObjectClass.pm                           |  12 ++
 lib/RT/ObjectScrip.pm                           |  13 ++
 lib/RT/ObjectTopic.pm                           |  13 ++
 lib/RT/Transaction.pm                           |  39 ++++
 lib/RT/User.pm                                  |  18 ++
 sbin/rt-importer.in                             |  26 ++-
 share/html/Admin/Elements/EditCustomFieldValues |   2 +-
 share/html/Elements/Refresh                     |  12 +-
 share/html/Elements/ShowCustomFieldWikitext     |  16 +-
 share/html/Search/Elements/Chart                |   2 +
 share/html/Ticket/Update.html                   |   3 +
 share/html/Widgets/Form/Select                  |   4 +-
 t/shredder/02group_member.t                     |  17 +-
 22 files changed, 555 insertions(+), 59 deletions(-)

- Log -----------------------------------------------------------------
commit 00f6d2e0fc383b2b8f0a97cc74b6d3685c4df9a4
Merge: 6bb6e0f 0206ec7
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Wed Jul 20 13:31:15 2016 -0400

    Merge branch '4.2-trunk' into 4.4-trunk

diff --cc lib/RT/Config.pm
index 9db2980,71e727f..dfb3a61
--- a/lib/RT/Config.pm
+++ b/lib/RT/Config.pm
@@@ -321,15 -307,16 +321,25 @@@ our %META
              Hints       => 'Only for entry, not display', #loc
          },
      },
 +    SignatureAboveQuote => {
 +        Section         => 'Ticket composition', #loc
 +        Overridable     => 1,
 +        SortOrder       => 10,
 +        Widget          => '/Widgets/Form/Boolean',
 +        WidgetArguments => {
 +            Description => 'Place signature above quote', #loc
 +        },
 +    },
+     RefreshIntervals => {
+         Type => 'ARRAY',
+         PostLoadCheck => sub {
+             my $self = shift;
+             my @intervals = $self->Get('RefreshIntervals');
+             if (grep { $_ == 0 } @intervals) {
+                 $RT::Logger->warning("Please do not include a 0 value in RefreshIntervals, as that default is already added for you.");
+             }
+         },
+     },
      SearchResultsRefreshInterval => {
          Section         => 'General',                       #loc
          Overridable     => 1,
diff --cc lib/RT/Interface/Email.pm
index 7ad978f,039c0a8..23543fc
--- a/lib/RT/Interface/Email.pm
+++ b/lib/RT/Interface/Email.pm
@@@ -778,279 -955,265 +778,280 @@@ header field then it's value is use
  
  =cut
  
 -sub ParseSenderAddressFromHead {
 -    my $head = shift;
 -    my @sender_headers = ('Reply-To', 'From', 'Sender');
 -    my @errors;  # Accumulate any errors
 +sub SendEmail {
 +    my (%args) = (
 +        Entity => undef,
 +        Bounce => 0,
 +        Ticket => undef,
 +        Transaction => undef,
 +        @_,
 +    );
  
 -    #Figure out who's sending this message.
 -    foreach my $header ( @sender_headers ) {
 -        my $addr_line = Encode::decode( "UTF-8", $head->get($header) ) || next;
 -        my ($addr, $name) = ParseAddressFromHeader( $addr_line );
 -        # only return if the address is not empty
 -        return ($addr, $name, @errors) if $addr;
 +    my $TicketObj = $args{'Ticket'};
 +    my $TransactionObj = $args{'Transaction'};
  
 -        chomp $addr_line;
 -        push @errors, "$header: $addr_line";
 +    unless ( $args{'Entity'} ) {
 +        $RT::Logger->crit( "Could not send mail without 'Entity' object" );
 +        return 0;
      }
  
 -    return (undef, undef, @errors);
 -}
 -
 -=head2 ParseErrorsToAddressFromHead HEAD
 -
 -Takes a MIME::Header object. Return a single value : user at host
 -of the From (evaluated in order of Return-path:,Errors-To:,Reply-To:,
 -From:, Sender)
 -
 -=cut
 -
 -sub ParseErrorsToAddressFromHead {
 -    my $head = shift;
 -
 -    #Figure out who's sending this message.
 -
 -    foreach my $header ( 'Errors-To', 'Reply-To', 'From', 'Sender' ) {
 -
 -        # If there's a header of that name
 -        my $headerobj = Encode::decode( "UTF-8", $head->get($header) );
 -        if ($headerobj) {
 -            my ( $addr, $name ) = ParseAddressFromHeader($headerobj);
 -
 -            # If it's got actual useful content...
 -            return ($addr) if ($addr);
 -        }
 +    my $msgid = Encode::decode( "UTF-8", $args{'Entity'}->head->get('Message-ID') || '' );
 +    chomp $msgid;
 +    
 +    # If we don't have any recipients to send to, don't send a message;
 +    unless ( $args{'Entity'}->head->get('To')
 +        || $args{'Entity'}->head->get('Cc')
 +        || $args{'Entity'}->head->get('Bcc') )
 +    {
 +        $RT::Logger->info( $msgid . " No recipients found. Not sending." );
 +        return -1;
      }
 -}
 -
 -
 -
 -=head2 ParseAddressFromHeader ADDRESS
 -
 -Takes an address from C<$head->get('Line')> and returns a tuple: user at host, friendly name
 -
 -=cut
 -
 -sub ParseAddressFromHeader {
 -    my $Addr = shift;
  
 -    # Some broken mailers send:  ""Vincent, Jesse"" <jesse at fsck.com>. Hate
 -    $Addr =~ s/\"\"(.*?)\"\"/\"$1\"/g;
 -    my @Addresses = RT::EmailParser->ParseEmailAddress($Addr);
 -
 -    my ($AddrObj) = grep ref $_, @Addresses;
 -    unless ( $AddrObj ) {
 -        return ( undef, undef );
 +    if ($args{'Entity'}->head->get('X-RT-Squelch')) {
 +        $RT::Logger->info( $msgid . " Squelch header found. Not sending." );
 +        return -1;
      }
  
 -    return ( $AddrObj->address, $AddrObj->phrase );
 -}
 -
 -=head2 DeleteRecipientsFromHead HEAD RECIPIENTS
 -
 -Gets a head object and list of addresses.
 -Deletes addresses from To, Cc or Bcc fields.
 -
 -=cut
 -
 -sub DeleteRecipientsFromHead {
 -    my $head = shift;
 -    my %skip = map { lc $_ => 1 } @_;
 -
 -    foreach my $field ( qw(To Cc Bcc) ) {
 -        $head->replace( $field => Encode::encode( "UTF-8",
 -            join ', ', map $_->format, grep !$skip{ lc $_->address },
 -                Email::Address->parse( Encode::decode( "UTF-8", $head->get( $field ) ) ) )
 -        );
 +    if (my $precedence = RT->Config->Get('DefaultMailPrecedence')
 +        and !$args{'Entity'}->head->get("Precedence")
 +    ) {
 +        $args{'Entity'}->head->replace( 'Precedence', Encode::encode("UTF-8",$precedence) );
      }
 -}
 -
 -sub GenMessageId {
 -    my %args = (
 -        Ticket      => undef,
 -        Scrip       => undef,
 -        ScripAction => undef,
 -        @_
 -    );
 -    my $org = RT->Config->Get('Organization');
 -    my $ticket_id = ( ref $args{'Ticket'}? $args{'Ticket'}->id : $args{'Ticket'} ) || 0;
 -    my $scrip_id = ( ref $args{'Scrip'}? $args{'Scrip'}->id : $args{'Scrip'} ) || 0;
 -    my $sent = ( ref $args{'ScripAction'}? $args{'ScripAction'}->{'_Message_ID'} : 0 ) || 0;
 -
 -    return "<rt-". $RT::VERSION ."-". $$ ."-". CORE::time() ."-". int(rand(2000)) .'.'
 -        . $ticket_id ."-". $scrip_id ."-". $sent ."@". $org .">" ;
 -}
 -
 -sub SetInReplyTo {
 -    my %args = (
 -        Message   => undef,
 -        InReplyTo => undef,
 -        Ticket    => undef,
 -        @_
 -    );
 -    return unless $args{'Message'} && $args{'InReplyTo'};
  
 -    my $get_header = sub {
 -        my @res;
 -        if ( $args{'InReplyTo'}->isa('MIME::Entity') ) {
 -            @res = map {Encode::decode("UTF-8", $_)} $args{'InReplyTo'}->head->get( shift );
 -        } else {
 -            @res = $args{'InReplyTo'}->GetHeader( shift ) || '';
 -        }
 -        return grep length, map { split /\s+/m, $_ } grep defined, @res;
 -    };
 +    if ( $TransactionObj && !$TicketObj
 +        && $TransactionObj->ObjectType eq 'RT::Ticket' )
 +    {
 +        $TicketObj = $TransactionObj->Object;
 +    }
  
 -    my @id = $get_header->('Message-ID');
 -    #XXX: custom header should begin with X- otherwise is violation of the standard
 -    my @rtid = $get_header->('RT-Message-ID');
 -    my @references = $get_header->('References');
 -    unless ( @references ) {
 -        @references = $get_header->('In-Reply-To');
 +    my $head = $args{'Entity'}->head;
 +    unless ( $head->get('Date') ) {
 +        require RT::Date;
 +        my $date = RT::Date->new( RT->SystemUser );
 +        $date->SetToNow;
 +        $head->replace( 'Date', Encode::encode("UTF-8",$date->RFC2822( Timezone => 'server' ) ) );
      }
 -    push @references, @id, @rtid;
 -    if ( $args{'Ticket'} ) {
 -        my $pseudo_ref = PseudoReference( $args{'Ticket'} );
 -        push @references, $pseudo_ref unless grep $_ eq $pseudo_ref, @references;
 +    unless ( $head->get('MIME-Version') ) {
 +        # We should never have to set the MIME-Version header
 +        $head->replace( 'MIME-Version', '1.0' );
 +    }
 +    unless ( $head->get('Content-Transfer-Encoding') ) {
 +        # fsck.com #5959: Since RT sends 8bit mail, we should say so.
 +        $head->replace( 'Content-Transfer-Encoding', '8bit' );
      }
 -    splice @references, 4, -6
 -        if @references > 10;
 -
 -    my $mail = $args{'Message'};
 -    $mail->head->replace( 'In-Reply-To' => Encode::encode( "UTF-8", join ' ', @rtid? (@rtid) : (@id)) ) if @id || @rtid;
 -    $mail->head->replace( 'References' => Encode::encode( "UTF-8", join ' ', @references) );
 -}
  
 -sub PseudoReference {
 -    my $ticket = shift;
 -    return '<RT-Ticket-'. $ticket->id .'@'. RT->Config->Get('Organization') .'>';
 -}
 +    if ( RT->Config->Get('Crypt')->{'Enable'} ) {
 +        %args = WillSignEncrypt(
 +            %args,
 +            Attachment => $TransactionObj ? $TransactionObj->Attachments->First : undef,
 +            Ticket     => $TicketObj,
 +        );
 +        my $res = SignEncrypt( %args );
 +        return $res unless $res > 0;
 +    }
  
 -=head2 ExtractTicketId
 +    my $mail_command = RT->Config->Get('MailCommand');
  
 -Passed a MIME::Entity.  Returns a ticket id or undef to signal 'new ticket'.
 +    # if it is a sub routine, we just return it;
 +    return $mail_command->($args{'Entity'}) if UNIVERSAL::isa( $mail_command, 'CODE' );
  
 -This is a great entry point if you need to customize how ticket ids are
 -handled for your site. RT-Extension-RepliesToResolved demonstrates one
 -possible use for this extension.
 +    if ( $mail_command eq 'sendmailpipe' ) {
 +        my $path = RT->Config->Get('SendmailPath');
 +        my @args = shellwords(RT->Config->Get('SendmailArguments'));
 +        push @args, "-t" unless grep {$_ eq "-t"} @args;
  
 -If the Subject of this ticket is modified, it will be reloaded by the
 -mail gateway code before Ticket creation.
 +        # SetOutgoingMailFrom and bounces conflict, since they both want -f
 +        if ( $args{'Bounce'} ) {
 +            push @args, shellwords(RT->Config->Get('SendmailBounceArguments'));
 +        } elsif ( my $MailFrom = RT->Config->Get('SetOutgoingMailFrom') ) {
 +            my $OutgoingMailAddress = $MailFrom =~ /\@/ ? $MailFrom : undef;
 +            my $Overrides = RT->Config->Get('OverrideOutgoingMailFrom') || {};
  
 -=cut
 +            if ($TicketObj) {
 +                my $Queue = $TicketObj->QueueObj;
 +                my $QueueAddressOverride = $Overrides->{$Queue->id}
 +                    || $Overrides->{$Queue->Name};
  
 -sub ExtractTicketId {
 -    my $entity = shift;
 +                if ($QueueAddressOverride) {
 +                    $OutgoingMailAddress = $QueueAddressOverride;
 +                } else {
 +                    $OutgoingMailAddress ||= $Queue->CorrespondAddress
 +                        || RT->Config->Get('CorrespondAddress');
 +                }
 +            }
 +            elsif ($Overrides->{'Default'}) {
 +                $OutgoingMailAddress = $Overrides->{'Default'};
 +            }
  
 -    my $subject = Encode::decode( "UTF-8", $entity->head->get('Subject') || '' );
 -    chomp $subject;
 -    return ParseTicketId( $subject );
 -}
 +            push @args, "-f", $OutgoingMailAddress
 +                if $OutgoingMailAddress;
 +        }
  
 -=head2 ParseTicketId
 +        # VERP
 +        if ( $TransactionObj and
 +             my $prefix = RT->Config->Get('VERPPrefix') and
 +             my $domain = RT->Config->Get('VERPDomain') )
 +        {
 +            my $from = $TransactionObj->CreatorObj->EmailAddress;
 +            $from =~ s/@/=/g;
 +            $from =~ s/\s//g;
 +            push @args, "-f", "$prefix$from\@$domain";
 +        }
  
 -Takes a string and searches for [subjecttag #id]
 +        eval {
 +            # don't ignore CHLD signal to get proper exit code
 +            local $SIG{'CHLD'} = 'DEFAULT';
  
 -Returns the id if a match is found.  Otherwise returns undef.
 +            # if something wrong with $mail->print we will get PIPE signal, handle it
 +            local $SIG{'PIPE'} = sub { die "program unexpectedly closed pipe" };
  
 -=cut
 +            require IPC::Open2;
 +            my ($mail, $stdout);
 +            my $pid = IPC::Open2::open2( $stdout, $mail, $path, @args )
 +                or die "couldn't execute program: $!";
  
 -sub ParseTicketId {
 -    my $Subject = shift;
 +            $args{'Entity'}->print($mail);
 +            close $mail or die "close pipe failed: $!";
  
 -    my $rtname = RT->Config->Get('rtname');
 -    my $test_name = RT->Config->Get('EmailSubjectTagRegex') || qr/\Q$rtname\E/i;
 +            waitpid($pid, 0);
 +            if ($?) {
 +                # sendmail exit statuses mostly errors with data not software
 +                # TODO: status parsing: core dump, exit on signal or EX_*
 +                my $msg = "$msgid: `$path @args` exited with code ". ($?>>8);
 +                $msg = ", interrupted by signal ". ($?&127) if $?&127;
 +                $RT::Logger->error( $msg );
 +                die $msg;
 +            }
 +        };
 +        if ( $@ ) {
 +            $RT::Logger->crit( "$msgid: Could not send mail with command `$path @args`: " . $@ );
 +            if ( $TicketObj ) {
 +                _RecordSendEmailFailure( $TicketObj );
 +            }
 +            return 0;
 +        }
 +    } elsif ( $mail_command eq 'mbox' ) {
 +        my $now = RT::Date->new(RT->SystemUser);
 +        $now->SetToNow;
  
 -    # We use @captures and pull out the last capture value to guard against
 -    # someone using (...) instead of (?:...) in $EmailSubjectTagRegex.
 -    my $id;
 -    if ( my @captures = $Subject =~ /\[$test_name\s+\#(\d+)\s*\]/i ) {
 -        $id = $captures[-1];
 +        state $logfile;
 +        unless ($logfile) {
 +            my $when = $now->ISO( Timezone => "server" );
 +            $when =~ s/\s+/-/g;
 +            $logfile = "$RT::VarPath/$when.mbox";
 +            $RT::Logger->info("Storing outgoing emails in $logfile");
 +        }
 +        my $fh;
 +        unless (open($fh, ">>", $logfile)) {
 +            $RT::Logger->crit( "Can't open mbox file $logfile: $!" );
 +            return 0;
 +        }
 +        my $content = $args{Entity}->stringify;
 +        $content =~ s/^(>*From )/>$1/mg;
-         print $fh "From $ENV{USER}\@localhost  ".localtime()."\n";
++        my $user = $ENV{USER} || getpwuid($<);
++        print $fh "From $user\@localhost  ".localtime()."\n";
 +        print $fh $content, "\n";
 +        close $fh;
      } else {
 -        foreach my $tag ( RT->System->SubjectTag ) {
 -            next unless my @captures = $Subject =~ /\[\Q$tag\E\s+\#(\d+)\s*\]/i;
 -            $id = $captures[-1];
 -            last;
 +        local ($ENV{'MAILADDRESS'}, $ENV{'PERL_MAILERS'});
 +
 +        my @mailer_args = ($mail_command);
 +        if ( $mail_command eq 'sendmail' ) {
 +            $ENV{'PERL_MAILERS'} = RT->Config->Get('SendmailPath');
 +            push @mailer_args, grep {$_ ne "-t"}
 +                split(/\s+/, RT->Config->Get('SendmailArguments'));
 +        } elsif ( $mail_command eq 'testfile' ) {
 +            unless ($Mail::Mailer::testfile::config{outfile}) {
 +                $Mail::Mailer::testfile::config{outfile} = File::Temp->new;
 +                $RT::Logger->info("Storing outgoing emails in $Mail::Mailer::testfile::config{outfile}");
 +            }
 +        } else {
 +            push @mailer_args, RT->Config->Get('MailParams');
          }
 -    }
 -    return undef unless $id;
  
 -    $RT::Logger->debug("Found a ticket ID. It's $id");
 -    return $id;
 +        unless ( $args{'Entity'}->send( @mailer_args ) ) {
 +            $RT::Logger->crit( "$msgid: Could not send mail." );
 +            if ( $TicketObj ) {
 +                _RecordSendEmailFailure( $TicketObj );
 +            }
 +            return 0;
 +        }
 +    }
 +    return 1;
  }
  
 -sub AddSubjectTag {
 -    my $subject = shift;
 -    my $ticket  = shift;
 -    unless ( ref $ticket ) {
 -        my $tmp = RT::Ticket->new( RT->SystemUser );
 -        $tmp->Load( $ticket );
 -        $ticket = $tmp;
 -    }
 -    my $id = $ticket->id;
 -    my $queue_tag = $ticket->QueueObj->SubjectTag;
 +=head3 PrepareEmailUsingTemplate Template => '', Arguments => {}
  
 -    my $tag_re = RT->Config->Get('EmailSubjectTagRegex');
 -    unless ( $tag_re ) {
 -        my $tag = $queue_tag || RT->Config->Get('rtname');
 -        $tag_re = qr/\Q$tag\E/;
 -    } elsif ( $queue_tag ) {
 -        $tag_re = qr/$tag_re|\Q$queue_tag\E/;
 -    }
 -    return $subject if $subject =~ /\[$tag_re\s+#$id\]/;
 +Loads a template. Parses it using arguments if it's not empty.
 +Returns a tuple (L<RT::Template> object, error message).
  
 -    $subject =~ s/(\r\n|\n|\s)/ /g;
 -    chomp $subject;
 -    return "[". ($queue_tag || RT->Config->Get('rtname')) ." #$id] $subject";
 -}
 +Note that even if a template object is returned MIMEObj method
 +may return undef for empty templates.
  
 +=cut
  
 -=head2 Gateway ARGSREF
 +sub PrepareEmailUsingTemplate {
 +    my %args = (
 +        Template => '',
 +        Arguments => {},
 +        @_
 +    );
  
 +    my $template = RT::Template->new( RT->SystemUser );
 +    $template->LoadGlobalTemplate( $args{'Template'} );
 +    unless ( $template->id ) {
 +        return (undef, "Couldn't load template '". $args{'Template'} ."'");
 +    }
 +    return $template if $template->IsEmpty;
  
 -Takes parameters:
 +    my ($status, $msg) = $template->Parse( %{ $args{'Arguments'} } );
 +    return (undef, $msg) unless $status;
  
 -    action
 -    queue
 -    message
 +    return $template;
 +}
  
 +=head3 SendEmailUsingTemplate Template => '', Arguments => {}, From => CorrespondAddress, To => '', Cc => '', Bcc => ''
  
 -This performs all the "guts" of the mail rt-mailgate program, and is
 -designed to be called from the web interface with a message, user
 -object, and so on.
 +Sends email using a template, takes name of template, arguments for it and recipients.
  
 -Can also take an optional 'ticket' parameter; this ticket id overrides
 -any ticket id found in the subject.
 +=cut
  
 -Returns:
 +sub SendEmailUsingTemplate {
 +    my %args = (
 +        Template => '',
 +        Arguments => {},
 +        To => undef,
 +        Cc => undef,
 +        Bcc => undef,
 +        From => RT->Config->Get('CorrespondAddress'),
 +        InReplyTo => undef,
 +        ExtraHeaders => {},
 +        @_
 +    );
  
 -    An array of:
 +    my ($template, $msg) = PrepareEmailUsingTemplate( %args );
 +    return (0, $msg) unless $template;
  
 -    (status code, message, optional ticket object)
 +    my $mail = $template->MIMEObj;
 +    unless ( $mail ) {
 +        $RT::Logger->info("Message is not sent as template #". $template->id ." is empty");
 +        return -1;
 +    }
  
 -    status code is a numeric value.
 +    $mail->head->replace( $_ => Encode::encode( "UTF-8", $args{ $_ } ) )
 +        foreach grep defined $args{$_}, qw(To Cc Bcc From);
  
 -      for temporary failures, the status code should be -75
 +    $mail->head->replace( $_ => Encode::encode( "UTF-8", $args{ExtraHeaders}{$_} ) )
 +        foreach keys %{ $args{ExtraHeaders} };
  
 -      for permanent failures which are handled by RT, the status code
 -      should be 0
 +    SetInReplyTo( Message => $mail, InReplyTo => $args{'InReplyTo'} );
  
 -      for succces, the status code should be 1
 +    return SendEmail( Entity => $mail );
 +}
  
 +=head3 GetForwardFrom Ticket => undef, Transaction => undef
  
 +Resolve the From field to use in forward mail
  
  =cut
  
diff --cc lib/RT/Transaction.pm
index 9afdedf,15d62b2..da41850
--- a/lib/RT/Transaction.pm
+++ b/lib/RT/Transaction.pm
@@@ -1328,15 -1312,42 +1328,51 @@@ sub _CanonicalizeRoleName 
              return ("Reminder completed"); #loc()
          }
      },
 +    'RT::Asset-Set-Catalog' => sub {
 +        my $self = shift;
 +        return ("[_1] changed from [_2] to [_3]",   #loc
 +                $self->loc($self->Field), map {
 +                    my $c = RT::Catalog->new($self->CurrentUser);
 +                    $c->Load($_);
 +                    $c->Name || $self->loc("~[a hidden catalog~]")
 +                } $self->OldValue, $self->NewValue);
 +    },
+     AddMember => sub {
+         my $self = shift;
+         my $principal = RT::Principal->new($self->CurrentUser);
+         $principal->Load($self->Field);
+ 
+         if ($principal->IsUser) {
+             return ("Added user '[_1]'", $principal->Object->Name); #loc()
+         }
+         else {
+             return ("Added group '[_1]'", $principal->Object->Name); #loc()
+         }
+     },
+     DeleteMember => sub {
+         my $self = shift;
+         my $principal = RT::Principal->new($self->CurrentUser);
+         $principal->Load($self->Field);
+ 
+         if ($principal->IsUser) {
+             return ("Removed user '[_1]'", $principal->Object->Name); #loc()
+         }
+         else {
+             return ("Removed group '[_1]'", $principal->Object->Name); #loc()
+         }
+     },
+     AddMembership => sub {
+         my $self = shift;
+         my $principal = RT::Principal->new($self->CurrentUser);
+         $principal->Load($self->Field);
+         return ("Added to group '[_1]'", $principal->Object->Name); #loc()
+     },
+     DeleteMembership => sub {
+         my $self = shift;
+         my $principal = RT::Principal->new($self->CurrentUser);
+         $principal->Load($self->Field);
+         return ("Removed from group '[_1]'", $principal->Object->Name); #loc()
+     },
  );
  
  

-----------------------------------------------------------------------


More information about the rt-commit mailing list