Need help with tickets generated by SPAM

Hi All

I have a spam filter in front of my queue. So all new tickets have to
pass thru the filter before they make it to the queue.
It works fine for most of the tickets. However, once in a while one or
two spams that manage to pass through the filter
as ham and hence create tickets. It is pretty embarrassing. For
regular emails I can just take those emails as it is and then
pass it through my spam learner and that works fine too. However, I am
not sure how I can do the same for a ticket. I
created a SPAM queue and I gave users’ right to drop any ticket that
is a sure spam and just drop them in that queue. So
now what I need is to find a way to take all tickets that are in SPAM
queue and run them through my spam learner. I do not
know how to do that. Any suggestion would be greatly appreciated!

Thanks

Asif Iqbal
PGP Key: 0xE62693C5 KeyServer: pgp.mit.edu
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

Hi All

I have a spam filter in front of my queue. So all new tickets have to
pass thru the filter before they make it to the queue.
It works fine for most of the tickets. However, once in a while one or
two spams that manage to pass through the filter
as ham and hence create tickets. It is pretty embarrassing. For
regular emails I can just take those emails as it is and then
pass it through my spam learner and that works fine too. However, I am
not sure how I can do the same for a ticket. I
created a SPAM queue and I gave users’ right to drop any ticket that
is a sure spam and just drop them in that queue. So
now what I need is to find a way to take all tickets that are in SPAM
queue and run them through my spam learner. I do not
know how to do that. Any suggestion would be greatly appreciated!

Here is a script I made (for 3.6.7, needs little adjustements), it submits
tickets to spamassassin sa-learn program depending on status (I used a "spam"
status).
It runs every day through cron.

#!/usr/bin/perl -w

Submit tickets to sa-learn

The user which run this script needs to be the user who handle Anti-Spam

software and need to have proper rights in RT to access tickets

(Global rights: SeeQueue, ShowTicket)

He also needs to be able to access RT files, especially config file.

use strict;
use lib “/opt/rt/rt/local/lib”;
use lib “/opt/rt/rt/lib”;
use lib “/opt/rt/rt/etc”;
use RT;
use RT::Interface::CLI qw( CleanEnv GetCurrentUser );
use RT::Queue;
use RT::Queues;
use RT::Tickets;
use RT::Date;
use MIME::Entity;
use MIME::Body;

my $debug = 0;
my $spam_status = ‘spam’;
my $ham_status = ‘resolved’;
my $learn_ham_cmd = ‘/usr/bin/sa-learn --ham - > /dev/null’;
my $learn_spam_cmd = ‘/usr/bin/sa-learn --spam - > /dev/null’;

if ($debug) {
$learn_ham_cmd = $learn_spam_cmd = ‘/bin/cat’;
}

Set locales

$ENV{‘LANG’} = ‘POSIX’;
$ENV{‘LC_ALL’} = ‘POSIX’;

RT CLI initialization

CleanEnv();
RT::LoadConfig();
RT::Init();

Get the current user all loaded

our $CurrentUser = GetCurrentUser();

unless( $CurrentUser->Id )
{
print STDERR “No RT user found. Please consult your RT administrator.\n”;
exit 1;
}

Limit to tickets LastUpdated 2 days ago

my $datelimit = new RT::Date($RT::SystemUser);
$datelimit->SetToNow();
$datelimit->AddDays(-1);

my $spam_count = 0;

From RT 3.8

sub ContentAsMIME {
my $self = shift;

my $entity = new MIME::Entity;
$entity->head->add( split /:/, $_, 2 )
    foreach SplitHeaders($self);

use MIME::Body;
$entity->bodyhandle(
    MIME::Body::Scalar->new( $self->OriginalContent )
);

return $entity;

}

sub SplitHeaders {
my $self = shift;
my @headers;
for (split(/\n(?=\w|\z)/,$self->Headers)) {
push @headers, $_ if ($_ !~ /^RT-Send-Bcc/i);
}
return(@headers);
}

sub submit_message ($$) {
my $message = shift;
my $type = shift;
if ($type eq ‘ham’) {
open (CMD, "| $learn_ham_cmd ") or die “Can’t run $learn_ham_cmd: $!\n”;
print CMD $message;
close(CMD);
} elsif ($type eq ‘spam’) {
open (CMD, "| $learn_spam_cmd ") or die “Can’t run $learn_spam_cmd: $!\n”;
print CMD $message;
close(CMD);
} else {
warn “Unknown type: $type\n”;
}
}

sub get_message ($$) {
my $ticket = shift;
my $txn = shift;
my $entity = new MIME::Entity;
my $header = 0;
my $attachments = RT::Attachments->new( $txn->CurrentUser );
$attachments->Limit( FIELD => ‘TransactionId’, VALUE => $txn->id );
$attachments->OrderBy( FIELD => ‘Id’, ORDER => ‘ASC’ );
while ( my $a = $attachments->Next ) {
if (! $header) {
$entity->head->add( split /:/, $_, 2 ) foreach SplitHeaders($a);
$header = 1;
} else {
# Skip multipart declaration
next if (! $a->Content || $a->Content eq ‘’);
$entity->make_multipart unless $entity->is_multipart;
$entity->add_part(ContentAsMIME($a));
}
}

return $entity->as_string;

}

Spams

print “=================SPAM==================\n” if ($debug);
my $queues = new RT::Queues($RT::SystemUser);
$queues->LimitToEnabled();
foreach my $queue (@{$queues->ItemsArrayRef()}) {
my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $spam_status);
$tickets->LimitQueue(VALUE => $queue->Id);
$tickets->LimitLastUpdated(OPERATOR => “>”,
VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
my $txn = $ticket->Transactions->First;
# Skip web created tickets
my $msgattr = $txn->Message->First;
next if (!$msgattr);
next if (!$msgattr->GetHeader(‘Received’));

    $spam_count++;

    my $message = get_message($ticket, $txn);
    submit_message($message, 'spam');

}

}

Ham

print “==================HAM==================\n” if ($debug);
my $ham_count = 0;
foreach my $queue (@{$queues->ItemsArrayRef()}) {

# Limit to same count of ham/spam messages
last if ($ham_count >= $spam_count);

my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $ham_status);
$tickets->LimitQueue(VALUE => $queue->Id);
$tickets->LimitLastUpdated(OPERATOR => ">",
                           VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
    # Limit to same count of ham/spam messages
    last if ($ham_count >= $spam_count);
    my $txn = $ticket->Transactions->First;
    # Skip web created tickets
    my $msgattr = $txn->Message->First;
    next if (!$msgattr);
    next if (!$msgattr->GetHeader('Received'));

    $ham_count++;

    my $message = get_message($ticket, $txn);
    submit_message($message, 'ham');

}

}

vim: expandtab tabstop=4

Let me give that a try, Thanks. (sorry for top posting… did not want
to ruin the format of the script)On Mon, Feb 9, 2009 at 11:28 AM, Emmanuel Lacour elacour@easter-eggs.com wrote:

On Mon, Feb 09, 2009 at 11:00:36AM -0500, Asif Iqbal wrote:

Hi All

I have a spam filter in front of my queue. So all new tickets have to
pass thru the filter before they make it to the queue.
It works fine for most of the tickets. However, once in a while one or
two spams that manage to pass through the filter
as ham and hence create tickets. It is pretty embarrassing. For
regular emails I can just take those emails as it is and then
pass it through my spam learner and that works fine too. However, I am
not sure how I can do the same for a ticket. I
created a SPAM queue and I gave users’ right to drop any ticket that
is a sure spam and just drop them in that queue. So
now what I need is to find a way to take all tickets that are in SPAM
queue and run them through my spam learner. I do not
know how to do that. Any suggestion would be greatly appreciated!

Here is a script I made (for 3.6.7, needs little adjustements), it submits
tickets to spamassassin sa-learn program depending on status (I used a "spam"
status).
It runs every day through cron.

#!/usr/bin/perl -w

Submit tickets to sa-learn

The user which run this script needs to be the user who handle Anti-Spam

software and need to have proper rights in RT to access tickets

(Global rights: SeeQueue, ShowTicket)

He also needs to be able to access RT files, especially config file.

use strict;
use lib “/opt/rt/rt/local/lib”;
use lib “/opt/rt/rt/lib”;
use lib “/opt/rt/rt/etc”;
use RT;
use RT::Interface::CLI qw( CleanEnv GetCurrentUser );
use RT::Queue;
use RT::Queues;
use RT::Tickets;
use RT::Date;
use MIME::Entity;
use MIME::Body;

