summaryrefslogtreecommitdiff
path: root/rt/lib/RT/Action
diff options
context:
space:
mode:
Diffstat (limited to 'rt/lib/RT/Action')
-rw-r--r--rt/lib/RT/Action/AutoOpen.pm23
-rwxr-xr-xrt/lib/RT/Action/Autoreply.pm6
-rw-r--r--rt/lib/RT/Action/CreateTickets.pm655
-rw-r--r--rt/lib/RT/Action/EscalatePriority.pm7
-rwxr-xr-xrt/lib/RT/Action/Generic.pm7
-rwxr-xr-xrt/lib/RT/Action/Notify.pm6
-rwxr-xr-xrt/lib/RT/Action/NotifyAsComment.pm6
-rw-r--r--rt/lib/RT/Action/RecordComment.pm6
-rw-r--r--rt/lib/RT/Action/RecordCorrespondence.pm6
-rw-r--r--rt/lib/RT/Action/ResolveMembers.pm6
-rwxr-xr-xrt/lib/RT/Action/SendEmail.pm125
-rw-r--r--rt/lib/RT/Action/SetPriority.pm6
-rw-r--r--rt/lib/RT/Action/UserDefined.pm6
13 files changed, 542 insertions, 323 deletions
diff --git a/rt/lib/RT/Action/AutoOpen.pm b/rt/lib/RT/Action/AutoOpen.pm
index 3423db93e..54b5ab4e2 100644
--- a/rt/lib/RT/Action/AutoOpen.pm
+++ b/rt/lib/RT/Action/AutoOpen.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
@@ -71,18 +73,15 @@ sub Prepare {
# if the ticket is already open or the ticket is new and the message is more mail from the
# requestor, don't reopen it.
- if ( ( $self->TicketObj->Status eq 'open' )
- || ( ( $self->TicketObj->Status eq 'new' )
- && $self->TransactionObj->IsInbound )
- || ( defined $self->TransactionObj->Message->First
- && $self->TransactionObj->Message->First->GetHeader('RT-Control') =~ /\bno-autoopen\b/i )
- ) {
+ my $status = $self->TicketObj->Status;
+ return undef if $status eq 'open';
+ return undef if $status eq 'new' && $self->TransactionObj->IsInbound;
- return undef;
- }
- else {
- return (1);
+ if ( my $msg = $self->TransactionObj->Message->First ) {
+ return undef if ($msg->GetHeader('RT-Control') || '') =~ /\bno-autoopen\b/i;
}
+
+ return 1;
}
# }}}
diff --git a/rt/lib/RT/Action/Autoreply.pm b/rt/lib/RT/Action/Autoreply.pm
index c1ac5f897..37dda00a7 100755
--- a/rt/lib/RT/Action/Autoreply.pm
+++ b/rt/lib/RT/Action/Autoreply.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
diff --git a/rt/lib/RT/Action/CreateTickets.pm b/rt/lib/RT/Action/CreateTickets.pm
index b708f2ea5..4e72e1151 100644
--- a/rt/lib/RT/Action/CreateTickets.pm
+++ b/rt/lib/RT/Action/CreateTickets.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
@@ -188,7 +190,7 @@ A complete list of acceptable fields for this beastie:
Started =>
Resolved =>
Owner => Username or id of an RT user who can and should own
- this ticket
+ this ticket; forces the owner if necessary
+ Requestor => Email address
+ Cc => Email address
+ AdminCc => Email address
@@ -208,8 +210,15 @@ A complete list of acceptable fields for this beastie:
within a template after a Content: header is treated
as content until we hit a line containing only
ENDOFCONTENT
- ContentType => the content-type of the Content field
+ ContentType => the content-type of the Content field. Defaults to
+ 'text/plain'
+ UpdateType => 'correspond' or 'comment'; used in conjunction with
+ 'content' if this is an update. Defaults to
+ 'correspond'
+
CustomField-<id#> => custom field value
+ CF-name => custom field value
+ CustomField-name => custom field value
Fields marked with an * are required.
@@ -545,7 +554,10 @@ sub Prepare {
}
- $self->Parse( Content => $self->TemplateObj->Content, _ActiveContent => 1);
+ $self->Parse(
+ Content => $self->TemplateObj->Content,
+ _ActiveContent => 1
+ );
return 1;
}
@@ -566,43 +578,41 @@ sub CreateByTemplate {
use bytes;
local %T::Tickets = %T::Tickets;
- local $T::TOP = $T::TOP;
- local $T::ID = $T::ID;
+ local $T::TOP = $T::TOP;
+ local $T::ID = $T::ID;
$T::Tickets{'TOP'} = $T::TOP = $top if $top;
my $ticketargs;
my ( @links, @postponed );
foreach my $template_id ( @{ $self->{'create_tickets'} } ) {
$RT::Logger->debug("Workflow: processing $template_id of $T::TOP")
- if $T::TOP;
+ if $T::TOP;
$T::ID = $template_id;
@T::AllID = @{ $self->{'create_tickets'} };
- ( $T::Tickets{$template_id}, $ticketargs ) =
- $self->ParseLines( $template_id, \@links, \@postponed );
+ ( $T::Tickets{$template_id}, $ticketargs )
+ = $self->ParseLines( $template_id, \@links, \@postponed );
# Now we have a %args to work with.
# Make sure we have at least the minimum set of
# reasonable data and do our thang
- my ( $id, $transid, $msg ) =
- $T::Tickets{$template_id}->Create(%$ticketargs);
+ my ( $id, $transid, $msg )
+ = $T::Tickets{$template_id}->Create(%$ticketargs);
foreach my $res ( split( '\n', $msg ) ) {
push @results,
- $T::Tickets{$template_id}
- ->loc( "Ticket [_1]", $T::Tickets{$template_id}->Id ) . ': '
- . $res;
+ $T::Tickets{$template_id}
+ ->loc( "Ticket [_1]", $T::Tickets{$template_id}->Id ) . ': '
+ . $res;
}
if ( !$id ) {
if ( $self->TicketObj ) {
- $msg =
- "Couldn't create related ticket $template_id for "
- . $self->TicketObj->Id . " "
- . $msg;
- }
- else {
+ $msg = "Couldn't create related ticket $template_id for "
+ . $self->TicketObj->Id . " "
+ . $msg;
+ } else {
$msg = "Couldn't create ticket $template_id " . $msg;
}
@@ -612,8 +622,8 @@ sub CreateByTemplate {
$RT::Logger->debug("Assigned $template_id with $id");
$T::Tickets{$template_id}->SetOriginObj( $self->TicketObj )
- if $self->TicketObj
- && $T::Tickets{$template_id}->can('SetOriginObj');
+ if $self->TicketObj
+ && $T::Tickets{$template_id}->can('SetOriginObj');
}
@@ -631,7 +641,7 @@ sub UpdateByTemplate {
my @results;
local %T::Tickets = %T::Tickets;
- local $T::ID = $T::ID;
+ local $T::ID = $T::ID;
my $ticketargs;
my ( @links, @postponed );
@@ -641,37 +651,35 @@ sub UpdateByTemplate {
$T::ID = $template_id;
@T::AllID = @{ $self->{'update_tickets'} };
- ( $T::Tickets{$template_id}, $ticketargs ) =
- $self->ParseLines( $template_id, \@links, \@postponed );
+ ( $T::Tickets{$template_id}, $ticketargs )
+ = $self->ParseLines( $template_id, \@links, \@postponed );
# Now we have a %args to work with.
# Make sure we have at least the minimum set of
# reasonable data and do our thang
my @attribs = qw(
- Subject
- FinalPriority
- Priority
- TimeEstimated
- TimeWorked
- TimeLeft
- Status
- Queue
- Due
- Starts
- Started
- Resolved
+ Subject
+ FinalPriority
+ Priority
+ TimeEstimated
+ TimeWorked
+ TimeLeft
+ Status
+ Queue
+ Due
+ Starts
+ Started
+ Resolved
);
my $id = $template_id;
$id =~ s/update-(\d+).*/$1/;
- $T::Tickets{$template_id}->Load($id);
-
- my $msg;
- if ( !$T::Tickets{$template_id}->Id ) {
- $msg = "Couldn't update ticket $template_id " . $msg;
+ my ($loaded, $msg) = $T::Tickets{$template_id}->LoadById($id);
- $RT::Logger->error($msg);
+ unless ( $loaded ) {
+ $RT::Logger->error("Couldn't update ticket $template_id: " . $msg);
+ push @results, $self->loc( "Couldn't load ticket '[_1]'", $id );
next;
}
@@ -681,60 +689,68 @@ sub UpdateByTemplate {
my $base_id = "base-$1";
my $base = $self->{'templates'}->{$base_id};
if ($base) {
- $base =~ s/\r//g;
- $base =~ s/\n+$//;
- $current =~ s/\n+$//;
-
- # If we have no base template, set what we can.
- if ($base ne $current) {
- push @results,
- "Could not update ticket "
- . $T::Tickets{$template_id}->Id
- . ": Ticket has changed";
- next;
- }
+ $base =~ s/\r//g;
+ $base =~ s/\n+$//;
+ $current =~ s/\n+$//;
+
+ # If we have no base template, set what we can.
+ if ( $base ne $current ) {
+ push @results,
+ "Could not update ticket "
+ . $T::Tickets{$template_id}->Id
+ . ": Ticket has changed";
+ next;
+ }
}
push @results, $T::Tickets{$template_id}->Update(
AttributesRef => \@attribs,
ARGSRef => $ticketargs
);
+ if ( $ticketargs->{'Owner'} ) {
+ ($id, $msg) = $T::Tickets{$template_id}->SetOwner($ticketargs->{'Owner'}, "Force");
+ push @results, $msg unless $msg eq $self->loc("That user already owns that ticket");
+ }
+
push @results,
- $self->UpdateWatchers( $T::Tickets{$template_id}, $ticketargs );
+ $self->UpdateWatchers( $T::Tickets{$template_id}, $ticketargs );
- next unless exists $ticketargs->{'UpdateType'};
- if ( $ticketargs->{'UpdateType'} =~ /^(private|public)$/ ) {
- my ( $Transaction, $Description, $Object ) =
- $T::Tickets{$template_id}->Comment(
- CcMessageTo => $ticketargs->{'Cc'},
+ push @results,
+ $self->UpdateCustomFields( $T::Tickets{$template_id}, $ticketargs );
+
+ next unless $ticketargs->{'MIMEObj'};
+ if ( $ticketargs->{'UpdateType'} =~ /^(private|comment)$/i ) {
+ my ( $Transaction, $Description, $Object )
+ = $T::Tickets{$template_id}->Comment(
BccMessageTo => $ticketargs->{'Bcc'},
MIMEObj => $ticketargs->{'MIMEObj'},
TimeTaken => $ticketargs->{'TimeWorked'}
- );
+ );
push( @results,
$T::Tickets{$template_id}
- ->loc( "Ticket [_1]", $T::Tickets{$template_id}->id ) . ': '
- . $Description );
- }
- elsif ( $ticketargs->{'UpdateType'} eq 'response' ) {
- my ( $Transaction, $Description, $Object ) =
- $T::Tickets{$template_id}->Correspond(
- CcMessageTo => $ticketargs->{'Cc'},
+ ->loc( "Ticket [_1]", $T::Tickets{$template_id}->id )
+ . ': '
+ . $Description );
+ } elsif ( $ticketargs->{'UpdateType'} =~ /^(public|response|correspond)$/i ) {
+ my ( $Transaction, $Description, $Object )
+ = $T::Tickets{$template_id}->Correspond(
BccMessageTo => $ticketargs->{'Bcc'},
MIMEObj => $ticketargs->{'MIMEObj'},
TimeTaken => $ticketargs->{'TimeWorked'}
- );
- push( @results,
- $T::Tickets{$template_id}
- ->loc( "Ticket [_1]", $T::Tickets{$template_id}->id ) . ': '
- . $Description );
- }
- else {
+ );
push( @results,
$T::Tickets{$template_id}
- ->loc("Update type was neither correspondence nor comment.")
- . " "
- . $T::Tickets{$template_id}->loc("Update not recorded.") );
+ ->loc( "Ticket [_1]", $T::Tickets{$template_id}->id )
+ . ': '
+ . $Description );
+ } else {
+ push(
+ @results,
+ $T::Tickets{$template_id}->loc(
+ "Update type was neither correspondence nor comment.")
+ . " "
+ . $T::Tickets{$template_id}->loc("Update not recorded.")
+ );
}
}
@@ -753,35 +769,58 @@ allowing you to embed active perl in your templates.
=cut
sub Parse {
- my $self = shift;
- my %args = ( Content => undef,
- Queue => undef,
- Requestor => undef,
- _ActiveContent => undef,
- @_);
-
- if ($args{'_ActiveContent'}) {
- $self->{'UsePerlTextTemplate'} =1;
+ my $self = shift;
+ my %args = (
+ Content => undef,
+ Queue => undef,
+ Requestor => undef,
+ _ActiveContent => undef,
+ @_
+ );
+
+ if ( $args{'_ActiveContent'} ) {
+ $self->{'UsePerlTextTemplate'} = 1;
} else {
$self->{'UsePerlTextTemplate'} = 0;
}
- my @template_order;
+ if ( substr( $args{'Content'}, 0, 3 ) eq '===' ) {
+ $self->_ParseMultilineTemplate(%args);
+ } elsif ( $args{'Content'} =~ /(?:\t|,)/i ) {
+ $self->_ParseXSVTemplate(%args);
+
+ }
+}
+
+=head2 _ParseMultilineTemplate
+
+Parses mulitline templates. Things like:
+
+ ===Create-Ticket ...
+
+Takes the same arguments as Parse
+
+=cut
+
+sub _ParseMultilineTemplate {
+ my $self = shift;
+ my %args = (@_);
+
my $template_id;
my ( $queue, $requestor );
- if ( substr( $args{'Content'}, 0, 3 ) eq '===' ) {
$RT::Logger->debug("Line: ===");
foreach my $line ( split( /\n/, $args{'Content'} ) ) {
$line =~ s/\r$//;
$RT::Logger->debug("Line: $line");
if ( $line =~ /^===/ ) {
if ( $template_id && !$queue && $args{'Queue'} ) {
- $self->{'templates'}->{$template_id} .= "Queue: $args{'Queue'}\n";
+ $self->{'templates'}->{$template_id}
+ .= "Queue: $args{'Queue'}\n";
}
if ( $template_id && !$requestor && $args{'Requestor'} ) {
- $self->{'templates'}->{$template_id} .=
- "Requestor: $args{'Requestor'}\n";
+ $self->{'templates'}->{$template_id}
+ .= "Requestor: $args{'Requestor'}\n";
}
$queue = 0;
$requestor = 0;
@@ -790,37 +829,33 @@ sub Parse {
$template_id = "create-$1";
$RT::Logger->debug("**** Create ticket: $template_id");
push @{ $self->{'create_tickets'} }, $template_id;
- }
- elsif ( $line =~ /^===Update-Ticket: (.*)$/ ) {
+ } elsif ( $line =~ /^===Update-Ticket: (.*)$/ ) {
$template_id = "update-$1";
$RT::Logger->debug("**** Update ticket: $template_id");
push @{ $self->{'update_tickets'} }, $template_id;
- }
- elsif ( $line =~ /^===Base-Ticket: (.*)$/ ) {
+ } elsif ( $line =~ /^===Base-Ticket: (.*)$/ ) {
$template_id = "base-$1";
$RT::Logger->debug("**** Base ticket: $template_id");
push @{ $self->{'base_tickets'} }, $template_id;
- }
- elsif ( $line =~ /^===#.*$/ ) { # a comment
+ } elsif ( $line =~ /^===#.*$/ ) { # a comment
next;
- }
- else {
+ } else {
if ( $line =~ /^Queue:(.*)/i ) {
$queue = 1;
my $value = $1;
$value =~ s/^\s//;
$value =~ s/\s$//;
- if ( !$value && $args{'Queue'}) {
+ if ( !$value && $args{'Queue'} ) {
$value = $args{'Queue'};
$line = "Queue: $value";
}
}
- if ( $line =~ /^Requestor:(.*)/i ) {
+ if ( $line =~ /^Requestors?:(.*)/i ) {
$requestor = 1;
my $value = $1;
$value =~ s/^\s//;
$value =~ s/\s$//;
- if ( !$value && $args{'Requestor'}) {
+ if ( !$value && $args{'Requestor'} ) {
$value = $args{'Requestor'};
$line = "Requestor: $value";
}
@@ -828,118 +863,10 @@ sub Parse {
$self->{'templates'}->{$template_id} .= $line . "\n";
}
}
- if ( $template_id && !$queue && $args{'Queue'} ) {
- $self->{'templates'}->{$template_id} .= "Queue: $args{'Queue'}\n";
- }
- }
- elsif ( substr( $args{'Content'}, 0, 2 ) =~ /^id$/i ) {
- $RT::Logger->debug("Line: id");
- use Regexp::Common qw(delimited);
- my $first = substr( $args{'Content'}, 0, index( $args{'Content'}, "\n" ) );
- $first =~ s/\r$//;
-
- my $delimiter;
- if ( $first =~ /\t/ ) {
- $delimiter = "\t";
- }
- else {
- $delimiter = ',';
- }
- my @fields = split( /$delimiter/, $first );
-
-
- my $delimiter_re = qr[$delimiter];
-
- my $delimited = qr[[^$delimiter]+];
- my $empty = qr[^[$delimiter](?=[$delimiter])];
- my $justquoted = qr[$RE{quoted}];
-
- $args{'Content'} = substr( $args{'Content'}, index( $args{'Content'}, "\n" ) + 1 );
- $RT::Logger->debug("First: $first");
-
- my $queue;
- foreach my $line ( split( /\n/, $args{'Content'} ) ) {
- next unless $line;
- $RT::Logger->debug("Line: $line");
-
- # first item is $template_id
- my $i = 0;
- my $template_id;
- while ($line && $line =~ s/^($justquoted|.*?)(?:$delimiter_re|$)//ix) {
- if ( $i == 0 ) {
- $queue = 0;
- $requestor = 0;
- my $tid = $1;
- $tid =~ s/^\s//;
- $tid =~ s/\s$//;
- next unless $tid;
-
-
- if ($tid =~ /^\d+$/) {
- $template_id = 'update-' . $tid;
- push @{ $self->{'update_tickets'} }, $template_id;
-
- } elsif ($tid =~ /^#base-(\d+)$/) {
-
- $template_id = 'base-' . $1;
- push @{ $self->{'base_tickets'} }, $template_id;
-
- } else {
- $template_id = 'create-' . $tid;
- push @{ $self->{'create_tickets'} }, $template_id;
- }
- $RT::Logger->debug("template_id: $tid");
- }
- else {
- my $value = $1;
- $value = '' if ( $value =~ /^$delimiter$/ );
- if ($value =~ /^$RE{delimited}{-delim=>qq{\'\"}}$/) {
- substr($value,0,1) = "";
- substr($value,-1,1) = "";
- }
- my $field = $fields[$i];
- next unless $field;
- $field =~ s/^\s//;
- $field =~ s/\s$//;
- if ( $field =~ /Body/i
- || $field =~ /Data/i
- || $field =~ /Message/i )
- {
- $field = 'Content';
- }
- if ( $field =~ /Summary/i ) {
- $field = 'Subject';
- }
- if ( $field =~ /Queue/i ) {
- $queue = 1;
- if ( !$value && $args{'Queue'} ) {
- $value = $args{'Queue'};
- }
- }
- if ( $field =~ /Requestor/i ) {
- $requestor = 1;
- if ( !$value && $args{'Requestor'} ) {
- $value = $args{'Requestor'};
- }
- }
- $self->{'templates'}->{$template_id} .= $field . ": ";
- $self->{'templates'}->{$template_id} .= $value || "";
- $self->{'templates'}->{$template_id} .= "\n";
- $self->{'templates'}->{$template_id} .= "ENDOFCONTENT\n"
- if $field =~ /content/i;
- }
- $i++;
- }
- if ( !$queue && $args{'Queue'} ) {
- $self->{'templates'}->{$template_id} .= "Queue: $args{'Queue'}\n";
- }
- if ( !$requestor && $args{'Requestor'} ) {
- $self->{'templates'}->{$template_id} .=
- "Requestor: $args{'Requestor'}\n";
- }
+ if ( $template_id && !$queue && $args{'Queue'} ) {
+ $self->{'templates'}->{$template_id} .= "Queue: $args{'Queue'}\n";
}
}
-}
sub ParseLines {
my $self = shift;
@@ -947,7 +874,6 @@ sub ParseLines {
my $links = shift;
my $postponed = shift;
-
my $content = $self->{'templates'}->{$template_id};
if ( $self->{'UsePerlTextTemplate'} ) {
@@ -980,69 +906,77 @@ sub ParseLines {
next;
}
}
-
- my $TicketObj ||= RT::Ticket->new($self->CurrentUser);
+
+ my $TicketObj ||= RT::Ticket->new( $self->CurrentUser );
my %args;
+ my %original_tags;
my @lines = ( split( /\n/, $content ) );
while ( defined( my $line = shift @lines ) ) {
if ( $line =~ /^(.*?):(?:\s+)(.*?)(?:\s*)$/ ) {
my $value = $2;
- my $tag = lc($1);
+ my $original_tag = $1;
+ my $tag = lc($original_tag);
$tag =~ s/-//g;
+ $tag =~ s/^(requestor|cc|admincc)s?$/$1/i;
+
+ $original_tags{$tag} = $original_tag;
if ( ref( $args{$tag} ) )
{ #If it's an array, we want to push the value
push @{ $args{$tag} }, $value;
- }
- elsif ( defined( $args{$tag} ) )
+ } elsif ( defined( $args{$tag} ) )
{ #if we're about to get a second value, make it an array
$args{$tag} = [ $args{$tag}, $value ];
- }
- else { #if there's nothing there, just set the value
+ } else { #if there's nothing there, just set the value
$args{$tag} = $value;
}
- if ( $tag eq 'content' ) { #just build up the content
+ if ( $tag =~ /^content$/i ) { #just build up the content
# convert it to an array
$args{$tag} = defined($value) ? [ $value . "\n" ] : [];
while ( defined( my $l = shift @lines ) ) {
last if ( $l =~ /^ENDOFCONTENT\s*$/ );
push @{ $args{'content'} }, $l . "\n";
}
- }
- else {
-
+ } else {
# if it's not content, strip leading and trailing spaces
if ( $args{$tag} ) {
$args{$tag} =~ s/^\s+//g;
$args{$tag} =~ s/\s+$//g;
}
+ if (($tag =~ /^(requestor|cc|admincc)$/i or grep {lc $_ eq $tag} keys %LINKTYPEMAP) and $args{$tag} =~ /,/) {
+ $args{$tag} = [ split /,\s*/, $args{$tag} ];
+ }
}
}
}
foreach my $date qw(due starts started resolved) {
- my $dateobj = RT::Date->new($self->CurrentUser);
+ my $dateobj = RT::Date->new( $self->CurrentUser );
next unless $args{$date};
if ( $args{$date} =~ /^\d+$/ ) {
$dateobj->Set( Format => 'unix', Value => $args{$date} );
- }
- else {
- $dateobj->Set( Format => 'unknown', Value => $args{$date} );
+ } else {
+ eval {
+ $dateobj->Set( Format => 'iso', Value => $args{$date} );
+ };
+ if ($@ or $dateobj->Unix <= 0) {
+ $dateobj->Set( Format => 'unknown', Value => $args{$date} );
+ }
}
$args{$date} = $dateobj->ISO;
}
$args{'requestor'} ||= $self->TicketObj->Requestors->MemberEmailAddresses
- if $self->TicketObj;
+ if $self->TicketObj;
$args{'type'} ||= 'ticket';
my %ticketargs = (
Queue => $args{'queue'},
Subject => $args{'subject'},
- Status => 'new',
+ Status => $args{'status'} || 'new',
Due => $args{'due'},
Starts => $args{'starts'},
Started => $args{'started'},
@@ -1059,19 +993,32 @@ sub ParseLines {
Type => $args{'type'},
);
- if ($args{content}) {
+ if ( $args{content} ) {
my $mimeobj = MIME::Entity->new();
$mimeobj->build(
- Type => $args{'contenttype'},
+ Type => $args{'contenttype'} || 'text/plain',
Data => $args{'content'}
);
$ticketargs{MIMEObj} = $mimeobj;
- $ticketargs{UpdateType} = $args{'updatetype'} if $args{'updatetype'};
+ $ticketargs{UpdateType} = $args{'updatetype'} || 'correspond';
}
- foreach my $key ( keys(%args) ) {
- $key =~ /^customfield(\d+)$/ or next;
- $ticketargs{ "CustomField-" . $1 } = $args{$key};
+ foreach my $tag ( keys(%args) ) {
+ # if the tag was added later, skip it
+ my $orig_tag = $original_tags{$tag} or next;
+ if ( $orig_tag =~ /^customfield-?(\d+)$/i ) {
+ $ticketargs{ "CustomField-" . $1 } = $args{$tag};
+ } elsif ( $orig_tag =~ /^(?:customfield|cf)-?(.*)$/i ) {
+ my $cf = RT::CustomField->new( $self->CurrentUser );
+ $cf->LoadByName( Name => $1, Queue => $ticketargs{Queue} );
+ $ticketargs{ "CustomField-" . $cf->id } = $args{$tag};
+ } elsif ($orig_tag) {
+ my $cf = RT::CustomField->new( $self->CurrentUser );
+ $cf->LoadByName( Name => $orig_tag, Queue => $ticketargs{Queue} );
+ next unless ($cf->id) ;
+ $ticketargs{ "CustomField-" . $cf->id } = $args{$tag};
+
+ }
}
$self->GetDeferred( \%args, $template_id, $links, $postponed );
@@ -1079,6 +1026,137 @@ sub ParseLines {
return $TicketObj, \%ticketargs;
}
+
+=head2 _ParseXSVTemplate
+
+Parses a tab or comma delimited template. Should only ever be called by Parse
+
+=cut
+
+sub _ParseXSVTemplate {
+ my $self = shift;
+ my %args = (@_);
+
+ use Regexp::Common qw(delimited);
+ my($first, $content) = split(/\r?\n/, $args{'Content'}, 2);
+
+ my $delimiter;
+ if ( $first =~ /\t/ ) {
+ $delimiter = "\t";
+ } else {
+ $delimiter = ',';
+ }
+ my @fields = split( /$delimiter/, $first );
+
+ my $delimiter_re = qr[$delimiter];
+ my $justquoted = qr[$RE{quoted}];
+
+ # Used to generate automatic template ids
+ my $autoid = 1;
+
+ LINE:
+ while ($content) {
+ $content =~ s/^(\s*\r?\n)+//;
+
+ # Keep track of Queue and Requestor, so we can provide defaults
+ my $queue;
+ my $requestor;
+
+ # The template for this line
+ my $template;
+
+ # What column we're on
+ my $i = 0;
+
+ # If the last iteration was the end of the line
+ my $EOL = 0;
+
+ # The template id
+ my $template_id;
+
+ COLUMN:
+ while (not $EOL and length $content and $content =~ s/^($justquoted|.*?)($delimiter_re|$)//smix) {
+ $EOL = not $2;
+
+ # Strip off quotes, if they exist
+ my $value = $1;
+ if ( $value =~ /^$RE{delimited}{-delim=>qq{\'\"}}$/ ) {
+ substr( $value, 0, 1 ) = "";
+ substr( $value, -1, 1 ) = "";
+ }
+
+ # What column is this?
+ my $field = $fields[$i++];
+ next COLUMN unless $field =~ /\S/;
+ $field =~ s/^\s//;
+ $field =~ s/\s$//;
+
+ if ( $field =~ /^id$/i ) {
+ # Special case if this is the ID column
+ if ( $value =~ /^\d+$/ ) {
+ $template_id = 'update-' . $value;
+ push @{ $self->{'update_tickets'} }, $template_id;
+ } elsif ( $value =~ /^#base-(\d+)$/ ) {
+ $template_id = 'base-' . $1;
+ push @{ $self->{'base_tickets'} }, $template_id;
+ } elsif ( $value =~ /\S/ ) {
+ $template_id = 'create-' . $value;
+ push @{ $self->{'create_tickets'} }, $template_id;
+ }
+ } else {
+ # Some translations
+ if ( $field =~ /^Body$/i
+ || $field =~ /^Data$/i
+ || $field =~ /^Message$/i )
+ {
+ $field = 'Content';
+ } elsif ( $field =~ /^Summary$/i ) {
+ $field = 'Subject';
+ } elsif ( $field =~ /^Queue$/i ) {
+ # Note that we found a queue
+ $queue = 1;
+ $value ||= $args{'Queue'};
+ } elsif ( $field =~ /^Requestors?$/i ) {
+ $field = 'Requestor'; # Remove plural
+ # Note that we found a requestor
+ $requestor = 1;
+ $value ||= $args{'Requestor'};
+ }
+
+ # Tack onto the end of the template
+ $template .= $field . ": ";
+ $template .= (defined $value ? $value : "");
+ $template .= "\n";
+ $template .= "ENDOFCONTENT\n"
+ if $field =~ /^Content$/i;
+ }
+ }
+
+ # Ignore blank lines
+ next unless $template;
+
+ # If we didn't find a queue of requestor, tack on the defaults
+ if ( !$queue && $args{'Queue'} ) {
+ $template .= "Queue: $args{'Queue'}\n";
+ }
+ if ( !$requestor && $args{'Requestor'} ) {
+ $template .= "Requestor: $args{'Requestor'}\n";
+ }
+
+ # If we never found an ID, come up with one
+ unless ($template_id) {
+ $autoid++ while exists $self->{'templates'}->{"create-auto-$autoid"};
+ $template_id = "create-auto-$autoid";
+ # Also, it's a ticket to create
+ push @{ $self->{'create_tickets'} }, $template_id;
+ }
+
+ # Save the template we generated
+ $self->{'templates'}->{$template_id} = $template;
+
+ }
+}
+
sub GetDeferred {
my $self = shift;
my $args = shift;
@@ -1088,17 +1166,16 @@ sub GetDeferred {
# Deferred processing
push @$links,
- (
+ (
$id,
- {
- DependsOn => $args->{'dependson'},
+ { DependsOn => $args->{'dependson'},
DependedOnBy => $args->{'dependedonby'},
RefersTo => $args->{'refersto'},
ReferredToBy => $args->{'referredtoby'},
Children => $args->{'children'},
Parents => $args->{'parents'},
}
- );
+ );
push @$postponed, (
@@ -1115,7 +1192,7 @@ sub GetUpdateTemplate {
$string .= "Queue: " . $t->QueueObj->Name . "\n";
$string .= "Subject: " . $t->Subject . "\n";
$string .= "Status: " . $t->Status . "\n";
- $string .= "UpdateType: response\n";
+ $string .= "UpdateType: correspond\n";
$string .= "Content: \n";
$string .= "ENDOFCONTENT\n";
$string .= "Due: " . $t->DueObj->AsString . "\n";
@@ -1234,14 +1311,31 @@ sub UpdateWatchers {
foreach my $type qw(Requestor Cc AdminCc) {
my $method = $type . 'Addresses';
my $oldaddr = $ticket->$method;
-
-
+
# Skip unless we have a defined field
next unless defined $args->{$type};
my $newaddr = $args->{$type};
- my @old = split( ', ', $oldaddr );
- my @new = split( ', ', $newaddr );
+ my @old = split( /,\s*/, $oldaddr );
+ my @new;
+ for (ref $newaddr ? @{$newaddr} : split( /,\s*/, $newaddr )) {
+ # Sometimes these are email addresses, sometimes they're
+ # users. Try to guess which is which, as we want to deal
+ # with email addresses if at all possible.
+ if (/^\S+@\S+$/) {
+ push @new, $_;
+ } else {
+ # It doesn't look like an email address. Try to load it.
+ my $user = RT::User->new($self->CurrentUser);
+ $user->Load($_);
+ if ($user->Id) {
+ push @new, $user->EmailAddress;
+ } else {
+ push @new, $_;
+ }
+ }
+ }
+
my %oldhash = map { $_ => 1 } @old;
my %newhash = map { $_ => 1 } @new;
@@ -1255,7 +1349,7 @@ sub UpdateWatchers {
);
push @results,
- $ticket->loc( "Ticket [_1]", $ticket->Id ) . ': ' . $msg;
+ $ticket->loc( "Ticket [_1]", $ticket->Id ) . ': ' . $msg;
}
foreach (@delete) {
@@ -1264,7 +1358,47 @@ sub UpdateWatchers {
Email => $_
);
push @results,
- $ticket->loc( "Ticket [_1]", $ticket->Id ) . ': ' . $msg;
+ $ticket->loc( "Ticket [_1]", $ticket->Id ) . ': ' . $msg;
+ }
+ }
+ return @results;
+}
+
+sub UpdateCustomFields {
+ my $self = shift;
+ my $ticket = shift;
+ my $args = shift;
+
+ my @results;
+ foreach my $arg (keys %{$args}) {
+ next unless $arg =~ /^CustomField-(\d+)$/;
+ my $cf = $1;
+
+ my $CustomFieldObj = RT::CustomField->new($self->CurrentUser);
+ $CustomFieldObj->LoadById($cf);
+
+ my @values;
+ if ($CustomFieldObj->Type =~ /text/i) { # Both Text and Wikitext
+ @values = ($args->{$arg});
+ } else {
+ @values = split /\n/, $args->{$arg};
+ }
+
+ if ( ($CustomFieldObj->Type eq 'Freeform'
+ && ! $CustomFieldObj->SingleValue) ||
+ $CustomFieldObj->Type =~ /text/i) {
+ foreach my $val (@values) {
+ $val =~ s/\r//g;
+ }
+ }
+
+ foreach my $value (@values) {
+ next unless length($value);
+ my ( $val, $msg ) = $ticket->AddCustomFieldValue(
+ Field => $cf,
+ Value => $value
+ );
+ push ( @results, $msg );
}
}
return @results;
@@ -1289,21 +1423,22 @@ sub PostProcess {
{
next unless $link;
- if ($link =~ /^TOP$/i) {
- $RT::Logger->debug( "Building $type link for $link: " . $T::Tickets{TOP}->Id );
+ if ( $link =~ /^TOP$/i ) {
+ $RT::Logger->debug( "Building $type link for $link: "
+ . $T::Tickets{TOP}->Id );
$link = $T::Tickets{TOP}->Id;
- }
- elsif ( $link !~ m/^\d+$/ ) {
+ } elsif ( $link !~ m/^\d+$/ ) {
my $key = "create-$link";
if ( !exists $T::Tickets{$key} ) {
- $RT::Logger->debug( "Skipping $type link for $key (non-existent)");
+ $RT::Logger->debug(
+ "Skipping $type link for $key (non-existent)");
next;
}
- $RT::Logger->debug( "Building $type link for $link: " . $T::Tickets{$key}->Id );
+ $RT::Logger->debug( "Building $type link for $link: "
+ . $T::Tickets{$key}->Id );
$link = $T::Tickets{$key}->Id;
- }
- else {
+ } else {
$RT::Logger->debug("Building $type link for $link");
}
@@ -1314,7 +1449,7 @@ sub PostProcess {
);
$RT::Logger->warning("AddLink thru $link failed: $wmsg")
- unless $wval;
+ unless $wval;
# push @non_fatal_errors, $wmsg unless ($wval);
}
@@ -1325,7 +1460,7 @@ sub PostProcess {
# postponed actions -- Status only, currently
while ( my $template_id = shift(@$postponed) ) {
my $ticket = $T::Tickets{$template_id};
- $RT::Logger->debug("Handling postponed actions for ".$ticket->id);
+ $RT::Logger->debug( "Handling postponed actions for " . $ticket->id );
my %args = %{ shift(@$postponed) };
$ticket->SetStatus( $args{Status} ) if defined $args{Status};
}
diff --git a/rt/lib/RT/Action/EscalatePriority.pm b/rt/lib/RT/Action/EscalatePriority.pm
index c54992166..1a62aab01 100644
--- a/rt/lib/RT/Action/EscalatePriority.pm
+++ b/rt/lib/RT/Action/EscalatePriority.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
@@ -43,7 +45,6 @@
# those contributions and any derivatives thereof.
#
# END BPS TAGGED BLOCK }}}
-
=head1 NAME
RT::Action::EscalatePriority
diff --git a/rt/lib/RT/Action/Generic.pm b/rt/lib/RT/Action/Generic.pm
index cf7600a63..166e7aa9b 100755
--- a/rt/lib/RT/Action/Generic.pm
+++ b/rt/lib/RT/Action/Generic.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
@@ -43,7 +45,6 @@
# those contributions and any derivatives thereof.
#
# END BPS TAGGED BLOCK }}}
-
=head1 NAME
RT::Action::Generic - a generic baseclass for RT Actions
diff --git a/rt/lib/RT/Action/Notify.pm b/rt/lib/RT/Action/Notify.pm
index 0daaa5586..8a7d7c9a7 100755
--- a/rt/lib/RT/Action/Notify.pm
+++ b/rt/lib/RT/Action/Notify.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
diff --git a/rt/lib/RT/Action/NotifyAsComment.pm b/rt/lib/RT/Action/NotifyAsComment.pm
index f7cc87543..d74b21d91 100755
--- a/rt/lib/RT/Action/NotifyAsComment.pm
+++ b/rt/lib/RT/Action/NotifyAsComment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
diff --git a/rt/lib/RT/Action/RecordComment.pm b/rt/lib/RT/Action/RecordComment.pm
index d9740dcd1..285b33f04 100644
--- a/rt/lib/RT/Action/RecordComment.pm
+++ b/rt/lib/RT/Action/RecordComment.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
diff --git a/rt/lib/RT/Action/RecordCorrespondence.pm b/rt/lib/RT/Action/RecordCorrespondence.pm
index 62255ec53..c01c89ac5 100644
--- a/rt/lib/RT/Action/RecordCorrespondence.pm
+++ b/rt/lib/RT/Action/RecordCorrespondence.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
diff --git a/rt/lib/RT/Action/ResolveMembers.pm b/rt/lib/RT/Action/ResolveMembers.pm
index 00813181c..a28d88d08 100644
--- a/rt/lib/RT/Action/ResolveMembers.pm
+++ b/rt/lib/RT/Action/ResolveMembers.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
diff --git a/rt/lib/RT/Action/SendEmail.pm b/rt/lib/RT/Action/SendEmail.pm
index 431b97c75..d8ebbd87b 100755
--- a/rt/lib/RT/Action/SendEmail.pm
+++ b/rt/lib/RT/Action/SendEmail.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
@@ -56,6 +58,7 @@ use MIME::Words qw(encode_mimeword);
use RT::EmailParser;
use Mail::Address;
+use Date::Format qw(strftime);
=head1 NAME
@@ -99,7 +102,12 @@ perl(1).
sub Commit {
my $self = shift;
- return($self->SendMessage($self->TemplateObj->MIMEObj));
+ my ($ret) = $self->SendMessage( $self->TemplateObj->MIMEObj );
+ if ( $ret > 0 ) {
+ $self->RecordOutgoingMailTransaction( $self->TemplateObj->MIMEObj )
+ if ($RT::RecordOutgoingEmail);
+ }
+ return (abs $ret);
}
# }}}
@@ -247,18 +255,78 @@ sub SendMessage {
|| $MIMEObj->head->get('Bcc') )
{
$RT::Logger->info( $msgid . " No recipients found. Not sending.\n" );
- return (1);
+ return (-1);
+ }
+
+ unless ($MIMEObj->head->get('Date')) {
+ # We coerce localtime into an array since strftime has a flawed prototype that only accepts
+ # a list
+ $MIMEObj->head->replace(Date => strftime('%a, %d %b %Y %H:%M:%S %z', @{[localtime()]}));
+ }
+
+ return (0) unless ($self->OutputMIMEObject($MIMEObj));
+
+ my $success = $msgid . " sent ";
+ foreach( qw(To Cc Bcc) ) {
+ my $recipients = $MIMEObj->head->get($_);
+ $success .= " $_: ". $recipients if $recipients;
+ }
+ $success =~ s/\n//g;
+
+ $RT::Logger->info($success);
+
+ return (1);
+}
+
+
+=head2 OutputMIMEObject MIME::Entity
+
+Sends C<MIME::Entity> as an email message according to RT's mailer configuration.
+
+=cut
+
+
+
+sub OutputMIMEObject {
+ my $self = shift;
+ my $MIMEObj = shift;
+
+ my $msgid = $MIMEObj->head->get('Message-ID');
+ chomp $msgid;
+
+ my $SendmailArguments = $RT::SendmailArguments;
+ if (defined $RT::VERPPrefix && defined $RT::VERPDomain) {
+ my $EnvelopeFrom = $self->TransactionObj->CreatorObj->EmailAddress;
+ $EnvelopeFrom =~ s/@/=/g;
+ $EnvelopeFrom =~ s/\s//g;
+ $SendmailArguments .= " -f ${RT::VERPPrefix}${EnvelopeFrom}\@${RT::VERPDomain}";
}
if ( $RT::MailCommand eq 'sendmailpipe' ) {
eval {
- open( my $mail, "|$RT::SendmailPath $RT::SendmailArguments" ) || die $!;
+ # don't ignore CHLD signal to get proper exit code
+ local $SIG{'CHLD'} = 'DEFAULT';
+
+ my $mail;
+ unless( open $mail, "|$RT::SendmailPath $SendmailArguments" ) {
+ die "Couldn't run $RT::SendmailPath: $!";
+ }
+
+ # if something wrong with $mail->print we will get PIPE signal, handle it
+ local $SIG{'PIPE'} = sub { die "$RT::SendmailPath closed pipe" };
$MIMEObj->print($mail);
- close($mail);
+
+ unless ( close $mail ) {
+ die "Close failed: $!" if $!; # system error
+ # sendmail exit statuses mostly errors with data not software
+ # TODO: status parsing: core dump, exit on signal or EX_*
+ $RT::Logger->warning( "$RT::SendmailPath exitted with status $?" );
+ }
};
if ($@) {
- $RT::Logger->crit( $msgid . "Could not send mail. -" . $@ );
+ $RT::Logger->crit( $msgid . "Could not send mail: " . $@ );
+ return 0;
}
}
else {
@@ -267,7 +335,7 @@ sub SendMessage {
local $ENV{MAILADDRESS};
if ( $RT::MailCommand eq 'sendmail' ) {
- push @mailer_args, split(/\s+/, $RT::SendmailArguments);
+ push @mailer_args, split(/\s+/, $SendmailArguments);
}
elsif ( $RT::MailCommand eq 'smtp' ) {
$ENV{MAILADDRESS} = $RT::SMTPFrom || $MIMEObj->head->get('From');
@@ -283,20 +351,7 @@ sub SendMessage {
return (0);
}
}
-
- my $success =
- ( $msgid
- . " sent To: "
- . $MIMEObj->head->get('To') . " Cc: "
- . $MIMEObj->head->get('Cc') . " Bcc: "
- . $MIMEObj->head->get('Bcc') );
- $success =~ s/\n//gi;
-
- $self->RecordOutgoingMailTransaction($MIMEObj) if ($RT::RecordOutgoingEmail);
-
- $RT::Logger->info($success);
-
- return (1);
+ return 1;
}
# }}}
@@ -497,6 +552,10 @@ Remove addresses that are RT addresses or that are on this transaction's blackli
sub RemoveInappropriateRecipients {
my $self = shift;
+ my $msgid = $self->TemplateObj->MIMEObj->head->get ('Message-Id');
+
+
+
my @blacklist;
my @types = qw/To Cc Bcc/;
@@ -528,6 +587,7 @@ sub RemoveInappropriateRecipients {
@{ $self->{'Cc'} } = ();
@{ $self->{'Bcc'} } = ();
+ $RT::Logger->info( $msgid . " The incoming message was autogenerated. Not redistributing this message based on site configuration.\n");
}
elsif ( $RT::RedistributeAutoGeneratedMessages eq 'privileged' ) {
@@ -545,6 +605,7 @@ sub RemoveInappropriateRecipients {
}
}
+ $RT::Logger->info( $msgid . " The incoming message was autogenerated. Not redistributing this message to unprivileged users based on site configuration.\n");
}
@@ -609,7 +670,8 @@ sub SetReturnAddress {
unless ( $self->TemplateObj->MIMEObj->head->get('From') ) {
if ($RT::UseFriendlyFromLine) {
- my $friendly_name = $self->TransactionObj->CreatorObj->RealName;
+ my $friendly_name = $self->TransactionObj->CreatorObj->RealName
+ || $self->TransactionObj->CreatorObj->Name;
if ( $friendly_name =~ /^"(.*)"$/ ) { # a quoted string
$friendly_name = $1;
}
@@ -716,13 +778,18 @@ This routine fixes the RT tag in the subject. It's unlikely that you want to ove
sub SetSubjectToken {
my $self = shift;
- my $tag = "[$RT::rtname #" . $self->TicketObj->id . "]";
my $sub = $self->TemplateObj->MIMEObj->head->get('Subject');
- unless ( $sub =~ /\Q$tag\E/ ) {
- $sub =~ s/(\r\n|\n|\s)/ /gi;
- chomp $sub;
- $self->TemplateObj->MIMEObj->head->replace( 'Subject', "$tag $sub" );
- }
+ my $id = $self->TicketObj->id;
+
+ my $token_re = $RT::EmailSubjectTagRegex;
+ $token_re = qr/\Q$RT::rtname\E/o unless $token_re;
+ return if $sub =~ /\[$token_re\s+#$id\]/;
+
+ $sub =~ s/(\r\n|\n|\s)/ /gi;
+ chomp $sub;
+ $self->TemplateObj->MIMEObj->head->replace(
+ Subject => "[$RT::rtname #$id] $sub",
+ );
}
# }}}
diff --git a/rt/lib/RT/Action/SetPriority.pm b/rt/lib/RT/Action/SetPriority.pm
index c129bf0a2..4d74cc032 100644
--- a/rt/lib/RT/Action/SetPriority.pm
+++ b/rt/lib/RT/Action/SetPriority.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY:
diff --git a/rt/lib/RT/Action/UserDefined.pm b/rt/lib/RT/Action/UserDefined.pm
index 90653f68a..6aec928b8 100644
--- a/rt/lib/RT/Action/UserDefined.pm
+++ b/rt/lib/RT/Action/UserDefined.pm
@@ -2,7 +2,7 @@
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -22,7 +22,9 @@
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/copyleft/gpl.html.
#
#
# CONTRIBUTION SUBMISSION POLICY: