Browse files

support customized forward message and use scrip to send forwarded me…

…ssage

now we record the forward transaction with customized message and use a scrip
bound to it to actually send the message.
(SendForward action is newly added for it)

As we use SendEmail action, invalid recipients will be stripped, so I removed
"rt-test" recipient in test.
  • Loading branch information...
1 parent 62a4a2b commit ab8edd262c5741ea25f1ff521d6721d3f78fabd3 sunnavy committed Jul 18, 2012
View
19 etc/initialdata
@@ -98,6 +98,9 @@
{ Name => 'Extract Subject Tag', # loc
Description => 'Extract tags from a Transaction\'s subject and add them to the Ticket\'s subject.', # loc
ExecModule => 'ExtractSubjectTag' },
+ { Name => 'Send Forward', # loc
+ Description => 'Send forwarded message', # loc
+ ExecModule => 'SendForward', },
);
@ScripConditions = (
@@ -400,17 +403,21 @@ The ticket has been approved, you may now start to act on it.
},
{ Queue => 0,
Name => "Forward", # loc
- Description => "Heading of a forwarded message", # loc
+ Description => "Forwarded message", # loc
Content => q{
This is a forward of transaction #{$Transaction->id} of ticket #{ $Ticket->id }
+
+{ $ForwardTransaction->Content }
}
},
{ Queue => 0,
Name => "Forward Ticket", # loc
- Description => "Heading of a forwarded Ticket", # loc
+ Description => "Forwarded ticket message", # loc
Content => q{
This is a forward of ticket #{ $Ticket->id }
+
+{ $ForwardTransaction->Content }
}
},
{ Queue => 0,
@@ -555,6 +562,14 @@ Hour: { $SubscriptionObj->SubValue('Hour') }
ScripCondition => 'On Transaction',
ScripAction => 'Extract Subject Tag',
Template => 'Blank' },
+ { Description => 'On Forward Transaction Send forwarded message',
+ ScripCondition => 'On Forward Transaction',
+ ScripAction => 'Send Forward',
+ Template => 'Forward' },
+ { Description => 'On Forward Ticket Send forwarded message',
+ ScripCondition => 'On Forward Ticket',
+ ScripAction => 'Send Forward',
+ Template => 'Forward Ticket' },
);
@ACL = (
View
16 lib/RT/Action/SendEmail.pm
@@ -151,13 +151,15 @@ Builds an outgoing email we're going to send using scrip's template.
sub Prepare {
my $self = shift;
- my ( $result, $message ) = $self->TemplateObj->Parse(
- Argument => $self->Argument,
- TicketObj => $self->TicketObj,
- TransactionObj => $self->TransactionObj
- );
- if ( !$result ) {
- return (undef);
+ unless ( $self->TemplateObj->MIMEObj ) {
+ my ( $result, $message ) = $self->TemplateObj->Parse(
+ Argument => $self->Argument,
+ TicketObj => $self->TicketObj,
+ TransactionObj => $self->TransactionObj
+ );
+ if ( !$result ) {
+ return (undef);
+ }
}
my $MIMEObj = $self->TemplateObj->MIMEObj;
View
148 lib/RT/Action/SendForward.pm
@@ -0,0 +1,148 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
+# <sales@bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
+#
+package RT::Action::SendForward;
+
+use strict;
+use warnings;
+
+use base qw(RT::Action::SendEmail);
+
+use Email::Address;
+
+=head2 Prepare
+
+=cut
+
+sub Prepare {
+ my $self = shift;
+
+ my $txn = $self->TransactionObj;
+
+ if ( $txn->Type eq 'Forward Transaction' ) {
+ my $forwarded_txn = RT::Transaction->new( $self->CurrentUser );
+ $forwarded_txn->Load( $txn->Field );
+ $self->{ForwardedTransactionObj} = $forwarded_txn;
+ }
+
+ my ( $result, $message ) = $self->TemplateObj->Parse(
+ Argument => $self->Argument,
+ Ticket => $self->TicketObj,
+ Transaction => $self->ForwardedTransactionObj,
+ ForwardTransaction => $self->TransactionObj,
+ );
+
+ if ( !$result ) {
+ return (undef);
+ }
+
+ my $mime = $self->TemplateObj->MIMEObj;
+ $mime->make_multipart unless $mime->is_multipart;
+
+ my $entity;
+ if ( $txn->Type eq 'Forward Transaction' ) {
+ $entity = $self->ForwardedTransactionObj->ContentAsMIME;
+ }
+ else {
+ my $txns = $self->TicketObj->Transactions;
+ $txns->Limit(
+ FIELD => 'Type',
+ VALUE => $_,
+ ) for qw(Create Correspond);
+
+ $entity = MIME::Entity->build(
+ Type => 'multipart/mixed',
+ Description => 'forwarded ticket',
+ );
+ $entity->add_part($_) foreach
+ map $_->ContentAsMIME,
+ @{ $txns->ItemsArrayRef };
+ }
+
+ $mime->add_part($entity);
+
+ unless ( $mime->head->get('Subject') ) {
+ my $subject = '';
+ $subject = $self->ForwardedTransactionObj->Subject
+ if $self->ForwardedTransactionObj;
+ $subject ||= $self->TicketObj->Subject;
+ unless ( RT->Config->Get('ForwardFromUser') ) {
+ $subject =
+ RT::Interface::Email::AddSubjectTag( $subject, $self->TicketObj );
+ }
+ $mime->head->set( Subject => $self->MIMEEncodeString("Fwd: $subject") );
+ }
+
+ my $txn_attachment = $self->TransactionObj->Attachments->First;
+ for my $header (qw/From To Cc Bcc/) {
+ if ( $txn_attachment->GetHeader( $header ) ) {
+ $mime->head->set( $header => $txn_attachment->GetHeader($header) );
+ }
+ }
+
+ if ( RT->Config->Get('ForwardFromUser') ) {
+ $mime->head->set( 'X-RT-Sign' => 0 );
+ }
+
+ $self->SUPER::Prepare();
+}
+
+sub SetSubjectToken {
+
+ # we already take care of this in Prepare.
+}
+
+sub ForwardedTransactionObj {
+ my $self = shift;
+ return $self->{'ForwardedTransactionObj'};
+}
+
+RT::Base->_ImportOverlays();
+
+1;
View
190 lib/RT/Interface/Email.pm
@@ -611,190 +611,56 @@ sub SendEmailUsingTemplate {
return SendEmail( Entity => $mail );
}
-=head2 ForwardTransaction TRANSACTION, To => '', Cc => '', Bcc => ''
-
-Forwards transaction with all attachments as 'message/rfc822'.
-
-=cut
-
-sub ForwardTransaction {
- my $txn = shift;
- my %args = ( To => '', Cc => '', Bcc => '', @_ );
-
- my $entity = $txn->ContentAsMIME;
-
- my ( $ret, $msg ) = SendForward( %args, Entity => $entity, Transaction => $txn );
- if ($ret) {
- my $ticket = $txn->TicketObj;
- my ( $ret, $msg ) = $ticket->_NewTransaction(
- Type => 'Forward Transaction',
- Field => $txn->id,
- Data => join ', ', grep { length } $args{To}, $args{Cc}, $args{Bcc},
- );
- unless ($ret) {
- $RT::Logger->error("Failed to create transaction: $msg");
- }
- }
- return ( $ret, $msg );
-}
-
-=head2 ForwardTicket TICKET, To => '', Cc => '', Bcc => ''
-
-Forwards a ticket's Create and Correspond Transactions and their Attachments as 'message/rfc822'.
-
-=cut
-
-sub ForwardTicket {
- my $ticket = shift;
- my %args = ( To => '', Cc => '', Bcc => '', @_ );
-
- my $txns = $ticket->Transactions;
- $txns->Limit(
- FIELD => 'Type',
- VALUE => $_,
- ) for qw(Create Correspond);
-
- my $entity = MIME::Entity->build(
- Type => 'multipart/mixed',
- Description => 'forwarded ticket',
- );
- $entity->add_part( $_ ) foreach
- map $_->ContentAsMIME,
- @{ $txns->ItemsArrayRef };
-
- my ( $ret, $msg ) = SendForward(
- %args,
- Entity => $entity,
- Ticket => $ticket,
- Template => 'Forward Ticket',
- );
-
- if ($ret) {
- my ( $ret, $msg ) = $ticket->_NewTransaction(
- Type => 'Forward Ticket',
- Field => $ticket->id,
- Data => join ', ', grep { length } $args{To}, $args{Cc}, $args{Bcc},
- );
- unless ($ret) {
- $RT::Logger->error("Failed to create transaction: $msg");
- }
- }
-
- return ( $ret, $msg );
-
-}
-
-=head2 SendForward Entity => undef, Ticket => undef, Transaction => undef, Template => undef, To => '', Cc => '', Bcc => ''
+=head2 GetForwardFrom Ticket => undef, Transaction => undef
-Forwards an Entity representing Ticket or Transaction as 'message/rfc822'. Entity is wrapped into Template.
+Resolve the From field to use in forward mail
=cut
-sub SendForward {
- my (%args) = (
- Entity => undef,
- Ticket => undef,
- Transaction => undef,
- Template => 'Forward',
- To => '', Cc => '', Bcc => '',
- @_
- );
-
- my $txn = $args{'Transaction'};
- my $ticket = $args{'Ticket'};
- $ticket ||= $txn->Object if $txn;
-
- my $entity = $args{'Entity'};
- unless ( $entity ) {
- require Carp;
- $RT::Logger->error(Carp::longmess("No entity provided"));
- return (0, $ticket->loc("Couldn't send email"));
- }
-
- my ($template, $msg) = PrepareEmailUsingTemplate(
- Template => $args{'Template'},
- Arguments => {
- Ticket => $ticket,
- Transaction => $txn,
- },
- );
-
- my $mail;
- if ( $template ) {
- $mail = $template->MIMEObj;
- } else {
- $RT::Logger->warning($msg);
- }
- unless ( $mail ) {
- $RT::Logger->warning("Couldn't generate email using template '$args{Template}'");
+sub GetForwardFrom {
+ my %args = ( Ticket => undef, Transaction => undef, @_ );
+ my $txn = $args{Transaction};
+ my $ticket = $args{Ticket} || $txn->Object;
- my $description;
- unless ( $args{'Transaction'} ) {
- $description = 'This is forward of ticket #'. $ticket->id;
- } else {
- $description = 'This is forward of transaction #'
- . $txn->id ." of a ticket #". $txn->ObjectId;
- }
- $mail = MIME::Entity->build(
- Type => 'text/plain',
- Data => $description,
- );
+ if ( RT->Config->Get('ForwardFromUser') ) {
+ return ( $txn || $ticket )->CurrentUser->EmailAddress;
}
-
- $mail->head->set( $_ => EncodeToMIME( String => $args{$_} ) )
- foreach grep defined $args{$_}, qw(To Cc Bcc);
-
- $mail->make_multipart unless $mail->is_multipart;
- $mail->add_part( $entity );
-
- my $from;
- unless (defined $mail->head->get('Subject')) {
- my $subject = '';
- $subject = $txn->Subject if $txn;
- $subject ||= $ticket->Subject if $ticket;
-
- unless ( RT->Config->Get('ForwardFromUser') ) {
- # XXX: what if want to forward txn of other object than ticket?
- $subject = AddSubjectTag( $subject, $ticket );
- }
-
- $mail->head->set( Subject => EncodeToMIME( String => "Fwd: $subject" ) );
+ else {
+ return $ticket->QueueObj->CorrespondAddress
+ || RT->Config->Get('CorrespondAddress');
}
-
- $mail->head->set(
- From => EncodeToMIME(
- String => GetForwardFrom( Transaction => $txn, Ticket => $ticket )
- )
- );
-
- my $status = RT->Config->Get('ForwardFromUser')
- # never sign if we forward from User
- ? SendEmail( %args, Entity => $mail, Sign => 0 )
- : SendEmail( %args, Entity => $mail );
- return (0, $ticket->loc("Couldn't send email")) unless $status;
- return (1, $ticket->loc("Sent email successfully"));
}
-=head2 GetForwardFrom Ticket => undef, Transaction => undef
+=head2 GetForwardAttachments Ticket => undef, Transaction => undef
-Resolve the From field to use in forward mail
+Resolve the Attachments to forward
=cut
-sub GetForwardFrom {
+sub GetForwardAttachments {
my %args = ( Ticket => undef, Transaction => undef, @_ );
my $txn = $args{Transaction};
my $ticket = $args{Ticket} || $txn->Object;
- if ( RT->Config->Get('ForwardFromUser') ) {
- return ( $txn || $ticket )->CurrentUser->EmailAddress;
+ my $attachments = RT::Attachments->new( $ticket->CurrentUser );
+ if ($txn) {
+ $attachments->Limit( FIELD => 'TransactionId', VALUE => $txn->id );
}
else {
- return $ticket->QueueObj->CorrespondAddress
- || RT->Config->Get('CorrespondAddress');
+ my $txns = $ticket->Transactions;
+ $txns->Limit(
+ FIELD => 'Type',
+ VALUE => $_,
+ ) for qw(Create Correspond);
+
+ while ( my $txn = $txns->Next ) {
+ $attachments->Limit( FIELD => 'TransactionId', VALUE => $txn->id );
+ }
}
+ return $attachments;
}
+
=head2 SignEncrypt Entity => undef, Sign => 0, Encrypt => 0
Signs and encrypts message using L<RT::Crypt::GnuPG>, but as well
View
69 lib/RT/Ticket.pm
@@ -3749,6 +3749,75 @@ sub ACLEquivalenceObjects {
}
+=head2 Forward Transaction => undef, To => '', Cc => '', Bcc => ''
+
+Forwards transaction with all attachments as 'message/rfc822'.
+
+=cut
+
+sub Forward {
+ my $self = shift;
+ my %args = (
+ Transaction => undef,
+ To => '',
+ Cc => '',
+ Bcc => '',
+ Content => '',
+ ContentType => 'text/plain',
+ DryRun => 0,
+ CommitScrips => 1,
+ @_
+ );
+
+ unless ( $self->CurrentUserHasRight('ForwardMessage') ) {
+ return ( 0, $self->loc("Permission Denied") );
+ }
+
+ my $mime = MIME::Entity->build(
+ Type => $args{'ContentType'},
+ Data => $args{Content},
+ );
+
+ $mime->head->set(
+ $_ => RT::Interface::Email::EncodeToMIME( String => $args{$_} ) )
+ for grep defined $args{$_}, qw(To Cc Bcc);
+ $mime->head->set(
+ From => RT::Interface::Email::EncodeToMIME(
+ String => RT::Interface::Email::GetForwardFrom(
+ Transaction => $args{Transaction},
+ Ticket => $self,
+ )
+ )
+ );
+
+ if ($args{'DryRun'}) {
+ $RT::Handle->BeginTransaction();
+ $args{'CommitScrips'} = 0;
+ }
+
+ my ( $ret, $msg ) = $self->_NewTransaction(
+ $args{Transaction}
+ ? (
+ Type => 'Forward Transaction',
+ Field => $args{Transaction}->id,
+ )
+ : (
+ Type => 'Forward Ticket',
+ Field => $self->id,
+ ),
+ MIMEObj => $mime,
+ CommitScrips => $args{'CommitScrips'},
+ );
+
+ unless ($ret) {
+ $RT::Logger->error("Failed to create transaction: $msg");
+ }
+
+ if ($args{'DryRun'}) {
+ $RT::Handle->Rollback();
+ }
+ return ( $ret, $self->loc('Message recorded') );
+}
1;
View
5 lib/RT/Transaction.pm
@@ -661,11 +661,10 @@ sub BriefDescription {
return $self->loc("System error");
}
elsif ( $type =~ /Forward Transaction/ ) {
- return $self->loc( "Forwarded Transaction #[_1] to [_2]",
- $self->Field, $self->Data );
+ return $self->loc( "Forwarded Transaction #[_1]", $self->Field );
}
elsif ( $type =~ /Forward Ticket/ ) {
- return $self->loc( "Forwarded Ticket to [_1]", $self->Data );
+ return $self->loc( "Forwarded Ticket" );
}
if ( my $code = $_BriefDescriptions{$type} ) {
View
23 share/html/Ticket/Forward.html
@@ -72,8 +72,21 @@
<tr><td align="right"><&|/l&>Bcc</&>:</td>
<td><input name="Bcc" size="60" value="<% $ARGS{'Bcc'} || '' %>" /></td></tr>
+<tr>
+<td><&|/l&>Content</&>:</td>
+<td>
+% if (exists $ARGS{Content}) {
+<& /Elements/MessageBox, Default => $ARGS{Content}, IncludeSignature => 0 &>
+% } else {
+<& /Elements/MessageBox &>
+%}
+</td>
+</tr>
+
</table>
+<& /Ticket/Elements/ShowAttachments, Attachments => $attachments &>
+
<& /Elements/Submit, Label => loc('Forward Message and Return'), Name => 'ForwardAndReturn' &>
<& /Elements/Submit, Label => loc('Forward Message'), Name => 'Forward' &>
</form>
@@ -94,10 +107,7 @@
my @results;
if ( $Forward || $ForwardAndReturn ) {
- require RT::Interface::Email;
- my ($status, $msg) = $txn
- ? RT::Interface::Email::ForwardTransaction( $txn, %ARGS )
- : RT::Interface::Email::ForwardTicket( $TicketObj, %ARGS );
+ my ( $status, $msg ) = $TicketObj->Forward( Transaction => $txn, %ARGS );
push @results, $msg;
if ( $ForwardAndReturn ) {
@@ -119,6 +129,11 @@
$subject = RT::Interface::Email::AddSubjectTag( $subject, $TicketObj )
unless RT->Config->Get('ForwardFromUser');
+my $attachments = RT::Interface::Email::GetForwardAttachments(
+ Ticket => $TicketObj,
+ $txn ? ( Transaction => $txn ) : (),
+);
+
</%INIT>
<%ARGS>
View
31 t/web/ticket_forward.t
@@ -37,18 +37,15 @@ diag "Forward Ticket" if $ENV{TEST_VERBOSE};
$m->submit_form(
form_name => 'ForwardMessage',
fields => {
- To => 'rt-test, rt-to@example.com',
+ To => 'rt-to@example.com',
Cc => 'rt-cc@example.com',
},
button => 'ForwardAndReturn'
);
- $m->content_contains( 'Sent email successfully', 'sent mail msg' );
- $m->content_contains(
- 'Forwarded Ticket to rt-test, rt-to@example.com, rt-cc@example.com',
- 'txn msg' );
+ $m->content_contains( 'Forwarded Ticket', 'txn msg' );
my ($mail) = RT::Test->fetch_caught_mails;
like( $mail, qr!Subject: test forward!, 'Subject field' );
- like( $mail, qr!To: rt-test, rt-to\@example.com!, 'To field' );
+ like( $mail, qr!To: rt-to\@example.com!, 'To field' );
like( $mail, qr!Cc: rt-cc\@example.com!, 'Cc field' );
like( $mail, qr!This is a forward of ticket!, 'content' );
like( $mail, qr!this is an attachment!, 'att content' );
@@ -61,20 +58,16 @@ diag "Forward Transaction" if $ENV{TEST_VERBOSE};
$m->submit_form(
form_name => 'ForwardMessage',
fields => {
- To => 'rt-test, rt-to@example.com',
+ To => 'rt-to@example.com',
Cc => 'rt-cc@example.com',
Bcc => 'rt-bcc@example.com'
},
button => 'ForwardAndReturn'
);
- $m->content_contains( 'Sent email successfully', 'sent mail msg' );
- $m->content_like(
-qr/Forwarded Transaction #\d+ to rt-test, rt-to\@example.com, rt-cc\@example.com, rt-bcc\@example.com/,
- 'txn msg'
- );
+ $m->content_like( qr/Forwarded Transaction #\d+/, 'txn msg' );
my ($mail) = RT::Test->fetch_caught_mails;
like( $mail, qr!Subject: test forward!, 'Subject field' );
- like( $mail, qr!To: rt-test, rt-to\@example.com!, 'To field' );
+ like( $mail, qr!To: rt-to\@example.com!, 'To field' );
like( $mail, qr!Cc: rt-cc\@example.com!, 'Cc field' );
like( $mail, qr!Bcc: rt-bcc\@example.com!, 'Bcc field' );
like( $mail, qr!This is a forward of transaction!, 'content' );
@@ -94,7 +87,6 @@ diag "Forward Ticket without content" if $ENV{TEST_VERBOSE};
fields => { To => 'rt-test@example.com', },
button => 'ForwardAndReturn'
);
- $m->content_contains( 'Sent email successfully', 'sent mail msg' );
my ($mail) = RT::Test->fetch_caught_mails;
like( $mail, qr/Subject: Fwd: \[example\.com #\d\] test forward without content/, 'Subject field' );
like( $mail, qr/To: rt-test\@example\.com/, 'To field' );
@@ -138,8 +130,7 @@ diag "Forward Transaction with attachments but empty content" if $ENV{TEST_VERBO
},
button => 'ForwardAndReturn'
);
- $m->content_contains( 'Sent email successfully', 'sent mail msg' );
- $m->content_like( qr/Forwarded Transaction #\d+ to rt-test\@example\.com/, 'txn msg' );
+ $m->content_like(qr/Forwarded Transaction #\d+/);
my ($mail) = RT::Test->fetch_caught_mails;
like( $mail, qr/Subject: test forward, empty content but attachments/, 'Subject field' );
like( $mail, qr/To: rt-test\@example.com/, 'To field' );
@@ -196,9 +187,8 @@ diag "Forward Transaction with attachments but no 'content' part" if $ENV{TEST_V
},
button => 'ForwardAndReturn'
);
- $m->content_contains( 'Sent email successfully', 'sent mail msg' );
- $m->content_like( qr/Forwarded Transaction #\d+ to rt-test\@example\.com/, 'txn msg' );
-
+ $m->content_like( qr/Forwarded Transaction #\d+/ );
+
# Forward ticket
$m->follow_link_ok( { text => 'Forward', n => 1 }, 'follow 1st Forward' );
$m->submit_form(
@@ -208,8 +198,7 @@ diag "Forward Transaction with attachments but no 'content' part" if $ENV{TEST_V
},
button => 'ForwardAndReturn'
);
- $m->content_contains( 'Sent email successfully', 'sent mail msg' );
- $m->content_like( qr/Forwarded Ticket to rt-test\@example\.com/, 'txn msg' );
+ $m->content_like( qr/Forwarded Ticket/ );
my ($forward_txn, $forward_ticket) = RT::Test->fetch_caught_mails;
my $tag = qr/Fwd: \[example\.com #\d+\]/;

0 comments on commit ab8edd2

Please sign in to comment.