my $debug = 0;
my $spam_status = ‘spam’;
my $ham_status = ‘resolved’;
my $learn_ham_cmd = ‘/usr/bin/sa-learn --ham - > /dev/null’;
my $learn_spam_cmd = ‘/usr/bin/sa-learn --spam - > /dev/null’;

if ($debug) {
$learn_ham_cmd = $learn_spam_cmd = ‘/bin/cat’;
}

Set locales

$ENV{‘LANG’} = ‘POSIX’;
$ENV{‘LC_ALL’} = ‘POSIX’;

RT CLI initialization

CleanEnv();
RT::LoadConfig();
RT::Init();

Get the current user all loaded

our $CurrentUser = GetCurrentUser();

unless( $CurrentUser->Id )
{
print STDERR “No RT user found. Please consult your RT administrator.\n”;
exit 1;
}

Limit to tickets LastUpdated 2 days ago

my $datelimit = new RT::Date($RT::SystemUser);
$datelimit->SetToNow();
$datelimit->AddDays(-1);

my $spam_count = 0;

From RT 3.8

sub ContentAsMIME {
my $self = shift;

my $entity = new MIME::Entity;
$entity->head->add( split /:/, $_, 2 )
foreach SplitHeaders($self);

use MIME::Body;
$entity->bodyhandle(
MIME::Body::Scalar->new( $self->OriginalContent )
);

return $entity;
}

sub SplitHeaders {
my $self = shift;
my @headers;
for (split(/\n(?=\w|\z)/,$self->Headers)) {
push @headers, $_ if ($_ !~ /^RT-Send-Bcc/i);
}
return(@headers);
}

sub submit_message ($$) {
my $message = shift;
my $type = shift;
if ($type eq ‘ham’) {
open (CMD, "| $learn_ham_cmd ") or die “Can’t run $learn_ham_cmd: $!\n”;
print CMD $message;
close(CMD);
} elsif ($type eq ‘spam’) {
open (CMD, "| $learn_spam_cmd ") or die “Can’t run $learn_spam_cmd: $!\n”;
print CMD $message;
close(CMD);
} else {
warn “Unknown type: $type\n”;
}
}

sub get_message ($$) {
my $ticket = shift;
my $txn = shift;
my $entity = new MIME::Entity;
my $header = 0;
my $attachments = RT::Attachments->new( $txn->CurrentUser );
$attachments->Limit( FIELD => ‘TransactionId’, VALUE => $txn->id );
$attachments->OrderBy( FIELD => ‘Id’, ORDER => ‘ASC’ );
while ( my $a = $attachments->Next ) {
if (! $header) {
$entity->head->add( split /:/, $_, 2 ) foreach SplitHeaders($a);
$header = 1;
} else {
# Skip multipart declaration
next if (! $a->Content || $a->Content eq ‘’);
$entity->make_multipart unless $entity->is_multipart;
$entity->add_part(ContentAsMIME($a));
}
}

return $entity->as_string;

}

Spams

print “=================SPAM==================\n” if ($debug);
my $queues = new RT::Queues($RT::SystemUser);
$queues->LimitToEnabled();
foreach my $queue (@{$queues->ItemsArrayRef()}) {
my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $spam_status);
$tickets->LimitQueue(VALUE => $queue->Id);
$tickets->LimitLastUpdated(OPERATOR => “>”,
VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
my $txn = $ticket->Transactions->First;
# Skip web created tickets
my $msgattr = $txn->Message->First;
next if (!$msgattr);
next if (!$msgattr->GetHeader(‘Received’));

   $spam_count++;

   my $message = get_message($ticket, $txn);
   submit_message($message, 'spam');

}
}

Ham

print “==================HAM==================\n” if ($debug);
my $ham_count = 0;
foreach my $queue (@{$queues->ItemsArrayRef()}) {

Limit to same count of ham/spam messages

last if ($ham_count >= $spam_count);

my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $ham_status);
$tickets->LimitQueue(VALUE => $queue->Id);
$tickets->LimitLastUpdated(OPERATOR => “>”,
VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
# Limit to same count of ham/spam messages
last if ($ham_count >= $spam_count);
my $txn = $ticket->Transactions->First;
# Skip web created tickets
my $msgattr = $txn->Message->First;
next if (!$msgattr);
next if (!$msgattr->GetHeader(‘Received’));

   $ham_count++;

   my $message = get_message($ticket, $txn);
   submit_message($message, 'ham');

}
}

