Modified rt-crontool

Hi all,

I’d like to use rt-crontool to spot certain tickets, then email to
their owners. But rt-crontool seems not working with
RT::Action::SendEmail because of RT::Transaction. I modified
rt-crontool and took RT::Transaction out of RT::Action::SendEmail.
The folllowing are diff to rt-crontool against version 2.1.31, and the
resulting RT::Action::LightWeightSendEmail. There is also a
RT::Action::SystemNotify that is almost identical to
RT::Action::Notify.

rt-crontool now knows about RT::Template. It can be used as:

rt-crontool
–search RT::Search::ActiveTicketsInQueue --search-arg general
–action RT::Action::SystemNotify --action-arg Owner,AdminCc
–template-id 1

Then every owners and admincc’s will be bombed by emails.

Of course you may never want to use template #1. You can create
a new template to work with RT::Action::LightWeightSendEmail, the only
exception is that RT::Transaction is not allowed in templates. Recall
that rt-crontool don’t have any RT::Transaction.

plasma

--- rt-crontool.orig Tue Aug 27 16:43:13 2002 +++ rt-crontool Thu Sep 12 14:29:09 2002 @@ -11,6 +11,7 @@

use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);
use RT::Tickets;
+use RT::Template;

#Clean out all the nasties from the environment
CleanEnv();
@@ -33,6 +34,7 @@
}

my ( $search, $condition, $action, $search_arg, $condition_arg, $action_arg,

  • $template_id,
    $help, $verbose );
    

GetOptions( “search=s” => $search,
“search-arg=s” => $search_arg,
@@ -40,6 +42,7 @@
“condition-arg=s” => $condition_arg,
“action-arg=s” => $action_arg,
“action=s” => $action,

  •       "template-id=s"   => \$template_id,
           "help"            => \$help,
           "verbose|v"       => \$verbose );
    

@@ -50,6 +53,13 @@
load_module($action) if ($action);
load_module($condition) if ($condition);

+# load template if specified
+my $template_obj;
+if ($template_id) {

  • $template_obj = RT::Template->new($RT::Nobody);
  • $template_obj->LoadById($template_id);
    +}
    #At the appointed time:

#find a bunch of tickets
@@ -78,6 +88,7 @@

 #prepare our action
 my $action_obj = $action->new( TicketObj => $ticket,
  •                              TemplateObj => $template_obj,
                                  Argument  => $action_arg );
    

    #if our preparation, move onto the next ticket

    RT::Action::LightWeightSendEmail
    package RT::Action::LightWeightSendMail;
    require RT::Action::SendEmail;
    @ISA = qw(RT::Action::SendEmail);

=head1 NAME

RT::Action::LightWeightSendmail - An action which users can use to
send mail out of RT (ex., in rt-crontool) without a RT::Transaction
object. It can be subclassed for more specialized mail sending
behavior.

You can pass it with an RT::Template object, but you can not use
$Transaction in it because it’s alwasy undef.

=cut

{{{ sub Describe

sub Describe {
my $self = shift;
return (ref $self . " will send an email to ticket’s owner.\n");
}

}}}

{{{ 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->TicketObj) {
$RT::Logger->warning("No ticket object handed to $self\n");
}


$self->TemplateObj->Parse(Argument => $self->Argument,
		      TicketObj => $self->TicketObj);

# Header

$self->SetSubject();

$self->SetSubjectToken();

$self->SetRecipients();  

$self->SetReturnAddress();

$self->SetRTSpecialHeaders();

return 1;

}

}}}

{{{ sub Commit

#Do what we need to do and send it out.
sub Commit {
my $self = shift;

# 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;
$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->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'}}) 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 {
unless ($MIMEObj->send($RT::MailCommand, $RT::MailParams)) {
    $RT::Logger->crit("$self: Could not send mail for ".$self->TransactionObj."\n");
    return(0);
}
}

return (1);

}

}}}

