Our customer receives only spam from a certain Top Level Domain, in our case it was .icu. The customer assumes they will never receive legitimate E-Mails from this top level domain. They want all emails from this top level domain to be blacklisted.

According to the MailWatch FAQ (https://docs.mailwatch.org/using/faq.html), question “Can I use wildcards when using the Blacklist/Whitelist (SQLBlackWhiteList)?”, matching top level domains is not currently supported.

So we changed our file /usr/lib/MailScanner/MailScanner/CustomFunctions/SQLBlackWhiteList.pm

In sub LookupList, add $fromtld to the local variables, and use a regular expression to get the fromtld from the message->fromdomain.

Then we added some lines like $BlackWhite->{$to}{$fromtld}; and we are done.

# Based on the address it is going to, choose the right spam white/blacklist.
# Return 1 if the "from" address is white/blacklisted, 0 if not.
sub LookupList {
  my($message, $BlackWhite) = @_;
  return 0 unless $message; # Sanity check the input
  # Find the "from" address and the first "to" address
  my($from, $fromdomain, @todomain, $todomain, @to, $to, $ip, $fromtld);
  $from       = $message->{from};
  $fromdomain = $message->{fromdomain};
  @todomain   = @{$message->{todomain}};
  $todomain   = $todomain[0];
  @to         = @{$message->{to}};
  $to         = $to[0];
  $ip         = $message->{clientip};
  $fromtld    = $message->{fromdomain};
  ($fromtld)  = $fromtld =~ /(\.\w+)$/;
  # It is in the list if either the exact address is listed,
  # or the domain is listed
  return 1 if $BlackWhite->{$to}{$from};
  return 1 if $BlackWhite->{$to}{$fromdomain};
  return 1 if $BlackWhite->{$to}{$fromtld};
  return 1 if $BlackWhite->{$to}{$ip};
  return 1 if $BlackWhite->{$to}{'default'};
  return 1 if $BlackWhite->{$todomain}{$from};
  return 1 if $BlackWhite->{$todomain}{$fromdomain};
  return 1 if $BlackWhite->{$todomain}{$fromtld};
  return 1 if $BlackWhite->{$todomain}{$ip};
  return 1 if $BlackWhite->{$todomain}{'default'};
  return 1 if $BlackWhite->{'default'}{$from};
  return 1 if $BlackWhite->{'default'}{$fromdomain};
  return 1 if $BlackWhite->{'default'}{$fromtld};
  return 1 if $BlackWhite->{'default'}{$ip};
  # It is not in the list
  return 0;
Now you can define .icu on your Blacklist in MailWatch. Beware of the leading dot, don’t forget that!
Tags: , ,
Posted in Hosting, Software Development | Comments Closed

Our Request Tracker works for users in many countries, which are all assigned to areas. There is an IT administrator for each area, which should be added to the CC list for the request that is from one of the countries in his/her area.

We have created a custom field, and used the category to group the countries by areas.

We needed a scrip with an action that needs to know the category of the currently selected value of a custom field.

Condition: User Defined
Action: User Defined
Template: Global Template: Blank
Stage: TransactionCreate

Custom condition:

my $CFName = 'Field/Country';

my $CF = RT::CustomField->new( $RT::SystemUser );
$CF->LoadByNameAndQueue( Name => $CFName, Queue => $self->TicketObj->Queue );

if ( (($self->TransactionObj->Type eq "CustomField" && $self->TransactionObj->Field == $CF->id)
$self->TransactionObj->Type eq "Create" ) &&
($self->TicketObj->FirstCustomFieldValue('Field/Country')) )
return 1;
return 0;

Custom action preparation code:

my $CFName = 'Field/Country';
# for FirstCustomFieldValue see in Record.pm
my $fieldcountryVal = $self->TicketObj->FirstCustomFieldValue($CFName);
my $aita_email = '';
my $area = '';

#see CustomFieldValue_Overlay.pm, sub Category

my $CFObj = new RT::CustomField($RT::SystemUser);
my $valuesObj = $CFObj->ValuesObj();
while (my $myValue = $valuesObj->Next) {
if ($myValue->Name eq $fieldcountryVal)
#$RT::Logger->info($fieldcountryVal." belongs to area ".$myValue->Category);
$area = $myValue->Category;

if ($area eq "Some Area")
$aita_email = 'admin@somearea.ourdomain.org';
elsif ($area eq "Another Area")
$aita_email = 'admin@anotherarea.ourdomain.org';
#if ($aita_email ne '')
my ($ret, $msg) = $self->TicketObj->AddWatcher( Type => "Cc", Email => $aita_email);

if ($ret) {
#$RT::Logger->info("scrip: New watcher added to ticket");

} else {
#$RT::Logger->error("scrip: Failed to add new watcher to ticket");

return 1;

Custom action cleanup code:

return 1;
Tags: ,
Posted in Software Development | Comments Closed

see also http://www.ptitov.net/2008/07/request-tracker-installation-o.html

Here are the steps how to install Request Tracker on CentOS 5 with PostgreSQL:

Install RPM packages

yum install postgresql postgresql-server postgresql-libs
yum install httpd perl-BSD-Resource perl-FCGI perl-Apache-DBI mod_perl
wget http://dag.wieers.com/rpm/packages/rpmforge-release/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
rpm -Uhv rpmforge-release*.rpm

yum install perl-Digest-HMAC perl-Apache-Session perl-Class-Container perl-Class-Data-Inheritable perl-Crypt-DES perl-Devel-StackTrace perl-Exception-Class perl-GD \
perl-GD-Graph perl-GD-Text-Util perl-Hook-LexWrap perl-HTML-Mason perl-HTTP-Server-Simple perl-HTTP-Server-Simple-Mason perl-IO-Socket-INET6 \
perl-Net-SNMP perl-Params-Validate perl-Socket6 perl-UNIVERSAL-require perl-HTML-scrubber perl-Text-WikiFormat perl-XML-RSS perl-Tree-Simple \
perl-Text-Wrapper perl-Module-Versions-Report perl-CSS-Squish \
perl-Term-ReadKey perl-Class-ReturnValue perl-Text-Quoted perl-Calendar-Simple perl-DBIx-SearchBuilder perl-Text-Autoformat \
perl-MailTools perl-Regexp-Common perl-Locale-Maketext-Lexicon perl-Locale-Maketext-Fuzzy perl-Time-HiRes perl-Time-modules perl-TimeDate \
perl-Log-Dispatch perl-Text-Template perl-HTML-Tree perl-HTML-Format \
perl-HTML-Scrubber perl-libwww-perl perl-MIME-tools perl-DBD-mysql

Configuration of Perl modules
To see if all required perl modules have been installed, run this:

/usr/bin/perl -MCPAN -e shell
make testdeps
/usr/bin/perl ./sbin/rt-test-dependencies --verbose --with-pgsql

Also, make sure you have newer versions of IO::File (1.14) and File-Temp (1.21).
Otherwise you get in trouble. More details follow here:


cat testemail.txt | /usr/bin/rt-mailgate --queue MyQueue --action correspond --url http://rt.mydomain.org/
Can't locate object method "seek" via package "File::Temp"

check currently installed version of File::Temp:
perl -le 'use File::Temp; print File::Temp->VERSION'

install the latest version 0.21:

# for reinitialising cpan:
o conf init
i /MIME-tools/
test D/DO/DONEILL/MIME-tools-5.425.tar.gz
i /file-temp/
install T/TJ/TJENNESS/File-Temp-0.21.tar.gz

Problem with attachements:

cat rttestmailatt.txt | /usr/bin/rt-mailgate --debug --queue myQueue --action correspond --url http://rt.mydomain.org
Connecting to http://rt.mydomain.org/REST/1.0/NoAuth/mail-gateway at /usr/bin/rt-mailgate line 102, line 1.
hello http://rt.mydomain.org/REST/1.0/NoAuth/mail-gateway
not ok - Failed to parse this message. Something is likely badly wrong with the message at /usr/bin/rt-mailgate line 112, line 1
another problem:
Can't locate object method "binmode" via package "IO::File" at /usr/lib/perl5/vendor_perl/5.8.5/MIME/Body.pm line 437.

We need version 1.14 of IO::File

perl -le 'use IO::File; print IO::File->VERSION'

requires: yum install gcc
i /IO-1.2301/
install G/GB/GBARR/IO-1.2301.tar.gz

IMPORTANT: need to reload the apache server, otherwise the new perl packages have no effect:
/etc/init.d/httpd reload

I came once across a Cpan problem:

Going to read /root/.cpan/sources/modules/03modlist.data.gz
Unrecognized character \x88 at (eval 29) line 1.

The solution was: delete 03modlist.data.gz, and just run cpan again

Install RT
Download the latest tar.gz file from http://bestpractical.com/rt/download.html
In a tmp directory, not the destination directory:
cd /home/timop
tar xvzf rt-3.6.6.tar.gz
cd rt-3.6.6
./configure –prefix=/usr –enable-layout=RH \
–with-db-host=localhost \
–with-db-dba=rt –with-db-rt-user=rt \
–with-db-database=rt –with-pgsql

Check to see if all dependancies are installed:
make testdeps | grep MISSING
make install

You then need to configure /etc/rt/RT_SiteConfig.pm
e.g. if you want to use Postgresql, it could look like this:

# {{{ Database Configuration

# Database driver beeing used. Case matters
# Valid types are "mysql", "Oracle" and "Pg"

Set($DatabaseType , 'Pg');

# The domain name of your database server
# If you're running mysql and it's on localhost,
# leave it blank for enhanced performance
Set($DatabaseHost , 'localhost');
Set($DatabaseRTHost , 'localhost');

# The port that your database server is running on. Ignored unless it's
# a positive integer. It's usually safe to leave this blank
Set($DatabasePort , '');

#The name of the database user (inside the database)
Set($DatabaseUser , 'rt');

# Password the DatabaseUser should use to access the database
Set($DatabasePassword , 'secret');

# The name of the RT's database on your database server
Set($DatabaseName , 'rt');

# If you're using Postgres and have compiled in SSL support,
# set DatabaseRequireSSL to 1 to turn on SSL communication
Set($DatabaseRequireSSL , undef);

# }}}

Configuration of PostgreSQL
vi /var/lib/pgsql/data/postgresql.conf;
For PostgreSQL 7.x: add line: tcpip_socket=true;
For PostgreSQL 8.x: listen_addresses = ‘localhost’

vi /var/lib/pgsql/data/pg_hba.conf; it should contain:
local all all ident sameuser
host template1 rt md5
host rt rt md5
host all postgres trust

/etc/init.d/postgresql start
postgresql logfile if db does not start: /var/lib/pgsql/pgstartup.log
chkconfig postgresql on
make initialize-database: problem: user rt does not exist; need to use dba postgres
/usr/bin/perl //usr/sbin/rt-setup-database –action init –dba postgres –prompt-for-dba-password

For a nightly backup of your database, you can use this command:

su - postgres -c "umask 0077; pg_dumpall | gzip > /var/lib/pgsql/data/backup.sql.gz"

To restore a database, e.g. when moving from one server to another:

su - postgres
psql template1
drop database rt;
create database rt;
psql rt
HTTPD configuration
/etc/httpd/conf.d/rt.conf should contain:

ServerName rt.mysupport.com
DocumentRoot /var/rt/html
AddDefaultCharset UTF-8

ServerAdmin Timotheus.Pokorra@mysupport.com
PerlModule Apache::DBI
PerlRequire /usr/bin/webmux.pl

Options None
SetHandler perl-script
PerlHandler RT::Mason

PerlFixupHandler Apache::SmallProf

SetHandler default-handler

# To use this you have to start apache with -DPerlStatus.
# In RHEL, add the following line to /etc/sysconfig/httpd:
# OPTIONS=-DPerlStatus

SetHandler perl-script
PerlHandler Apache2::Status
PerlSetVar StatusOptionsAll On
PerlSetVar StatusTerse On
PerlSetVar StatusTerseSize On
PerlSetVar StatusTerseSizeMainSummary On
PerlSetVar StatusLexInfo On

To solve issues with "Can't change ownership of files written by interp object: Permission denied" when running Apache:
chcon -Rt httpd_sys_content_t /var/rt/mason_data/obj

chown -R apache /var/rt/mason_data/obj
chgrp -R apache /var/rt/mason_data/obj
chcon -Rt httpd_sys_content_t /var/rt/html
not: chcon -Rt httpd_sys_script_t /var/rt/html
/etc/init.d/httpd restart

To solve issues after upgrading RT, I had to do this sometimes:

rm -fr /var/rt/mason_data/obj
mkdir /var/rt/mason_data/obj
touch /var/rt/mason_data/obj/.__obj_create_marker
chmod -R a+w /var/rt/mason_data/obj
/etc/init.d/httpd restart

Configure Sendmail
The goal is to receive new requests via email.

You need to create a symbolic link, to avoid errors like "DSN: Service unavailable" or "write error: Broken pipe" in /var/log/maillog

ln -s /usr/bin/rt-mailgate /etc/smrsh

I have these lines in my /etc/aliases file:
my-support-comment: "|/etc/smrsh/rt-mailgate --queue MySupport --action comment --url http://rt.mysupport.com/"
my-support: "|/etc/smrsh/rt-mailgate --queue MySupport --action correspond --url http://rt.mysupport.com/"

Make sure that your server knows about rt.mysupport.com, you might need to add it to /etc/hosts.

You can test the delivery of emails:

echo "test" | mail my-support@rt.mysupport.com -s "test rt"
tail -f /var/log/maillog
or even more directly:
cat testemail.txt |/etc/smrsh/rt-mailgate --queue MySupport --action correspond --url http://rt.mysupport.com/

One other error I got was: "Relaying denied. IP name lookup failed" in /var/log/maillog
The problem was that emails were delivered to ticket.mycompany.com, and the rt server was at rt.mysupport.com.
I had to edit the file /etc/mail/local-host-names
and add the line ticket.mycompany.com