vim: expandtab tabstop=4


List info: http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-devel

Asif Iqbal
PGP Key: 0xE62693C5 KeyServer: pgp.mit.edu
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

Hi All

I have a spam filter in front of my queue. So all new tickets have to
pass thru the filter before they make it to the queue.
It works fine for most of the tickets. However, once in a while one or
two spams that manage to pass through the filter
as ham and hence create tickets. It is pretty embarrassing. For
regular emails I can just take those emails as it is and then
pass it through my spam learner and that works fine too. However, I am
not sure how I can do the same for a ticket. I
created a SPAM queue and I gave users’ right to drop any ticket that
is a sure spam and just drop them in that queue. So
now what I need is to find a way to take all tickets that are in SPAM
queue and run them through my spam learner. I do not
know how to do that. Any suggestion would be greatly appreciated!

Here is a script I made (for 3.6.7, needs little adjustements), it submits

I am using rt 3.4.5 with perl 5.8.6

tickets to spamassassin sa-learn program depending on status (I used a "spam"
status).
It runs every day through cron.

#!/usr/bin/perl -w

Submit tickets to sa-learn

The user which run this script needs to be the user who handle Anti-Spam

software and need to have proper rights in RT to access tickets

(Global rights: SeeQueue, ShowTicket)

He also needs to be able to access RT files, especially config file.

use strict;
use lib “/opt/rt/rt/local/lib”;
use lib “/opt/rt/rt/lib”;
use lib “/opt/rt/rt/etc”;
use RT;
use RT::Interface::CLI qw( CleanEnv GetCurrentUser );
use RT::Queue;
use RT::Queues;
use RT::Tickets;
use RT::Date;
use MIME::Entity;
use MIME::Body;

my $debug = 0;
my $spam_status = ‘spam’;
my $ham_status = ‘resolved’;
my $learn_ham_cmd = ‘/usr/bin/sa-learn --ham - > /dev/null’;
my $learn_spam_cmd = ‘/usr/bin/sa-learn --spam - > /dev/null’;

My spam learner is on a separate host.

if ($debug) {
$learn_ham_cmd = $learn_spam_cmd = ‘/bin/cat’;
}

Set locales

$ENV{‘LANG’} = ‘POSIX’;
$ENV{‘LC_ALL’} = ‘POSIX’;

RT CLI initialization

CleanEnv();
RT::LoadConfig();
RT::Init();

Get the current user all loaded

our $CurrentUser = GetCurrentUser();

unless( $CurrentUser->Id )
{
print STDERR “No RT user found. Please consult your RT administrator.\n”;
exit 1;
}

Limit to tickets LastUpdated 2 days ago

my $datelimit = new RT::Date($RT::SystemUser);
$datelimit->SetToNow();
$datelimit->AddDays(-1);

my $spam_count = 0;

From RT 3.8

sub ContentAsMIME {
my $self = shift;

my $entity = new MIME::Entity;
$entity->head->add( split /:/, $_, 2 )
foreach SplitHeaders($self);

use MIME::Body;
$entity->bodyhandle(
MIME::Body::Scalar->new( $self->OriginalContent )
);

return $entity;
}

sub SplitHeaders {
my $self = shift;
my @headers;
for (split(/\n(?=\w|\z)/,$self->Headers)) {
push @headers, $_ if ($_ !~ /^RT-Send-Bcc/i);
}
return(@headers);
}

sub submit_message ($$) {
my $message = shift;
my $type = shift;
if ($type eq ‘ham’) {
open (CMD, "| $learn_ham_cmd ") or die “Can’t run $learn_ham_cmd: $!\n”;
print CMD $message;
close(CMD);
} elsif ($type eq ‘spam’) {
open (CMD, "| $learn_spam_cmd ") or die “Can’t run $learn_spam_cmd: $!\n”;
print CMD $message;
close(CMD);
} else {
warn “Unknown type: $type\n”;
}
}

