diff options
Diffstat (limited to 'rt/lib/RT/Action')
| -rw-r--r-- | rt/lib/RT/Action/AutoOpen.pm | 86 | ||||
| -rwxr-xr-x | rt/lib/RT/Action/Autoreply.pm | 40 | ||||
| -rw-r--r-- | rt/lib/RT/Action/CreateTickets.pm | 564 | ||||
| -rw-r--r-- | rt/lib/RT/Action/EscalatePriority.pm | 142 | ||||
| -rwxr-xr-x | rt/lib/RT/Action/Generic.pm | 56 | ||||
| -rwxr-xr-x | rt/lib/RT/Action/Notify.pm | 83 | ||||
| -rwxr-xr-x | rt/lib/RT/Action/NotifyAsComment.pm | 34 | ||||
| -rw-r--r-- | rt/lib/RT/Action/OpenDependent.pm | 55 | ||||
| -rw-r--r-- | rt/lib/RT/Action/ResolveMembers.pm | 35 | ||||
| -rwxr-xr-x | rt/lib/RT/Action/SendEmail.pm | 699 | ||||
| -rwxr-xr-x | rt/lib/RT/Action/SendPasswordEmail.pm | 170 | ||||
| -rw-r--r-- | rt/lib/RT/Action/SetPriority.pm | 61 | ||||
| -rw-r--r-- | rt/lib/RT/Action/StallDependent.pm | 68 | ||||
| -rw-r--r-- | rt/lib/RT/Action/UserDefined.pm | 71 | 
14 files changed, 575 insertions, 1589 deletions
| diff --git a/rt/lib/RT/Action/AutoOpen.pm b/rt/lib/RT/Action/AutoOpen.pm deleted file mode 100644 index ea6da1952..000000000 --- a/rt/lib/RT/Action/AutoOpen.pm +++ /dev/null @@ -1,86 +0,0 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK -# This Action will open the BASE if a dependent is resolved. - -package RT::Action::AutoOpen; -require RT::Action::Generic; - -use strict; -use vars qw/@ISA/; -@ISA=qw(RT::Action::Generic); - -#Do what we need to do and send it out. - -#What does this type of Action does - -# {{{ sub Describe  -sub Describe  { -  my $self = shift; -  return (ref $self ); -} -# }}} - - -# {{{ sub Prepare  -sub Prepare { -    my $self = shift; - -    # 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 ) -      ) { - -        return undef; -    } -    else { -        return (1); -    } -} -# }}} - -sub Commit { -    my $self = shift; -      my $oldstatus = $self->TicketObj->Status(); -        $self->TicketObj->__Set( Field => 'Status', Value => 'open' ); -        $self->TicketObj->_NewTransaction( -                         Type     => 'Set', -                         Field    => 'Status', -                         OldValue => $oldstatus, -                         NewValue => 'open', -                         Data => 'Ticket auto-opened on incoming correspondence' -        ); - - -    return(1); -} - -eval "require RT::Action::AutoOpen_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/AutoOpen_Vendor.pm}); -eval "require RT::Action::AutoOpen_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/AutoOpen_Local.pm}); - -1; diff --git a/rt/lib/RT/Action/Autoreply.pm b/rt/lib/RT/Action/Autoreply.pm index 81f7bddfa..624888e94 100755 --- a/rt/lib/RT/Action/Autoreply.pm +++ b/rt/lib/RT/Action/Autoreply.pm @@ -1,31 +1,7 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK +#$Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Action/Autoreply.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ +  package RT::Action::Autoreply;  require RT::Action::SendEmail; - -use strict; -use vars qw/@ISA/;  @ISA = qw(RT::Action::SendEmail); @@ -41,7 +17,7 @@ Sets the recipients of this message to this ticket's Requestor.  sub SetRecipients {      my $self=shift; -    push(@{$self->{'To'}}, $self->TicketObj->Requestors->MemberEmailAddresses); +    push(@{$self->{'To'}}, @{$self->TicketObj->Requestors->Emails});      return(1);  } @@ -63,7 +39,6 @@ sub SetReturnAddress {  		 @_  	       ); -    my $replyto;      if ($args{'is_comment'}) {   	$replyto = $self->TicketObj->QueueObj->CommentAddress ||   		     $RT::CommentAddress; @@ -74,9 +49,7 @@ sub SetReturnAddress {      }      unless ($self->TemplateObj->MIMEObj->head->get('From')) { -	my $friendly_name = $self->TicketObj->QueueObj->Description || -		$self->TicketObj->QueueObj->Name; -	$friendly_name =~ s/"/\\"/g; +	my $friendly_name=$self->TicketObj->QueueObj->Name;  	$self->SetHeader('From', "\"$friendly_name\" <$replyto>");      } @@ -88,9 +61,4 @@ sub SetReturnAddress {  # }}} -eval "require RT::Action::Autoreply_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/Autoreply_Vendor.pm}); -eval "require RT::Action::Autoreply_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/Autoreply_Local.pm}); -  1; diff --git a/rt/lib/RT/Action/CreateTickets.pm b/rt/lib/RT/Action/CreateTickets.pm deleted file mode 100644 index 0ab206771..000000000 --- a/rt/lib/RT/Action/CreateTickets.pm +++ /dev/null @@ -1,564 +0,0 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK -package RT::Action::CreateTickets; -require RT::Action::Generic; - -use strict; -use vars qw/@ISA/; -@ISA = qw(RT::Action::Generic); - -use MIME::Entity; - -=head1 NAME - - RT::Action::CreateTickets - -Create one or more tickets according to an externally supplied template. - - -=head1 SYNOPSIS - - ===Create-Ticket: codereview - Subject: Code review for {$Tickets{'TOP'}->Subject} - Depended-On-By: {$Tickets{'TOP'}->Id} - Content: Someone has created a ticket. you should review and approve it, - so they can finish their work - ENDOFCONTENT - -=head1 DESCRIPTION - - -Using the "CreateTickets" ScripAction and mandatory dependencies, RT now has  -the ability to model complex workflow. When a ticket is created in a queue -that has a "CreateTickets" scripaction, that ScripAction parses its "Template" - - - -=head2 FORMAT - -CreateTickets uses the template as a template for an ordered set of tickets  -to create. The basic format is as follows: - - - ===Create-Ticket: identifier - Param: Value - Param2: Value - Param3: Value - Content: Blah - blah - blah - ENDOFCONTENT - ===Create-Ticket: id2 - Param: Value - Content: Blah - ENDOFCONTENT - - -Each ===Create-Ticket: section is evaluated as its own  -Text::Template object, which means that you can embed snippets -of perl inside the Text::Template using {} delimiters, but that  -such sections absolutely can not span a ===Create-Ticket boundary. - -After each ticket is created, it's stuffed into a hash called %Tickets -so as to be available during the creation of other tickets during the same  -ScripAction.  The hash is prepopulated with the ticket which triggered the  -ScripAction as $Tickets{'TOP'}; you can also access that ticket using the -shorthand $TOP. - -A simple example: - - ===Create-Ticket: codereview - Subject: Code review for {$Tickets{'TOP'}->Subject} - Depended-On-By: {$Tickets{'TOP'}->Id} - Content: Someone has created a ticket. you should review and approve it, - so they can finish their work - ENDOFCONTENT - - - -A convoluted example - - ===Create-Ticket: approval - { # Find out who the administrators of the group called "HR"  -   # of which the creator of this ticket is a member -    my $name = "HR"; -    -    my $groups = RT::Groups->new($RT::SystemUser); -    $groups->LimitToUserDefinedGroups(); -    $groups->Limit(FIELD => "Name", OPERATOR => "=", VALUE => "$name"); -    $groups->WithMember($TransactionObj->CreatorObj->Id); -  -    my $groupid = $groups->First->Id; -  -    my $adminccs = RT::Users->new($RT::SystemUser); -    $adminccs->WhoHaveRight( -	Right => "AdminGroup", -	Object =>$groups->First, -	IncludeSystemRights => undef, -	IncludeSuperusers => 0, -	IncludeSubgroupMembers => 0, -    ); -  -     my @admins; -     while (my $admin = $adminccs->Next) { -         push (@admins, $admin->EmailAddress);  -     } - } - Queue: Approvals - Type: Approval - AdminCc: {join ("\nAdminCc: ",@admins) } - Depended-On-By: {$Tickets{"TOP"}->Id} - Refers-To: {$Tickets{"TOP"}->Id} - Subject: Approval for ticket: {$Tickets{"TOP"}->Id} - {$Tickets{"TOP"}->Subject} - Due: {time + 86400} - Content-Type: text/plain - Content: Your approval is requested for the ticket {$Tickets{"TOP"}->Id}: {$Tickets{"TOP"}->Subject} - Blah - Blah - ENDOFCONTENT - ===Create-Ticket: two - Subject: Manager approval - Depended-On-By: {$Tickets{"TOP"}->Id} - Refers-On: {$Tickets{"approval"}->Id} - Queue: Approvals - Content-Type: text/plain - Content:  - Your approval is requred for this ticket, too. - ENDOFCONTENT -  -=head2 Acceptable fields - -A complete list of acceptable fields for this beastie: - - -    *  Queue           => Name or id# of a queue -       Subject         => A text string -     ! Status          => A valid status. defaults to 'new' -       Due             => Dates can be specified in seconds since the epoch -                          to be handled literally or in a semi-free textual -                          format which RT will attempt to parse. -                         -                           -                           -       Starts          =>  -       Started         =>  -       Resolved        =>  -       Owner           => Username or id of an RT user who can and should own  -                          this ticket -   +   Requestor       => Email address -   +   Cc              => Email address  -   +   AdminCc         => Email address  -       TimeWorked      =>  -       TimeEstimated   =>  -       TimeLeft        =>  -       InitialPriority =>  -       FinalPriority   =>  -       Type            =>  -    +! DependsOn       =>  -    +! DependedOnBy    => -    +! RefersTo        => -    +! ReferredToBy    =>  -    +! Members         => -    +! MemberOf        =>  -       Content         => content. Can extend to multiple lines. Everything -                          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 -       CustomField-<id#> => custom field value - -Fields marked with an * are required. - -Fields marked with a + man have multiple values, simply -by repeating the fieldname on a new line with an additional value. - -Fields marked with a ! are postponed to be processed after all -tickets in the same actions are created.  Except for 'Status', those -field can also take a ticket name within the same action (i.e. -the identifiers after ==Create-Ticket), instead of raw Ticket ID -numbers. - -When parsed, field names are converted to lowercase and have -s stripped. -Refers-To, RefersTo, refersto, refers-to and r-e-f-er-s-tO will all  -be treated as the same thing. - - -=begin testing - -ok (require RT::Action::CreateTickets); -use_ok(RT::Scrip); -use_ok(RT::Template); -use_ok(RT::ScripAction); -use_ok(RT::ScripCondition); -use_ok(RT::Ticket); - -my $approvalsq = RT::Queue->new($RT::SystemUser); -$approvalsq->Create(Name => 'Approvals'); -ok ($approvalsq->Id, "Created Approvals test queue"); - - -my $approvals =  -'===Create-Ticket: approval -{  my $name = "HR"; -     my $groups = RT::Groups->new($RT::SystemUser); -   $groups->LimitToUserDefinedGroups(); -   $groups->Limit(FIELD => "Name", OPERATOR => "=", VALUE => "$name"); -   $groups->WithMember($Transaction->CreatorObj->Id); - -   my $groupid = $groups->First->Id; - -   my $adminccs = RT::Users->new($RT::SystemUser); -   $adminccs->WhoHaveRight(Right => "AdminGroup", IncludeSystemRights => undef, IncludeSuperusers => 0, IncludeSubgroupMembers => 0, Object => $groups->First); - -    my @admins; -    while (my $admin = $adminccs->Next) { -        push (@admins, $admin->EmailAddress);  -    } -} -Queue: Approvals -Type: Approval -AdminCc: {join ("\nAdminCc: ",@admins) } -Depended-On-By: {$Tickets{"TOP"}->Id} -Refers-To: {$Tickets{"TOP"}->Id} -Subject: Approval for ticket: {$Tickets{"TOP"}->Id} - {$Tickets{"TOP"}->Subject} -Due: {time + 86400} -Content-Type: text/plain -Content: Your approval is requested for the ticket {$Tickets{"TOP"}->Id}: {$Tickets{"TOP"}->Subject} -Blah -Blah -ENDOFCONTENT -===Create-Ticket: two -Subject: Manager approval. -Depends-On: {$Tickets{"approval"}->Id} -Queue: Approvals -Content-Type: text/plain -Content:  -Your minion approved this ticket. you ok with that? -ENDOFCONTENT -'; - -ok ($approvals =~ /Content/, "Read in the approvals template"); - -my $apptemp = RT::Template->new($RT::SystemUser); -$apptemp->Create( Content => $approvals, Name => "Approvals", Queue => "0"); - -ok ($apptemp->Id); - -my $q = RT::Queue->new($RT::SystemUser); -$q->Create(Name => 'WorkflowTest'); -ok ($q->Id, "Created workflow test queue"); - -my $scrip = RT::Scrip->new($RT::SystemUser); -my ($sval, $smsg) =$scrip->Create( ScripCondition => 'On Transaction', -                ScripAction => 'Create Tickets', -                Template => 'Approvals', -                Queue => $q->Id); -ok ($sval, $smsg); -ok ($scrip->Id, "Created the scrip"); -ok ($scrip->TemplateObj->Id, "Created the scrip template"); -ok ($scrip->ConditionObj->Id, "Created the scrip condition"); -ok ($scrip->ActionObj->Id, "Created the scrip action"); - -my $t = RT::Ticket->new($RT::SystemUser); -$t->Create(Subject => "Sample workflow test", -           Owner => "root", -           Queue => $q->Id); - - -=end testing - - -=head1 AUTHOR - -Jesse Vincent <jesse@bestpractical.com>  - -=head1 SEE ALSO - -perl(1). - -=cut - -my %LINKTYPEMAP = ( -    MemberOf => { Type => 'MemberOf', -                  Mode => 'Target', }, -    Members => { Type => 'MemberOf', -                 Mode => 'Base', }, -    HasMember => { Type => 'MemberOf', -                   Mode => 'Base', }, -    RefersTo => { Type => 'RefersTo', -                  Mode => 'Target', }, -    ReferredToBy => { Type => 'RefersTo', -                      Mode => 'Base', }, -    DependsOn => { Type => 'DependsOn', -                   Mode => 'Target', }, -    DependedOnBy => { Type => 'DependsOn', -                      Mode => 'Base', }, - -); - -# {{{ Scrip methods (Commit, Prepare) - -# {{{ sub Commit  -#Do what we need to do and send it out. -sub Commit { -    my $self = shift; -    my (@links, @postponed); - -    # XXX: cargo cult programming that works. i'll be back. -    use bytes; - -    # Create all the tickets we care about -    return(1) unless $self->TicketObj->Type eq 'ticket'; - -    %T::Tickets = (); - -    foreach my $template_id ( @{ $self->{'template_order'} } ) { -	$T::Tickets{'TOP'} = $T::TOP = $self->TicketObj; -	$RT::Logger->debug("Workflow: processing $template_id of $T::TOP"); - -	$T::ID = $template_id; -	@T::AllID = @{ $self->{'template_order'} }; - -        my $template = Text::Template->new( -	      TYPE   => 'STRING', -	      SOURCE => $self->{'templates'}->{$template_id} -        ); - -	$RT::Logger->debug("Workflow: evaluating\n$self->{templates}{$template_id}"); - -	my $err; -        my $filled_in = $template->fill_in( PACKAGE => 'T', BROKEN => sub { -	    $err = { @_ }->{error}; -	} ); - -	$RT::Logger->debug("Workflow: yielding\n$filled_in"); - -	if ($err) { -	    $RT::Logger->error("Ticket creation failed for ".$self->TicketObj->Id." ".$err); -	    while (my ($k, $v) = each %T::X) { -		$RT::Logger->debug("Eliminating $template_id from ${k}'s parents."); -		delete $v->{$template_id}; -	    } -	    next; -	} - -        my %args; -        my @lines = ( split ( /\n/, $filled_in ) ); -        while ( defined(my $line = shift @lines) ) { -            if ( $line =~ /^(.*?):(?:\s+(.*))?$/ ) { -                my $value = $2; -                my $tag = lc ($1); -                $tag =~ s/-//g; - -		if (ref($args{$tag})) { #If it's an array, we want to push the value -		    push @{$args{$tag}}, $value; -		} -		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 -		    $args{ $tag } = $value; -		} - -                if ( $tag eq 'content' ) { #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"; -                        } -                } -            } -	} - -	foreach my $date qw(due starts started resolved) { -	    my $dateobj = RT::Date->new($RT::SystemUser); -	    next unless $args{$date}; -	    if ($args{$date} =~ /^\d+$/) { -		$dateobj->Set(Format => 'unix', Value => $args{$date}); -	    } else { -		$dateobj->Set(Format => 'unknown', Value => $args{$date}); -	    } -	    $args{$date} = $dateobj->ISO; -	} -	my $mimeobj = MIME::Entity->new(); -	$mimeobj->build(Type => $args{'contenttype'}, -			Data => $args{'content'}); -	# Now we have a %args to work with.  -	# Make sure we have at least the minimum set of  -	# reasonable data and do our thang -	$T::Tickets{$template_id} ||= RT::Ticket->new($RT::SystemUser); - -	# Deferred processing	 -	push @links, ( -	    $T::Tickets{$template_id}, { -		DependsOn		=> $args{'dependson'}, -		DependedOnBy	=> $args{'dependedonby'}, -		RefersTo		=> $args{'refersto'}, -		ReferredToBy	=> $args{'referredtoby'}, -		Members		=> $args{'members'}, -		MemberOf		=> $args{'memberof'}, -	    } -	); - -	push @postponed, ( -	    # Status is postponed so we don't violate dependencies -	    $T::Tickets{$template_id}, { -		Status		=> $args{'status'}, -	    } -	); - -	$args{'requestor'} ||= $self->TicketObj->Requestors->MemberEmailAddresses; - -	my %ticketargs = ( Queue => $args{'queue'}, -		      Subject=> $args{'subject'}, -		    Status => 'new', -		    Due => $args{'due'}, -		    Starts => $args{'starts'}, -		    Started => $args{'started'}, -		    Resolved => $args{'resolved'}, -		    Owner => $args{'owner'}, -		    Requestor => $args{'requestor'}, -		    Cc => $args{'cc'}, -		    AdminCc=> $args{'admincc'}, -		    TimeWorked =>$args{'timeworked'}, -		    TimeEstimated =>$args{'timeestimated'}, -		    TimeLeft =>$args{'timeleft'}, -		    InitialPriority => $args{'initialpriority'}, -		    FinalPriority => $args{'finalpriority'}, -		    Type => $args{'type'},  -		    MIMEObj => $mimeobj); - - -	foreach my $key (keys(%args)) { -	    $key =~ /^customfield-(\d+)$/ or next; -	    $ticketargs{ "CustomField-" . $1 } = $args{$key}; -	} - -	my ($id, $transid, $msg) = $T::Tickets{$template_id}->Create(%ticketargs); -	if (!$id) { -	    $RT::Logger->error( -		"Couldn't create related ticket $template_id for ". -		$self->TicketObj->Id." ".$msg -	    ); -	    next; -	} - -	$RT::Logger->debug("Assigned $template_id with $id"); -	$T::Tickets{$template_id}->SetOriginObj($self->TicketObj) -	    if $T::Tickets{$template_id}->can('SetOriginObj'); -    } - -    # postprocessing: add links - -    while (my $ticket = shift(@links)) { -	$RT::Logger->debug("Handling links for " . $ticket->Id); -	my %args = %{shift(@links)}; - -	foreach my $type ( keys %LINKTYPEMAP ) { -	    next unless (defined $args{$type}); -	    foreach my $link ( -		ref( $args{$type} ) ? @{ $args{$type} } : ( $args{$type} ) ) -	    { -		if (!exists $T::Tickets{$link}) { -		    $RT::Logger->debug("Skipping $type link for $link (non-existent)"); -		    next; -		} -		$RT::Logger->debug("Building $type link for $link: " . $T::Tickets{$link}->Id); -		$link = $T::Tickets{$link}->Id; - -		my ( $wval, $wmsg ) = $ticket->AddLink( -		    Type                          => $LINKTYPEMAP{$type}->{'Type'}, -		    $LINKTYPEMAP{$type}->{'Mode'} => $link, -		    Silent                        => 1 -		); - -		$RT::Logger->warning("AddLink thru $link failed: $wmsg") unless $wval; -		# push @non_fatal_errors, $wmsg unless ($wval); -	    } - -	} -    } - -    # postponed actions -- Status only, currently -    while (my $ticket = shift(@postponed)) { -	$RT::Logger->debug("Handling postponed actions for $ticket"); -	my %args = %{shift(@postponed)}; - -	$ticket->SetStatus($args{Status}) if defined $args{Status}; -    } - -    return(1); -} -# }}} - -# {{{ sub Prepare  - -sub Prepare  { -  my $self = shift; -   -  unless ($self->TemplateObj) { -    $RT::Logger->warning("No template object handed to $self\n"); -  } -   -  unless ($self->TransactionObj) { -    $RT::Logger->warning("No transaction object handed to $self\n"); -     -  } -   -  unless ($self->TicketObj) { -    $RT::Logger->warning("No ticket object handed to $self\n"); -       -  } -  - -     - -my $template_id; -foreach my $line (split(/\n/,$self->TemplateObj->Content)) { -        if ($line =~ /^===Create-Ticket: (.*)$/) { -                $template_id = $1; -                push @{$self->{'template_order'}},$template_id; -        } else { -                $self->{'templates'}->{$template_id} .= $line."\n"; -        }        -         -         -} -   -  return 1; -   -} - -# }}} - -# }}} - -eval "require RT::Action::CreateTickets_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/CreateTickets_Vendor.pm}); -eval "require RT::Action::CreateTickets_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/CreateTickets_Local.pm}); - -1; - diff --git a/rt/lib/RT/Action/EscalatePriority.pm b/rt/lib/RT/Action/EscalatePriority.pm deleted file mode 100644 index 7ed63ae01..000000000 --- a/rt/lib/RT/Action/EscalatePriority.pm +++ /dev/null @@ -1,142 +0,0 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK -=head1 NAME - -  RT::Action::EscalatePriority - -=head1 DESCRIPTION - -EscalatePriority is a ScripAction which is NOT intended to be called per  -transaction. It's intended to be called by an RT escalation daemon. -(The daemon is called escalator). - -EsclatePriority uses the following formula to change a ticket's priority: - -    Priority = Priority +  (( FinalPriority - Priority ) / ( DueDate-Today)) - -Unless the duedate is past, in which case priority gets bumped straight -to final priority. - -In this way, priority is either increased or decreased toward the final priority -as the ticket heads toward its due date. - - -=cut - - -package RT::Action::EscalatePriority; -require RT::Action::Generic; - -use strict; -use vars qw/@ISA/; -@ISA=qw(RT::Action::Generic); - -#Do what we need to do and send it out. - -#What does this type of Action does - -# {{{ sub Describe  -sub Describe  { -  my $self = shift; -  return (ref $self . " will move a ticket's priority toward its final priority."); -} -# }}} -	 - -# {{{ sub Prepare  -sub Prepare  { -    my $self = shift; -     -    if ($self->TicketObj->Priority() == $self->TicketObj->FinalPriority()) { -	# no update necessary. -	return 0; -    } -    -    #compute the number of days until the ticket is due -    my $due = $self->TicketObj->DueObj(); -     - -    # If we don't have a due date, adjust the priority by one -    # until we hit the final priority -    if ($due->Unix() < 1) { -	if ( $self->TicketObj->Priority > $self->TicketObj->FinalPriority ){ -	    $self->{'prio'} = ($self->TicketObj->Priority - 1); -	    return 1; -	} -	elsif ( $self->TicketObj->Priority < $self->TicketObj->FinalPriority ){ -	    $self->{'prio'} = ($self->TicketObj->Priority + 1); -	    return 1; -	} -	# otherwise the priority is at the final priority. we don't need to -	# Continue -	else { -	    return 0; -	} -    } - -    # we've got a due date. now there are other things we should do -    else {  -	my $diff_in_seconds = $due->Diff(time());     -	my $diff_in_days = int( $diff_in_seconds / 86400);     -	 -	#if we haven't hit the due date yet -	if ($diff_in_days > 0 ) {	 -	     -	    # compute the difference between the current priority and the -	    # final priority -	     -	    my $prio_delta =  -	      $self->TicketObj->FinalPriority() - $self->TicketObj->Priority; -	     -	    my $inc_priority_by = int( $prio_delta / $diff_in_days ); -	     -	    #set the ticket's priority to that amount -	    $self->{'prio'} = $self->TicketObj->Priority + $inc_priority_by; -	     -	} -	#if $days is less than 1, set priority to final_priority -	else {	 -	    $self->{'prio'} = $self->TicketObj->FinalPriority(); -	} - -    } -    return 1; -} -# }}} - -sub Commit { -    my $self = shift; -   my ($val, $msg) = $self->TicketObj->SetPriority($self->{'prio'}); - -   unless ($val) { -	$RT::Logger->debug($self . " $msg\n");  -   } -} - -eval "require RT::Action::EscalatePriority_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/EscalatePriority_Vendor.pm}); -eval "require RT::Action::EscalatePriority_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/EscalatePriority_Local.pm}); - -1; diff --git a/rt/lib/RT/Action/Generic.pm b/rt/lib/RT/Action/Generic.pm index 007d299c7..ecfd4ab1a 100755 --- a/rt/lib/RT/Action/Generic.pm +++ b/rt/lib/RT/Action/Generic.pm @@ -1,26 +1,7 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK +# $Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Action/Generic.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ +# (c) 1996-2000 Jesse Vincent <jesse@fsck.com> +# This software is redistributable under the terms of the GNU GPL +  =head1 NAME    RT::Action::Generic - a generic baseclass for RT Actions @@ -35,6 +16,7 @@  =begin testing +ok (require RT::TestHarness);  ok (require RT::Action::Generic);  =end testing @@ -43,8 +25,6 @@ ok (require RT::Action::Generic);  package RT::Action::Generic; -use strict; -  # {{{ sub new   sub new  {    my $proto = shift; @@ -56,13 +36,6 @@ sub new  {  }  # }}} -# {{{ sub new  -sub loc { -    my $self = shift; -    return $self->{'ScripObj'}->loc(@_); -} -# }}} -  # {{{ sub _Init   sub _Init  {    my $self = shift; @@ -114,13 +87,6 @@ sub TemplateObj  {  }  # }}} -# {{{ sub ScripObj -sub ScripObj  { -  my $self = shift; -  return($self->{'ScripObj'}); -} -# }}} -  # {{{ sub Type  sub Type  {    my $self = shift; @@ -136,7 +102,7 @@ sub Type  {  # {{{ sub Commit   sub Commit  {    my $self = shift; -  return(0, $self->loc("Commit Stubbed")); +  return(0,"Commit Stubbed");  }  # }}} @@ -146,7 +112,7 @@ sub Commit  {  # {{{ sub Describe   sub Describe  {    my $self = shift; -  return $self->loc("No description for [_1]", ref $self); +  return ("No description for " . ref $self);  }  # }}} @@ -156,7 +122,7 @@ sub Describe  {  # {{{ sub Prepare   sub Prepare  {    my $self = shift; -  return (0, $self->loc("Prepare Stubbed")); +  return (0,"Prepare Stubbed");  }  # }}} @@ -186,10 +152,4 @@ sub DESTROY {  }  # }}} - -eval "require RT::Action::Generic_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/Generic_Vendor.pm}); -eval "require RT::Action::Generic_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/Generic_Local.pm}); -  1; diff --git a/rt/lib/RT/Action/Notify.pm b/rt/lib/RT/Action/Notify.pm index 1e4e4c073..6dca4fd41 100755 --- a/rt/lib/RT/Action/Notify.pm +++ b/rt/lib/RT/Action/Notify.pm @@ -1,31 +1,7 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK +#$Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Action/Notify.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ +  package RT::Action::Notify;  require RT::Action::SendEmail; - -use strict; -use vars qw/@ISA/;  @ISA = qw(RT::Action::SendEmail);  # {{{ sub SetRecipients @@ -33,14 +9,14 @@ use vars qw/@ISA/;  =head2 SetRecipients  Sets the recipients of this meesage to Owner, Requestor, AdminCc, Cc or All.  -Explicitly B<does not> notify the creator of the transaction by default +Explicitly B<does not> notify the creator of the transaction.  =cut  sub SetRecipients {      my $self = shift; -    my $arg = $self->Argument; +    $arg = $self->Argument;      $arg =~ s/\bAll\b/Owner,Requestor,AdminCc,Cc/; @@ -48,14 +24,14 @@ sub SetRecipients {      if ($arg =~ /\bOtherRecipients\b/) { -        if ($self->TransactionObj->Attachments->First) { -            push (@Cc, $self->TransactionObj->Attachments->First->GetHeader('RT-Send-Cc')); -            push (@Bcc, $self->TransactionObj->Attachments->First->GetHeader('RT-Send-Bcc')); +        if ($self->TransactionObj->Message->First) { +            push (@Cc, $self->TransactionObj->Message->First->GetHeader('RT-Send-Cc')); +            push (@Bcc, $self->TransactionObj->Message->First->GetHeader('RT-Send-Bcc'));          }      }      if ( $arg =~ /\bRequestor\b/ ) { -        push ( @To, $self->TicketObj->Requestors->MemberEmailAddresses  ); +        push ( @To, @{ $self->TicketObj->Requestors->Emails } );      } @@ -64,12 +40,12 @@ sub SetRecipients {          #If we have a To, make the Ccs, Ccs, otherwise, promote them to To          if (@To) { -            push ( @Cc, $self->TicketObj->Cc->MemberEmailAddresses ); -            push ( @Cc, $self->TicketObj->QueueObj->Cc->MemberEmailAddresses  ); +            push ( @Cc, @{ $self->TicketObj->Cc->Emails } ); +            push ( @Cc, @{ $self->TicketObj->QueueObj->Cc->Emails } );          }          else { -            push ( @Cc, $self->TicketObj->Cc->MemberEmailAddresses  ); -            push ( @To, $self->TicketObj->QueueObj->Cc->MemberEmailAddresses  ); +            push ( @Cc, @{ $self->TicketObj->Cc->Emails } ); +            push ( @To, @{ $self->TicketObj->QueueObj->Cc->Emails } );          }      } @@ -89,16 +65,15 @@ sub SetRecipients {      }      if ( $arg =~ /\bAdminCc\b/ ) { -        push ( @Bcc, $self->TicketObj->AdminCc->MemberEmailAddresses  ); -        push ( @Bcc, $self->TicketObj->QueueObj->AdminCc->MemberEmailAddresses  ); +        push ( @Bcc, @{ $self->TicketObj->AdminCc->Emails } ); +        push ( @Bcc, @{ $self->TicketObj->QueueObj->AdminCc->Emails } );      }      if ($RT::UseFriendlyToLine) {          unless (@To) { -            push ( -		@PseudoTo, -		sprintf($RT::FriendlyToLineFormat, $arg, $self->TicketObj->id), -	    ); +            push ( @PseudoTo, +                "\"$arg of $RT::rtname Ticket #" +                  . $self->TicketObj->id . "\":;" );          }      } @@ -106,17 +81,14 @@ sub SetRecipients {      #Strip the sender out of the To, Cc and AdminCc and set the       # recipients fields used to build the message by the superclass. -    # unless a flag is set  -    if ($RT::NotifyActor) { -        @{ $self->{'To'} }  = @To; -        @{ $self->{'Cc'} }  = @Cc; -        @{ $self->{'Bcc'} } = @Bcc; -    } -    else { -        @{ $self->{'To'} }  = grep ( !/^$creator$/, @To ); -        @{ $self->{'Cc'} }  = grep ( !/^$creator$/, @Cc ); -        @{ $self->{'Bcc'} } = grep ( !/^$creator$/, @Bcc ); -    } + +    $RT::Logger->debug("$self: To is ".join(",",@To)); +    $RT::Logger->debug("$self: Cc is ".join(",",@Cc)); +    $RT::Logger->debug("$self: Bcc is ".join(",",@Bcc)); + +    @{ $self->{'To'} }  = grep ( !/^$creator$/, @To ); +    @{ $self->{'Cc'} }  = grep ( !/^$creator$/, @Cc ); +    @{ $self->{'Bcc'} } = grep ( !/^$creator$/, @Bcc );      @{ $self->{'PseudoTo'} } = @PseudoTo;      return (1); @@ -124,9 +96,4 @@ sub SetRecipients {  # }}} -eval "require RT::Action::Notify_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/Notify_Vendor.pm}); -eval "require RT::Action::Notify_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/Notify_Local.pm}); -  1; diff --git a/rt/lib/RT/Action/NotifyAsComment.pm b/rt/lib/RT/Action/NotifyAsComment.pm index 210e4ab15..c72bfff13 100755 --- a/rt/lib/RT/Action/NotifyAsComment.pm +++ b/rt/lib/RT/Action/NotifyAsComment.pm @@ -1,31 +1,7 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK +#$Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Action/NotifyAsComment.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ +  package RT::Action::NotifyAsComment;  require RT::Action::Notify; - -use strict; -use vars qw/@ISA/;  @ISA = qw(RT::Action::Notify); @@ -45,11 +21,5 @@ sub SetReturnAddress {  	return($self->SUPER::SetReturnAddress(is_comment => 1));  } - -eval "require RT::Action::NotifyAsComment_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/NotifyAsComment_Vendor.pm}); -eval "require RT::Action::NotifyAsComment_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/NotifyAsComment_Local.pm}); -  1; diff --git a/rt/lib/RT/Action/OpenDependent.pm b/rt/lib/RT/Action/OpenDependent.pm new file mode 100644 index 000000000..b271e4709 --- /dev/null +++ b/rt/lib/RT/Action/OpenDependent.pm @@ -0,0 +1,55 @@ +# $Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Action/Attic/OpenDependent.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ +# This Action will open the BASE if a dependent is resolved. + +package RT::Action::OpenDependent; +require RT::Action::Generic; +require RT::Links; +@ISA=qw(RT::Action::Generic); + +#Do what we need to do and send it out. + +#What does this type of Action does + +# {{{ sub Describe  +sub Describe  { +  my $self = shift; +  return (ref $self . " will stall a [local] BASE if it's open and a dependency link is created."); +} +# }}} + + +# {{{ sub Prepare  +sub Prepare  { +    # nothing to prepare +    return 1; +} +# }}} + +sub Commit { +    my $self = shift; + +    my $Links=RT::Links->new($RT::SystemUser); +    $Links->Limit(FIELD => 'Type', VALUE => 'DependsOn'); +    $Links->Limit(FIELD => 'Target', VALUE => $self->TicketObj->id); + +    while (my $Link=$Links->Next()) { +	next unless $Link->BaseIsLocal; +	my $base=RT::Ticket->new($self->TicketObj->CurrentUser); +	# Todo: Only work if Base is a plain ticket num: +	$base->Load($Link->Base); +        $base->Open if $base->Status eq 'stalled'; +    } +} + + +# Applicability checked in Commit. + +# {{{ sub IsApplicable  +sub IsApplicable  { +  my $self = shift; +  1;   +  return 1; +} +# }}} + +1; diff --git a/rt/lib/RT/Action/ResolveMembers.pm b/rt/lib/RT/Action/ResolveMembers.pm index 02ff3a58c..00547ebe8 100644 --- a/rt/lib/RT/Action/ResolveMembers.pm +++ b/rt/lib/RT/Action/ResolveMembers.pm @@ -1,34 +1,8 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK  # This Action will resolve all members of a resolved group ticket  package RT::Action::ResolveMembers;  require RT::Action::Generic;  require RT::Links; - -use strict; -use vars qw/@ISA/;  @ISA=qw(RT::Action::Generic);  #Do what we need to do and send it out. @@ -38,7 +12,7 @@ use vars qw/@ISA/;  # {{{ sub Describe   sub Describe  {    my $self = shift; -  return $self->loc("[_1] will resolve all members of a resolved group ticket.", ref $self); +  return (ref $self . " will resolve all members of a resolved group ticket.");  }  # }}} @@ -59,7 +33,7 @@ sub Commit {      while (my $Link=$Links->Next()) {  	# Todo: Try to deal with remote URIs as well -	next unless $Link->BaseURI->IsLocal; +	next unless $Link->BaseIsLocal;  	my $base=RT::Ticket->new($self->TicketObj->CurrentUser);  	# Todo: Only work if Base is a plain ticket num:  	$base->Load($Link->Base); @@ -79,10 +53,5 @@ sub IsApplicable  {  }  # }}} -eval "require RT::Action::ResolveMembers_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/ResolveMembers_Vendor.pm}); -eval "require RT::Action::ResolveMembers_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/ResolveMembers_Local.pm}); -  1; diff --git a/rt/lib/RT/Action/SendEmail.pm b/rt/lib/RT/Action/SendEmail.pm index dac8fc8e7..e3abb1154 100755 --- a/rt/lib/RT/Action/SendEmail.pm +++ b/rt/lib/RT/Action/SendEmail.pm @@ -1,44 +1,20 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK +# $Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Action/SendEmail.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ +# Copyright 1996-2002  Jesse Vincent <jesse@bestpractical.com>   # Portions Copyright 2000 Tobias Brox <tobix@cpan.org> +# Released under the terms of version 2 of the GNU Public License  package RT::Action::SendEmail;  require RT::Action::Generic; -use strict; -use vars qw/@ISA/;  @ISA = qw(RT::Action::Generic); -use MIME::Words qw(encode_mimeword); - -use RT::EmailParser;  =head1 NAME -RT::Action::SendEmail - An Action which users can use to send mail  -or can subclassed for more specialized mail sending behavior.  -RT::Action::AutoReply is a good example subclass. +  RT::Action::SendEmail - An Action which users can use to send mail  +  or can subclassed for more specialized mail sending behavior.  +  RT::Action::AutoReply is a good example subclass. +  =head1 SYNOPSIS @@ -60,6 +36,7 @@ the comments for the SetRecipients sub).  =begin testing +ok (require RT::TestHarness);  ok (require RT::Action::SendEmail);  =end testing @@ -77,266 +54,158 @@ perl(1).  # {{{ Scrip methods (_Init, Commit, Prepare, IsApplicable) -# {{{ sub _Init +# {{{ sub _Init   # We use _Init from RT::Action  # }}} -# {{{ sub Commit +# {{{ sub Commit   #Do what we need to do and send it out. -sub Commit { +sub Commit  {      my $self = shift; - -    my $MIMEObj = $self->TemplateObj->MIMEObj; -    my $msgid = $MIMEObj->head->get('Message-Id'); -    chomp $msgid; -    $RT::Logger->info($msgid." #".$self->TicketObj->id."/".$self->TransactionObj->id." - Scrip ". $self->ScripObj->id ." ".$self->ScripObj->Description);      #send the email - -        # Weed out any RT addresses. We really don't want to talk to ourselves! -        @{$self->{'To'}} = RT::EmailParser::CullRTAddresses("", @{$self->{'To'}}); -        @{$self->{'Cc'}} = RT::EmailParser::CullRTAddresses("", @{$self->{'Cc'}}); -        @{$self->{'Bcc'}} = RT::EmailParser::CullRTAddresses("", @{$self->{'Bcc'}}); +          # If there are no recipients, don't try to send the message.      # If the transaction has content and has the header RT-Squelch-Replies-To - -    if ( defined $self->TransactionObj->Attachments->First() ) { - -        my $squelch = $self->TransactionObj->Attachments->First->GetHeader( 'RT-Squelch-Replies-To'); - -        if ($squelch) { -            my @blacklist = split ( /,/, $squelch ); - -            # Cycle through the people we're sending to and pull out anyone on the -            # system blacklist - -            foreach my $person_to_yank (@blacklist) { -                $person_to_yank =~ s/\s//g; -                @{ $self->{'To'} } = -                  grep ( !/^$person_to_yank$/, @{ $self->{'To'} } ); -                @{ $self->{'Cc'} } = -                  grep ( !/^$person_to_yank$/, @{ $self->{'Cc'} } ); -                @{ $self->{'Bcc'} } = -                  grep ( !/^$person_to_yank$/, @{ $self->{'Bcc'} } ); -            } -        } +     +    if (defined $self->TransactionObj->Message->First()) {  +	my $headers = $self->TransactionObj->Message->First->Headers(); +	 +	if ($headers =~ /^RT-Squelch-Replies-To: (.*?)$/si) { +	    my @blacklist = split(/,/,$1); +	     +	    # Cycle through the people we're sending to and pull out anyone on the +	    # system blacklist +	     +	    foreach my $person_to_yank (@blacklist) { +		$person_to_yank =~ s/\s//g; +		@{$self->{'To'}} = grep (!/^$person_to_yank$/, @{$self->{'To'}}); +		@{$self->{'Cc'}} = grep (!/^$person_to_yank$/, @{$self->{'Cc'}}); +		@{$self->{'Bcc'}} = grep (!/^$person_to_yank$/, @{$self->{'Bcc'}}); +	    } +	}      } - -    # Go add all the Tos, Ccs and Bccs that we need to to the message to +     +    # Go add all the Tos, Ccs and Bccs that we need to to the message to       # make it happy, but only if we actually have values in those arrays. +     +    $self->SetHeader('To', join(',', @{$self->{'To'}}))  +      if (@{$self->{'To'}}); +    $self->SetHeader('Cc', join(',' , @{$self->{'Cc'}}))  +      if (@{$self->{'Cc'}}); +	$self->SetHeader('Bcc', join(',', @{$self->{'Bcc'}}))  +	  if (@{$self->{'Bcc'}});; +     +    my $MIMEObj = $self->TemplateObj->MIMEObj; +     -    $self->SetHeader( 'To', join ( ',', @{ $self->{'To'} } ) ) -      if ( $self->{'To'} && @{ $self->{'To'} } ); -    $self->SetHeader( 'Cc', join ( ',', @{ $self->{'Cc'} } ) ) -      if ( $self->{'Cc'} && @{ $self->{'Cc'} } ); -    $self->SetHeader( 'Bcc', join ( ',', @{ $self->{'Bcc'} } ) ) -      if ( $self->{'Cc'} && @{ $self->{'Bcc'} } ); - - -    $self->SetHeader('MIME-Version', '1.0'); - -    # try to convert message body from utf-8 to $RT::EmailOutputEncoding -    $self->SetHeader( 'Content-Type', 'text/plain; charset="utf-8"' ); - -    RT::I18N::SetMIMEEntityToEncoding( $MIMEObj, $RT::EmailOutputEncoding, 'mime_words_ok' ); -    $self->SetHeader( 'Content-Type', 'text/plain; charset="' . $RT::EmailOutputEncoding . '"' ); - - -    # Build up a MIME::Entity that looks like the original message. - -    my $do_attach = $self->TemplateObj->MIMEObj->head->get('RT-Attach-Message'); - -    if ($do_attach) { -        $self->TemplateObj->MIMEObj->head->delete('RT-Attach-Message'); - -        my $attachments = RT::Attachments->new($RT::SystemUser); -        $attachments->Limit( FIELD => 'TransactionId', -                             VALUE => $self->TransactionObj->Id ); -        $attachments->OrderBy('id'); - -        my $transaction_content_obj = $self->TransactionObj->ContentObj; - -        # attach any of this transaction's attachments -        while ( my $attach = $attachments->Next ) { - -            # Don't attach anything blank -            next unless ( $attach->ContentLength ); - -            # We want to make sure that we don't include the attachment that's being sued as the "Content" of this message" -            next -              if (    $transaction_content_obj -                   && $transaction_content_obj->Id == $attach->Id  -                   && $transaction_content_obj->ContentType =~ qr{text/plain}i -                ); -            $MIMEObj->make_multipart('mixed'); -            $MIMEObj->attach( Type => $attach->ContentType, -                              Charset => $attach->OriginalEncoding, -                              Data => $attach->OriginalContent, -                              Filename => $self->MIMEEncodeString( $attach->Filename, $RT::EmailOutputEncoding ), -                              Encoding    => '-SUGGEST'); -        } - -    } - - -    my $retval = $self->SendMessage($MIMEObj); - - -    return ($retval); -} - -# }}} - -# {{{ sub Prepare - -sub Prepare { -    my $self = shift; - -    # This actually populates the MIME::Entity fields in the Template Object - -    unless ( $self->TemplateObj ) { -        $RT::Logger->warning("No template object handed to $self\n"); -    } - -    unless ( $self->TransactionObj ) { -        $RT::Logger->warning("No transaction object handed to $self\n"); - -    } - -    unless ( $self->TicketObj ) { -        $RT::Logger->warning("No ticket object handed to $self\n"); - -    } - -    my ( $result, $message ) = $self->TemplateObj->Parse( -                                         Argument       => $self->Argument, -                                         TicketObj      => $self->TicketObj, -                                         TransactionObj => $self->TransactionObj -    ); -    if ($result) { - -        # Header -        $self->SetSubject(); -        $self->SetSubjectToken(); -        $self->SetRecipients(); -        $self->SetReturnAddress(); -        $self->SetRTSpecialHeaders(); -        if ($RT::EmailOutputEncoding) { - -            # l10n related header -            $self->SetHeaderAsEncoding( 'Subject', $RT::EmailOutputEncoding ); -        } -    } - -    return $result; - -} - -# }}} - -# }}} - -# {{{ SendMessage -=head2 SendMessage MIMEObj - -sends the message using RT's preferred API. -TODO: Break this out to a seperate module - -=cut - -sub SendMessage { -    my $self = shift; -    my $MIMEObj = shift; - -    my $msgid = $MIMEObj->head->get('Message-Id'); - - +    $MIMEObj->make_singlepart; +     +          #If we don't have any recipients to send to, don't send a message; -    unless (    $MIMEObj->head->get('To') -             || $MIMEObj->head->get('Cc') -             || $MIMEObj->head->get('Bcc') ) { -        $RT::Logger->info($msgid.  " No recipients found. Not sending.\n"); -        return (1); +    unless ($MIMEObj->head->get('To') || +	    $MIMEObj->head->get('Cc') ||  +	    $MIMEObj->head->get('Bcc') ) { +	$RT::Logger->debug("$self: No recipients found. Not sending.\n"); +	return(1);      }      # PseudoTo	(fake to headers) shouldn't get matched for message recipients.      # If we don't have any 'To' header, drop in the pseudo-to header. -    $self->SetHeader( 'To', join ( ',', @{ $self->{'PseudoTo'} } ) ) -      if ( $self->{'PseudoTo'} && ( @{ $self->{'PseudoTo'} } ) -           and ( !$MIMEObj->head->get('To') ) ); -    if ( $RT::MailCommand eq 'sendmailpipe' ) { -        eval { -            open( MAIL, "|$RT::SendmailPath $RT::SendmailArguments" ); -            print MAIL $MIMEObj->as_string; -            close(MAIL); -          }; -          if ($@) { -            $RT::Logger->crit($msgid.  "Could not send mail. -".$@ ); -        } +    $self->SetHeader('To', join(',', @{$self->{'PseudoTo'}})) +      if ( (@{$self->{'PseudoTo'}}) and (! $MIMEObj->head->get('To'))); +     +    if ($RT::MailCommand eq 'sendmailpipe') { +	open (MAIL, "|$RT::SendmailPath $RT::SendmailArguments") || return(0); +	print MAIL $MIMEObj->as_string; +	close(MAIL);      }      else { -	my @mailer_args = ($RT::MailCommand); -	local $ENV{MAILADDRESS}; - -        if ( $RT::MailCommand eq 'sendmail' ) { -	    push @mailer_args, $RT::SendmailArguments; -        } -        elsif ( $RT::MailCommand eq 'smtp' ) { -	    $ENV{MAILADDRESS} = $RT::SMTPFrom || $MIMEObj->head->get('From'); -	    push @mailer_args, (Server => $RT::SMTPServer); -	    push @mailer_args, (Debug => $RT::SMTPDebug); -        } -	else { -	    push @mailer_args, $RT::MailParams; +	unless ($MIMEObj->send($RT::MailCommand, $RT::MailParams)) { +	    $RT::Logger->crit("$self: Could not send mail for ". +			      $self->TransactionObj . "\n"); +	    return(0);  	} - -        unless ( $MIMEObj->send( @mailer_args ) ) { -            $RT::Logger->crit($msgid.  "Could not send mail." ); -            return (0); -        }      } +     +    return (1); +     +} +# }}} +# {{{ sub Prepare  -     my $success = ($msgid. " sent To: ".$MIMEObj->head->get('To') . " Cc: ".$MIMEObj->head->get('Cc') . " Bcc: ".$MIMEObj->head->get('Bcc')); -    $success =~ s/\n//gi; -    $RT::Logger->info($success); +sub Prepare  { +  my $self = shift; +   +  # This actually populates the MIME::Entity fields in the Template Object +   +  unless ($self->TemplateObj) { +    $RT::Logger->warning("No template object handed to $self\n"); +  } +   +  unless ($self->TransactionObj) { +    $RT::Logger->warning("No transaction object handed to $self\n"); +     +  } +   +  unless ($self->TicketObj) { +    $RT::Logger->warning("No ticket object handed to $self\n"); +       +  } +   +   +  $self->TemplateObj->Parse(Argument => $self->Argument, +			    TicketObj => $self->TicketObj,  +			    TransactionObj => $self->TransactionObj); +   +  # Header +   +  $self->SetSubject(); +   +  $self->SetSubjectToken(); +   +  $self->SetRecipients();   +   +  $self->SetReturnAddress(); -    return (1); +  $self->SetRTSpecialHeaders(); +   +  return 1; +    }  # }}} +# }}} +  # {{{ Deal with message headers (Set* subs, designed for  easy overriding)  # {{{ sub SetRTSpecialHeaders -=head2 SetRTSpecialHeaders  - -This routine adds all the random headers that RT wants in a mail message -that don't matter much to anybody else. - -=cut +# This routine adds all the random headers that RT wants in a mail message +# that don't matter much to anybody else.  sub SetRTSpecialHeaders {      my $self = shift; - +          $self->SetReferences();      $self->SetMessageID(); - +          $self->SetPrecedence(); -    $self->SetHeader( 'X-RT-Loop-Prevention', $RT::rtname ); -    $self->SetHeader( 'RT-Ticket', -                      $RT::rtname . " #" . $self->TicketObj->id() ); -    $self->SetHeader( 'Managed-by', -                      "RT $RT::VERSION (http://www.bestpractical.com/rt/)" ); +    $self->SetHeader('X-RT-Loop-Prevention', $RT::rtname);  +    $self->SetHeader('RT-Ticket', $RT::rtname. " #".$self->TicketObj->id()); +    $self->SetHeader +      ('Managed-by',"RT $RT::VERSION (http://bestpractical.com/rt/)"); +     +    $self->SetHeader('RT-Originator', $self->TransactionObj->CreatorObj->EmailAddress); +    return(); +     +} -    $self->SetHeader( 'RT-Originator', -                      $self->TransactionObj->CreatorObj->EmailAddress ); -    return (); -}  # {{{ sub SetReferences @@ -349,126 +218,105 @@ sub SetRTSpecialHeaders {  =cut  sub SetReferences { -    my $self = shift; +  my $self = shift; +   +  # TODO: this one is broken.  What is this email really a reply to? +  # If it's a reply to an incoming message, we'll need to use the +  # actual message-id from the appropriate Attachment object.  For +  # incoming mails, we would like to preserve the In-Reply-To and/or +  # References. -    # TODO: this one is broken.  What is this email really a reply to? -    # If it's a reply to an incoming message, we'll need to use the -    # actual message-id from the appropriate Attachment object.  For -    # incoming mails, we would like to preserve the In-Reply-To and/or -    # References. +  $self->SetHeader +    ('In-Reply-To', "<rt-".$self->TicketObj->id(). +     "\@".$RT::rtname.">"); -    $self->SetHeader( 'In-Reply-To', -                   "<rt-" . $self->TicketObj->id() . "\@" . $RT::rtname . ">" ); -    # TODO We should always add References headers for all message-ids -    # of previous messages related to this ticket. +  # TODO We should always add References headers for all message-ids +  # of previous messages related to this ticket.  }  # }}}  # {{{ sub SetMessageID -=head2 SetMessageID  - -Without this one, threading won't work very nice in email agents. -Anyway, I'm not really sure it's that healthy if we need to send -several separate/different emails about the same transaction. - -=cut +# Without this one, threading won't work very nice in email agents. +# Anyway, I'm not really sure it's that healthy if we need to send +# several separate/different emails about the same transaction.  sub SetMessageID { -    my $self = shift; +  my $self = shift; -    # TODO this one might be sort of broken.  If we have several scrips +++ -    # sending several emails to several different persons, we need to -    # pull out different message-ids.  I'd suggest message ids like -    # "rt-ticket#-transaction#-scrip#-receipient#" - -    $self->SetHeader( 'Message-ID', -                      "<rt-" -                        . $RT::VERSION ."-" -                        . $self->TicketObj->id() . "-" -                        . $self->TransactionObj->id() . "." -                        . rand(20) . "\@" -                        . $RT::Organization . ">" ) +  # TODO this one might be sort of broken.  If we have several scrips +++ +  # sending several emails to several different persons, we need to +  # pull out different message-ids.  I'd suggest message ids like +  # "rt-ticket#-transaction#-scrip#-receipient#" + +  $self->SetHeader +    ('Message-ID', "<rt-".$self->TicketObj->id(). +     "-". +     $self->TransactionObj->id()."." .rand(20) . "\@".$RT::Organization.">")        unless $self->TemplateObj->MIMEObj->head->get('Message-ID');  } -# }}}  # }}} -# {{{ sub SetReturnAddress - -=head2 SetReturnAddress is_comment => BOOLEAN - -Calculate and set From and Reply-To headers based on the is_comment flag. +# }}} -=cut +# {{{ sub SetReturnAddress   sub SetReturnAddress { -    my $self = shift; -    my %args = ( is_comment => 0, -                 @_ ); - -    # From and Reply-To -    # $args{is_comment} should be set if the comment address is to be used. -    my $replyto; - -    if ( $args{'is_comment'} ) { -        $replyto = $self->TicketObj->QueueObj->CommentAddress -          || $RT::CommentAddress; -    } -    else { -        $replyto = $self->TicketObj->QueueObj->CorrespondAddress -          || $RT::CorrespondAddress; -    } - -    unless ( $self->TemplateObj->MIMEObj->head->get('From') ) { -	if ($RT::UseFriendlyFromLine) { -	    my $friendly_name = $self->TransactionObj->CreatorObj->RealName; -	    if ( $friendly_name =~ /^"(.*)"$/ ) {    # a quoted string -		$friendly_name = $1; -	    } - -	    $friendly_name =~ s/"/\\"/g; -	    $self->SetHeader( 'From', -		        sprintf($RT::FriendlyFromLineFormat,  -                $self->MIMEEncodeString( $friendly_name, $RT::EmailOutputEncoding ), $replyto), -	    ); -	} -	else { -	    $self->SetHeader( 'From', $replyto ); -	} -    } - -    unless ( $self->TemplateObj->MIMEObj->head->get('Reply-To') ) { -        $self->SetHeader( 'Reply-To', "$replyto" ); -    } - +  my $self = shift; +  my %args = ( is_comment => 0, +	       @_ ); + +  # From and Reply-To +  # $args{is_comment} should be set if the comment address is to be used. +  my $replyto; + +  if ($args{'is_comment'}) {  +      $replyto = $self->TicketObj->QueueObj->CommentAddress ||  +		  $RT::CommentAddress; +  } +  else { +      $replyto = $self->TicketObj->QueueObj->CorrespondAddress || +		  $RT::CorrespondAddress; +  } +     +  unless ($self->TemplateObj->MIMEObj->head->get('From')) { +      my $friendly_name=$self->TransactionObj->CreatorObj->RealName; + +      if ($friendly_name =~ /^\S+\@\S+$/) { # A "bare" mail address +          $friendly_name =~ s/"/\\"/g; +          $friendly_name = qq|"$friendly_name"|; +      } + + +      # TODO: this "via RT" should really be site-configurable. +      $self->SetHeader('From', "\"$friendly_name via RT\" <$replyto>"); +  } +   +  unless ($self->TemplateObj->MIMEObj->head->get('Reply-To')) { +      $self->SetHeader('Reply-To', "$replyto"); +  } +    }  # }}}  # {{{ sub SetHeader -=head2 SetHeader FIELD, VALUE - -Set the FIELD of the current MIME object into VALUE. - -=cut -  sub SetHeader { -    my $self  = shift; -    my $field = shift; -    my $val   = shift; - -    chomp $val; -    chomp $field; -    $self->TemplateObj->MIMEObj->head->fold_length( $field, 10000 ); -    $self->TemplateObj->MIMEObj->head->replace( $field,     $val ); -    return $self->TemplateObj->MIMEObj->head->get($field); +  my $self = shift; +  my $field = shift; +  my $val = shift; + +  chomp $val;                                                                   +  chomp $field;                                                                 +  $self->TemplateObj->MIMEObj->head->fold_length($field,10000);      +  $self->TemplateObj->MIMEObj->head->add($field, $val); +  return $self->TemplateObj->MIMEObj->head->get($field);  }  # }}} @@ -483,29 +331,21 @@ Dummy method to be overriden by subclasses which want to set the recipients.  sub SetRecipients {      my $self = shift; -    return (); +    return();  }  # }}}  # {{{ sub SetTo -=head2 SetTo - -Takes a string that is the addresses you want to send mail to - -=cut -  sub SetTo { -    my $self      = shift; +    my $self=shift;      my $addresses = shift; -    return $self->SetHeader( 'To', $addresses ); +    return $self->SetHeader('To',$addresses);  } -  # }}}  # {{{ sub SetCc -  =head2 SetCc  Takes a string that is the addresses you want to Cc @@ -513,12 +353,11 @@ Takes a string that is the addresses you want to Cc  =cut  sub SetCc { -    my $self      = shift; +    my $self=shift;      my $addresses = shift; -    return $self->SetHeader( 'Cc', $addresses ); +    return $self->SetHeader('Cc', $addresses);  } -  # }}}  # {{{ sub SetBcc @@ -528,24 +367,23 @@ sub SetCc {  Takes a string that is the addresses you want to Bcc  =cut -  sub SetBcc { -    my $self      = shift; +    my $self=shift;      my $addresses = shift; -    return $self->SetHeader( 'Bcc', $addresses ); +    return $self->SetHeader('Bcc', $addresses);  }  # }}} -# {{{ sub SetPrecedence +# {{{ sub SetPrecedence   sub SetPrecedence { -    my $self = shift; +  my $self = shift; -    unless ( $self->TemplateObj->MIMEObj->head->get("Precedence") ) { -        $self->SetHeader( 'Precedence', "bulk" ); -    } +  unless ($self->TemplateObj->MIMEObj->head->get("Precedence")) {  +    $self->SetHeader('Precedence', "bulk"); +   }  }  # }}} @@ -561,125 +399,70 @@ the transaction's subject.  =cut   sub SetSubject { -    my $self = shift; +  my $self = shift; +  unless ($self->TemplateObj->MIMEObj->head->get('Subject')) { +    my $message=$self->TransactionObj->Message; +    my $ticket=$self->TicketObj->Id; +          my $subject; +     +    if ($self->{'Subject'}) { +      $subject = $self->{'Subject'}; +    } +    elsif (($message->First()) && +	   ($message->First->Headers)) { +      $header = $message->First->Headers(); +      $header =~ s/\n\s+/ /g;  +      if ( $header =~ /^Subject: (.*?)$/m ) { +	$subject = $1; +      } +      else { +	$subject = $self->TicketObj->Subject(); +      } +       +    } +    else { +      $subject = $self->TicketObj->Subject(); +    } +     +    $subject =~ s/(\r\n|\n|\s)/ /gi; -    unless ( $self->TemplateObj->MIMEObj->head->get('Subject') ) { -        my $message = $self->TransactionObj->Attachments; -        my $ticket  = $self->TicketObj->Id; - -        if ( $self->{'Subject'} ) { -            $subject = $self->{'Subject'}; -        } -        elsif (    ( $message->First() ) -                && ( $message->First->Headers ) ) { -            my $header = $message->First->Headers(); -            $header =~ s/\n\s+/ /g; -            if ( $header =~ /^Subject: (.*?)$/m ) { -                $subject = $1; -            } -            else { -                $subject = $self->TicketObj->Subject(); -            } - -        } -        else { -            $subject = $self->TicketObj->Subject(); -        } - -        $subject =~ s/(\r\n|\n|\s)/ /gi; - -        chomp $subject; -        $self->SetHeader( 'Subject', $subject ); - +    chomp $subject; +    $self->SetHeader('Subject',$subject); +          } -    return ($subject); +  return($subject);  } -  # }}}  # {{{ sub SetSubjectToken  =head2 SetSubjectToken -This routine fixes the RT tag in the subject. It's unlikely that you want to overwrite this. + This routine fixes the RT tag in the subject. It's unlikely that you want to overwrite this.  =cut  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 $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"); +  }  }  # }}}  # }}} -# {{{ - -=head2 SetHeaderAsEncoding($field_name, $charset_encoding) - -This routine converts the field into specified charset encoding. - -=cut - -sub SetHeaderAsEncoding { -    my $self = shift; -    my ( $field, $enc ) = ( shift, shift ); - -    if ($field eq 'From' and $RT::SMTPFrom) { -        $self->TemplateObj->MIMEObj->head->replace( $field, $RT::SMTPFrom ); -	return; -    } - -    my $value = $self->TemplateObj->MIMEObj->head->get($field); - -    # don't bother if it's us-ascii - -    # See RT::I18N, 'NOTES:  Why Encode::_utf8_off before Encode::from_to' - -    $value =  $self->MIMEEncodeString($value, $enc); - -    $self->TemplateObj->MIMEObj->head->replace( $field, $value ); - - -}  -# }}} - -# {{{ MIMENcodeString - -=head2 MIMEEncodeString STRING ENCODING - -Takes a string and a possible encoding and returns the string wrapped in MIME goo. - -=cut - -sub MIMEEncodeString { -    my  $self = shift; -    my $value = shift; -    my $enc = shift; +__END__ -    chomp $value; -    return ($value) unless $value =~ /[^\x20-\x7e]/; - -    $value =~ s/\s*$//; -    Encode::_utf8_off($value); -    my $res = Encode::from_to( $value, "utf-8", $enc ); -    $value = encode_mimeword( $value,  'B', $enc ); -} +# {{{ POD  # }}} -eval "require RT::Action::SendEmail_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/SendEmail_Vendor.pm}); -eval "require RT::Action::SendEmail_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/SendEmail_Local.pm}); -  1; diff --git a/rt/lib/RT/Action/SendPasswordEmail.pm b/rt/lib/RT/Action/SendPasswordEmail.pm new file mode 100755 index 000000000..91bb3c1cb --- /dev/null +++ b/rt/lib/RT/Action/SendPasswordEmail.pm @@ -0,0 +1,170 @@ +# $Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Action/Attic/SendPasswordEmail.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $ +# Copyright 2001  Jesse Vincent <jesse@fsck.com> +# Released under the terms of the GNU Public License + +package RT::Action::SendPasswordEmail; +require RT::Action::Generic; + +@ISA = qw(RT::Action::Generic); + + +=head1 NAME + +  RT::Action::SendGenericEmail - An Action which users can use to send mail  +  or can subclassed for more specialized mail sending behavior.  + + + +=head1 SYNOPSIS + +  require RT::Action::SendPasswordEmail; + + +=head1 DESCRIPTION + +Basically, you create another module RT::Action::YourAction which ISA +RT::Action::SendEmail. + +If you want to set the recipients of the mail to something other than +the addresses mentioned in the To, Cc, Bcc and headers in +the template, you should subclass RT::Action::SendEmail and override +either the SetRecipients method or the SetTo, SetCc, etc methods (see +the comments for the SetRecipients sub). + + +=begin testing + +ok (require RT::TestHarness); +ok (require RT::Action::SendPasswordEmail); + +=end testing + + +=head1 AUTHOR + +Jesse Vincent <jesse@bestpractical.com> + +=head1 SEE ALSO + +perl(1). + +=cut + +# {{{ Scrip methods (_Init, Commit, Prepare, IsApplicable) + +# {{{ sub Commit  + +#Do what we need to do and send it out. + +sub Commit  { +    my $self = shift; +    #send the email +     +     +     + +     +    my $MIMEObj = $self->TemplateObj->MIMEObj; +     +     +    $MIMEObj->make_singlepart; +     +    #If we don\'t have any recipients to send to, don\'t send a message; +    unless ($MIMEObj->head->get('To')) { +	$RT::Logger->debug("$self: No recipients found. Not sending.\n"); +	return(1); +    } +     +    if ($RT::MailCommand eq 'sendmailpipe') { +	open (MAIL, "|$RT::SendmailPath $RT::SendmailArguments") || return(0); +	print MAIL $MIMEObj->as_string; +	close(MAIL); +    } +    else { +	unless ($MIMEObj->send($RT::MailCommand, $RT::MailParams)) { +	    $RT::Logger->crit("$self: Could not send mail for ". +			      $self->TransactionObj . "\n"); +	    return(0); +	} +    } +     +    return (1); +     +} +# }}} + +# {{{ sub Prepare  + +sub Prepare  { +    my $self = shift; +     +    # This actually populates the MIME::Entity fields in the Template Object +     +    unless ($self->TemplateObj) { +	$RT::Logger->warning("No template object handed to $self\n"); +    } +     +     +    unless ($self->TemplateObj->MIMEObj->head->get('Reply-To')) { +	$self->SetHeader('Reply-To',$RT::CorrespondAddress ); +    } + +     +    $self->SetHeader('Precedence', "bulk"); +    $self->SetHeader('X-RT-Loop-Prevention', $RT::rtname);  +    $self->SetHeader +      ('Managed-by',"Request Tracker $RT::VERSION (http://www.fsck.com/projects/rt/)"); +     +    $self->TemplateObj->Parse(Argument => $self->Argument); +     +     +    return 1; +} + +# }}} + +# }}} + + +# {{{ sub SetTo + +=head2 SetTo EMAIL + +Sets this message's "To" field to EMAIL + +=cut + +sub SetTo { +    my $self = shift; +    my $to = shift; +    $self->SetHeader('To',$to); +} + +# }}} + +# {{{ sub SetHeader + +sub SetHeader { +  my $self = shift; +  my $field = shift; +  my $val = shift; + +  chomp $val;                                                                   +  chomp $field;                                                                 +  $self->TemplateObj->MIMEObj->head->fold_length($field,10000);      +  $self->TemplateObj->MIMEObj->head->add($field, $val); +  return $self->TemplateObj->MIMEObj->head->get($field); +} + +# }}} + + + +__END__ + +# {{{ POD + +# }}} + +1; + diff --git a/rt/lib/RT/Action/SetPriority.pm b/rt/lib/RT/Action/SetPriority.pm deleted file mode 100644 index 515eeb58c..000000000 --- a/rt/lib/RT/Action/SetPriority.pm +++ /dev/null @@ -1,61 +0,0 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK -package RT::Action::SetPriority; -require RT::Action::Generic; - -use strict; -use vars qw/@ISA/; -@ISA=qw(RT::Action::Generic); - -#Do what we need to do and send it out. - -#What does this type of Action does - -# {{{ sub Describe  -sub Describe  { -  my $self = shift; -  return (ref $self . " will set a ticket's priority to the argument provided."); -} -# }}} - - -# {{{ sub Prepare  -sub Prepare  { -    # nothing to prepare -    return 1; -} -# }}} - -sub Commit { -    my $self = shift; -    $self->TicketObj->SetPriority($self->Argument); - -} - -eval "require RT::Action::SetPriority_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/SetPriority_Vendor.pm}); -eval "require RT::Action::SetPriority_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/SetPriority_Local.pm}); - -1; diff --git a/rt/lib/RT/Action/StallDependent.pm b/rt/lib/RT/Action/StallDependent.pm new file mode 100644 index 000000000..09d3448a8 --- /dev/null +++ b/rt/lib/RT/Action/StallDependent.pm @@ -0,0 +1,68 @@ +# This Action will stall the BASE if a dependency or membership link +# (according to argument) is created and if BASE is open. + +# TODO: Rename this .pm + +package RT::Action::StallDependent; +require RT::Action::Generic; +@ISA=qw|RT::Action::Generic|; + +# {{{ sub Describe  +sub Describe  { +  my $self = shift; +  return (ref $self . " will stall a [local] BASE if it's dependent [or member] of a linked up request."); +} +# }}} + + +# {{{ sub Prepare  +sub Prepare  { +    # nothing to prepare +    return 1; +} +# }}} + +sub Commit { +    my $self = shift; +    # Find all Dependent +    my $arg=$self->Argument || "DependsOn"; +    unless ($self->TransactionObj->Data =~ /^([^ ]+) $arg /) { +	warn; return 0; +    } +    my $base_id=$1; +    my $base; +    if ($1 eq "THIS") { +	$base=$self->TicketObj; +    } else { +	$base_id=&RT::Link::_IsLocal(undef, $base_id) || return 0; +	$base=RT::Ticket->new($self->TicketObj->CurrentUser); +	$base->Load($base_id); +    } +    $base->Stall if $base->Status eq 'open'; +    return 0; +} + + +# {{{ sub IsApplicable  + +# Only applicable if: +# 1. the link action is a dependency +# 2. BASE is a local ticket + +sub IsApplicable  { +  my $self = shift; + +  my $arg=$self->Argument || "DependsOn"; + +  # 1: +  $self->TransactionObj->Data =~ /^([^ ]*) $arg / || return 0; + +  # 2: +  # (dirty!) +  &RT::Link::_IsLocal(undef,$1) || return 0; + +  return 1; +} +# }}} + +1; diff --git a/rt/lib/RT/Action/UserDefined.pm b/rt/lib/RT/Action/UserDefined.pm deleted file mode 100644 index e2e3d72ce..000000000 --- a/rt/lib/RT/Action/UserDefined.pm +++ /dev/null @@ -1,71 +0,0 @@ -# BEGIN LICENSE BLOCK -#  -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> -#  -# (Except where explictly superceded by other copyright notices) -#  -# 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. -#  -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. -#  -#  -# END LICENSE BLOCK -  - -package RT::Action::UserDefined; -use RT::Action::Generic; - -use strict; -use vars qw/@ISA/; -@ISA = qw(RT::Action::Generic); - -=head2 Prepare - -This happens on every transaction. it's always applicable - -=cut - -sub Prepare { -    my $self = shift; -    my $retval = eval $self->ScripObj->CustomPrepareCode; -    if ($@) { -        $RT::Logger->error("Scrip ".$self->ScripObj->Id. " Prepare failed: ".$@); -        return (undef); -    } -    return ($retval); -} - -=head2 Commit - -This happens on every transaction. it's always applicable - -=cut - -sub Commit { -    my $self = shift; -    my $retval = eval $self->ScripObj->CustomCommitCode; -    if ($@) { -        $RT::Logger->error("Scrip ".$self->ScripObj->Id. " Commit failed: ".$@); -        return (undef); -    } -    return ($retval); -} - -eval "require RT::Action::UserDefined_Vendor"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/UserDefined_Vendor.pm}); -eval "require RT::Action::UserDefined_Local"; -die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/UserDefined_Local.pm}); - -1; - | 