{{{ Deal with message headers (Set* subs, designed for easy overriding)

{{{ sub SetRTSpecialHeaders

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->SetPrecedence();

$self->SetHeader('X-RT-Loop-Prevention', $RT::rtname); 
$self->SetHeader('RT-Ticket', $RT::rtname. " #".$self->TicketObj->id());
$self->SetHeader
  ('Managed-by',"Request Tracker $RT::VERSION (http://www.fsck.com/projects/rt/)");

return();

}

}}}

{{{ 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(‘Reply-To’)) {
$self->SetHeader(‘Reply-To’, “$replyto”);
}
}

}}}

{{{ sub SetSubject

sub SetSubject {
my $self = shift;

my $subject = $self->{'Subject'} || "An email from RT";
$self->SetHeader('Subject', $subject);

return $subject;

}

}}}

1;
</RT::Action::LightWeightSendEmail>
RT::Action::SystemNotify
package RT::Action::SystemNotify;
require RT::Action::LightWeightSendMail;

@ISA = qw(RT::Action::LightWeightSendMail);

{{{ sub SetRecipients

=head2 SetRecipients

Sets the recipients of this meesage to Owner, Requestor, AdminCc, Cc or All.
Explicitly B notify the creator of the transaction.

=cut

sub SetRecipients {
my $self = shift;

my $arg = $self->Argument;

$arg =~ s/\bAll\b/Owner,Requestor,AdminCc,Cc/;

my ( @To, @PseudoTo, @Cc, @Bcc );


if ( $arg =~ /\bRequestor\b/ ) {
    push ( @To, $self->TicketObj->Requestors->MemberEmailAddresses  );
}

if ( $arg =~ /\bCc\b/ ) {
    #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  );
    }
    else {
        push ( @Cc, $self->TicketObj->Cc->MemberEmailAddresses  );
        push ( @To, $self->TicketObj->QueueObj->Cc->MemberEmailAddresses  );
    }
}

if ( ( $arg =~ /\bOwner\b/ )
    && ( $self->TicketObj->OwnerObj->id != $RT::Nobody->id ) )
{
    # If we're not sending to Ccs or requestors, 
    # then the Owner can be the To.
    if (@To) {
        push ( @Bcc, $self->TicketObj->OwnerObj->EmailAddress );
    }
    else {
        push ( @To, $self->TicketObj->OwnerObj->EmailAddress );
    }

}

if ( $arg =~ /\bAdminCc\b/ ) {
    push ( @Bcc, $self->TicketObj->AdminCc->MemberEmailAddresses  );
    push ( @Bcc, $self->TicketObj->QueueObj->AdminCc->MemberEmailAddresses  );
}

if ($RT::UseFriendlyToLine) {
    unless (@To) {
        push ( @PseudoTo,
            "'$arg of $RT::rtname Ticket #"
              . $self->TicketObj->id . "':;" );
    }
}

#Strip the sender out of the To, Cc and AdminCc and set the 
# recipients fields used to build the message by the superclass.

$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'} }  = @To;
@{ $self->{'Cc'} }  = @Cc;
@{ $self->{'Bcc'} } = @Bcc;
@{ $self->{'PseudoTo'} } = @PseudoTo;
return (1);

}

}}}

1;
</RT::Action::SystemNotify>

PC home �q�l�H�c�A�ӽнЦ�: http://www.pchome.com.tw
PC home Online �����a�x�G�|���Ĥ@�A�x�W�̤j���J�f����

I just noticed there’s a bug in LightWeightSendMail.pm. Please change
the line in subroutine SetSubject:

my $subject = $self->{'Subject'} || "An email from RT";

to

my $subject = $self->TemplateObj->MIMEObj->head->get('Subject') ||
          $self->{'Subject'} ||
	  "An email from RT";

Then setting subject in a template will work.

plasma

PC home �q�l�H�c�A�ӽнЦ�: http://www.pchome.com.tw
PC home Online �����a�x�G�|���Ĥ@�A�x�W�̤j���J�f����