sub get_message ($$) {
my $ticket = shift;
my $txn = shift;
my $entity = new MIME::Entity;
my $header = 0;
my $attachments = RT::Attachments->new( $txn->CurrentUser );
$attachments->Limit( FIELD => ‘TransactionId’, VALUE => $txn->id );
$attachments->OrderBy( FIELD => ‘Id’, ORDER => ‘ASC’ );
while ( my $a = $attachments->Next ) {
if (! $header) {
$entity->head->add( split /:/, $_, 2 ) foreach SplitHeaders($a);
$header = 1;
} else {
# Skip multipart declaration
next if (! $a->Content || $a->Content eq ‘’);
$entity->make_multipart unless $entity->is_multipart;
$entity->add_part(ContentAsMIME($a));
}
}

return $entity->as_string;

}

Spams

print “=================SPAM==================\n” if ($debug);
my $queues = new RT::Queues($RT::SystemUser);

I am only interested in SPAM queue (actual name of the queue and all
tickets there that is unresolved)

$queues->LimitToEnabled();
foreach my $queue (@{$queues->ItemsArrayRef()}) {
my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $spam_status);
$tickets->LimitQueue(VALUE => $queue->Id);
$tickets->LimitLastUpdated(OPERATOR => “>”,
VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
my $txn = $ticket->Transactions->First;
# Skip web created tickets
my $msgattr = $txn->Message->First;
next if (!$msgattr);
next if (!$msgattr->GetHeader(‘Received’));

   $spam_count++;

   my $message = get_message($ticket, $txn);
   submit_message($message, 'spam');

}
}

Ham

print “==================HAM==================\n” if ($debug);
my $ham_count = 0;
foreach my $queue (@{$queues->ItemsArrayRef()}) {

Limit to same count of ham/spam messages

last if ($ham_count >= $spam_count);

my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $ham_status);
$tickets->LimitQueue(VALUE => $queue->Id);
$tickets->LimitLastUpdated(OPERATOR => “>”,
VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
# Limit to same count of ham/spam messages
last if ($ham_count >= $spam_count);
my $txn = $ticket->Transactions->First;
# Skip web created tickets
my $msgattr = $txn->Message->First;
next if (!$msgattr);
next if (!$msgattr->GetHeader(‘Received’));

   $ham_count++;

   my $message = get_message($ticket, $txn);
   submit_message($message, 'ham');

}
}

vim: expandtab tabstop=4


List info: http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-devel

Asif Iqbal
PGP Key: 0xE62693C5 KeyServer: pgp.mit.edu
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

Hi All

I have a spam filter in front of my queue. So all new tickets have to
pass thru the filter before they make it to the queue.
It works fine for most of the tickets. However, once in a while one or
two spams that manage to pass through the filter
as ham and hence create tickets. It is pretty embarrassing. For
regular emails I can just take those emails as it is and then
pass it through my spam learner and that works fine too. However, I am
not sure how I can do the same for a ticket. I
created a SPAM queue and I gave users’ right to drop any ticket that
is a sure spam and just drop them in that queue. So
now what I need is to find a way to take all tickets that are in SPAM
queue and run them through my spam learner. I do not
know how to do that. Any suggestion would be greatly appreciated!

Here is a script I made (for 3.6.7, needs little adjustements), it submits
tickets to spamassassin sa-learn program depending on status (I used a "spam"
status).

How do I create a new status in rt 3.4.5? I only see the default ones
open/new/stalled/resolved/rejected/deleted

It runs every day through cron.

#!/usr/bin/perl -w

Submit tickets to sa-learn

The user which run this script needs to be the user who handle Anti-Spam

software and need to have proper rights in RT to access tickets

(Global rights: SeeQueue, ShowTicket)

He also needs to be able to access RT files, especially config file.

use strict;
use lib “/opt/rt/rt/local/lib”;
use lib “/opt/rt/rt/lib”;
use lib “/opt/rt/rt/etc”;
use RT;
use RT::Interface::CLI qw( CleanEnv GetCurrentUser );
use RT::Queue;
use RT::Queues;
use RT::Tickets;
use RT::Date;
use MIME::Entity;
use MIME::Body;

my $debug = 0;
my $spam_status = ‘spam’;
my $ham_status = ‘resolved’;
my $learn_ham_cmd = ‘/usr/bin/sa-learn --ham - > /dev/null’;
my $learn_spam_cmd = ‘/usr/bin/sa-learn --spam - > /dev/null’;

if ($debug) {
$learn_ham_cmd = $learn_spam_cmd = ‘/bin/cat’;
}

Set locales

$ENV{‘LANG’} = ‘POSIX’;
$ENV{‘LC_ALL’} = ‘POSIX’;

RT CLI initialization

CleanEnv();
RT::LoadConfig();
RT::Init();

Get the current user all loaded

our $CurrentUser = GetCurrentUser();

unless( $CurrentUser->Id )
{
print STDERR “No RT user found. Please consult your RT administrator.\n”;
exit 1;
}

Limit to tickets LastUpdated 2 days ago

my $datelimit = new RT::Date($RT::SystemUser);
$datelimit->SetToNow();
$datelimit->AddDays(-1);

my $spam_count = 0;

From RT 3.8

sub ContentAsMIME {
my $self = shift;

my $entity = new MIME::Entity;
$entity->head->add( split /:/, $_, 2 )
foreach SplitHeaders($self);

use MIME::Body;
$entity->bodyhandle(
MIME::Body::Scalar->new( $self->OriginalContent )
);

return $entity;
}

sub SplitHeaders {
my $self = shift;
my @headers;
for (split(/\n(?=\w|\z)/,$self->Headers)) {
push @headers, $_ if ($_ !~ /^RT-Send-Bcc/i);
}
return(@headers);
}

sub submit_message ($$) {
my $message = shift;
my $type = shift;
if ($type eq ‘ham’) {
open (CMD, "| $learn_ham_cmd ") or die “Can’t run $learn_ham_cmd: $!\n”;
print CMD $message;
close(CMD);
} elsif ($type eq ‘spam’) {
open (CMD, "| $learn_spam_cmd ") or die “Can’t run $learn_spam_cmd: $!\n”;
print CMD $message;
close(CMD);
} else {
warn “Unknown type: $type\n”;
}
}

sub get_message ($$) {
my $ticket = shift;
my $txn = shift;
my $entity = new MIME::Entity;
my $header = 0;
my $attachments = RT::Attachments->new( $txn->CurrentUser );
$attachments->Limit( FIELD => ‘TransactionId’, VALUE => $txn->id );
$attachments->OrderBy( FIELD => ‘Id’, ORDER => ‘ASC’ );
while ( my $a = $attachments->Next ) {
if (! $header) {
$entity->head->add( split /:/, $_, 2 ) foreach SplitHeaders($a);
$header = 1;
} else {
# Skip multipart declaration
next if (! $a->Content || $a->Content eq ‘’);
$entity->make_multipart unless $entity->is_multipart;
$entity->add_part(ContentAsMIME($a));
}
}

return $entity->as_string;

}

Spams

print “=================SPAM==================\n” if ($debug);
my $queues = new RT::Queues($RT::SystemUser);
$queues->LimitToEnabled();
foreach my $queue (@{$queues->ItemsArrayRef()}) {
my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $spam_status);
$tickets->LimitQueue(VALUE => $queue->Id);
$tickets->LimitLastUpdated(OPERATOR => “>”,
VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
my $txn = $ticket->Transactions->First;
# Skip web created tickets
my $msgattr = $txn->Message->First;
next if (!$msgattr);
next if (!$msgattr->GetHeader(‘Received’));

   $spam_count++;

   my $message = get_message($ticket, $txn);
   submit_message($message, 'spam');

}
}

Ham

print “==================HAM==================\n” if ($debug);
my $ham_count = 0;
foreach my $queue (@{$queues->ItemsArrayRef()}) {

Limit to same count of ham/spam messages

last if ($ham_count >= $spam_count);

my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $ham_status);
$tickets->LimitQueue(VALUE => $queue->Id);
$tickets->LimitLastUpdated(OPERATOR => “>”,
VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
# Limit to same count of ham/spam messages
last if ($ham_count >= $spam_count);
my $txn = $ticket->Transactions->First;
# Skip web created tickets
my $msgattr = $txn->Message->First;
next if (!$msgattr);
next if (!$msgattr->GetHeader(‘Received’));

   $ham_count++;

   my $message = get_message($ticket, $txn);
   submit_message($message, 'ham');

}
}

vim: expandtab tabstop=4


List info: http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-devel

Asif Iqbal
PGP Key: 0xE62693C5 KeyServer: pgp.mit.edu
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

Hi All

I have a spam filter in front of my queue. So all new tickets have to
pass thru the filter before they make it to the queue.
It works fine for most of the tickets. However, once in a while one or
two spams that manage to pass through the filter
as ham and hence create tickets. It is pretty embarrassing. For
regular emails I can just take those emails as it is and then
pass it through my spam learner and that works fine too. However, I am
not sure how I can do the same for a ticket. I
created a SPAM queue and I gave users’ right to drop any ticket that
is a sure spam and just drop them in that queue. So
now what I need is to find a way to take all tickets that are in SPAM
queue and run them through my spam learner. I do not
know how to do that. Any suggestion would be greatly appreciated!

Here is a script I made (for 3.6.7, needs little adjustements), it submits
tickets to spamassassin sa-learn program depending on status (I used a "spam"
status).
It runs every day through cron.

#!/usr/bin/perl -w

Submit tickets to sa-learn

The user which run this script needs to be the user who handle Anti-Spam

software and need to have proper rights in RT to access tickets

(Global rights: SeeQueue, ShowTicket)

He also needs to be able to access RT files, especially config file.

use strict;
use lib “/opt/rt/rt/local/lib”;
use lib “/opt/rt/rt/lib”;
use lib “/opt/rt/rt/etc”;
use RT;
use RT::Interface::CLI qw( CleanEnv GetCurrentUser );
use RT::Queue;
use RT::Queues;
use RT::Tickets;
use RT::Date;
use MIME::Entity;
use MIME::Body;

my $debug = 0;
my $spam_status = ‘spam’;
my $ham_status = ‘resolved’;
my $learn_ham_cmd = ‘/usr/bin/sa-learn --ham - > /dev/null’;
my $learn_spam_cmd = ‘/usr/bin/sa-learn --spam - > /dev/null’;

if ($debug) {
$learn_ham_cmd = $learn_spam_cmd = ‘/bin/cat’;
}

Set locales

$ENV{‘LANG’} = ‘POSIX’;
$ENV{‘LC_ALL’} = ‘POSIX’;

RT CLI initialization

CleanEnv();
RT::LoadConfig();
RT::Init();

Get the current user all loaded

our $CurrentUser = GetCurrentUser();

unless( $CurrentUser->Id )
{
print STDERR “No RT user found. Please consult your RT administrator.\n”;
exit 1;
}

Limit to tickets LastUpdated 2 days ago

my $datelimit = new RT::Date($RT::SystemUser);
$datelimit->SetToNow();
$datelimit->AddDays(-1);

my $spam_count = 0;

From RT 3.8

sub ContentAsMIME {
my $self = shift;

my $entity = new MIME::Entity;
$entity->head->add( split /:/, $_, 2 )
foreach SplitHeaders($self);

use MIME::Body;
$entity->bodyhandle(
MIME::Body::Scalar->new( $self->OriginalContent )
);

return $entity;
}

sub SplitHeaders {
my $self = shift;
my @headers;
for (split(/\n(?=\w|\z)/,$self->Headers)) {
push @headers, $_ if ($_ !~ /^RT-Send-Bcc/i);
}
return(@headers);
}

sub submit_message ($$) {
my $message = shift;
my $type = shift;
if ($type eq ‘ham’) {
open (CMD, "| $learn_ham_cmd ") or die “Can’t run $learn_ham_cmd: $!\n”;
print CMD $message;
close(CMD);
} elsif ($type eq ‘spam’) {
open (CMD, "| $learn_spam_cmd ") or die “Can’t run $learn_spam_cmd: $!\n”;
print CMD $message;
close(CMD);
} else {
warn “Unknown type: $type\n”;
}
}

sub get_message ($$) {
my $ticket = shift;
my $txn = shift;
my $entity = new MIME::Entity;
my $header = 0;
my $attachments = RT::Attachments->new( $txn->CurrentUser );
$attachments->Limit( FIELD => ‘TransactionId’, VALUE => $txn->id );
$attachments->OrderBy( FIELD => ‘Id’, ORDER => ‘ASC’ );
while ( my $a = $attachments->Next ) {
if (! $header) {
$entity->head->add( split /:/, $_, 2 ) foreach SplitHeaders($a);
$header = 1;
} else {
# Skip multipart declaration
next if (! $a->Content || $a->Content eq ‘’);
$entity->make_multipart unless $entity->is_multipart;
$entity->add_part(ContentAsMIME($a));
}
}

return $entity->as_string;

}

Spams

print “=================SPAM==================\n” if ($debug);
my $queues = new RT::Queues($RT::SystemUser);
$queues->LimitToEnabled();
foreach my $queue (@{$queues->ItemsArrayRef()}) {
my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $spam_status);
$tickets->LimitQueue(VALUE => $queue->Id);

Since every ticket in SPAM queue is a spam I guess I need only
LimitQueue. How do I limit it to only “SPAM” ?

$tickets->LimitLastUpdated(OPERATOR => “>”,
VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
my $txn = $ticket->Transactions->First;
# Skip web created tickets
my $msgattr = $txn->Message->First;
next if (!$msgattr);
next if (!$msgattr->GetHeader(‘Received’));

   $spam_count++;

   my $message = get_message($ticket, $txn);
   submit_message($message, 'spam');

}
}

Ham

print “==================HAM==================\n” if ($debug);
my $ham_count = 0;
foreach my $queue (@{$queues->ItemsArrayRef()}) {

Limit to same count of ham/spam messages

last if ($ham_count >= $spam_count);

my $tickets = new RT::Tickets($RT::SystemUser);
$tickets->LimitStatus(VALUE => $ham_status);
$tickets->LimitQueue(VALUE => $queue->Id);
$tickets->LimitLastUpdated(OPERATOR => “>”,
VALUE => $datelimit->ISO );
while (my $ticket = $tickets->Next) {
# Limit to same count of ham/spam messages
last if ($ham_count >= $spam_count);
my $txn = $ticket->Transactions->First;
# Skip web created tickets
my $msgattr = $txn->Message->First;
next if (!$msgattr);
next if (!$msgattr->GetHeader(‘Received’));

   $ham_count++;

   my $message = get_message($ticket, $txn);
   submit_message($message, 'ham');

}
}

vim: expandtab tabstop=4


List info: http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-devel

Asif Iqbal
PGP Key: 0xE62693C5 KeyServer: pgp.mit.edu
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

We use lotus notes. We have set up a mailbox for RT that gets pulled down
onto a Fedora box using Fetchmail. In RT and in the email that gets sent
to queue watchers, the body of the email appears to have the plain text
email followed by the rich text part. I’ve included the "view source"
output from Lotus below. I am hoping there is something in the
RT_Config.pm file that could eliminate this problem. If anyone has any
thoughts on why this might be happening please let me know. The
installation is on Fedora 8 using the RT package available (installed
with yum) Thanks.

Received: xxxxx
Received: xxxxxSubject: xxxxx
From: xxxxx
Reply-To: xxxxx
In-Reply-To: xxxxx
References: xxxxx
Message-ID: xxxxx
Precedence: bulk
X-RT-Loop-Prevention: IT
RT-Ticket: IT #194
Managed-by: RT 3.6.5 (http://www.bestpractical.com/rt/)
RT-Originator: xxxxx
MIME-Version: 1.0
X-RT-Original-Encoding: utf-8
Date: Mon, 09 Feb 2009 10:43:18 -0500
To: undisclosed-recipients:;
X-MIMETrack: Itemize by SMTP Server on web1/huntalt(Release 6.5.5|November
30, 2005) at
02/09/2009 10:45:32 AM,
Serialize by Notes Client on John Minkle/huntalt(Release
6.5.1|January 21, 2004) at
02/09/2009 11:13:44 AM,
Serialize complete at 02/09/2009 11:13:44 AM
Content-type: multipart/mixed; boundary="----------=_1234194198-1929-0"

This is a multi-part message in MIME format…

------------=_1234194198-1929-0
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=“utf-8”

Mon Feb 09 10:43:18 2009: Request 194 was acted upon.
Transaction: Ticket created by xxxxx
Queue: General
Subject: xxxxx
Owner: Nobody
Requestors: xxxxx
Status: new
Ticket <URL: http://ma/rt3/Ticket/Display.html?id=3D194 >

Hello IT,

xxxxx

------------=_1234194198-1929-0
Content-Transfer-Encoding: 7bit
RT-Attachment: 194/2755/1906
Content-Type: text/html; charset="US-ASCII"
Content-Disposition: inline


Hello IT,



xxxxx


------------=_1234194198-1929-0–