X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=rt%2Fbin%2Frt-mailgate;h=e6f0d95c5d3963605889ce9398c95c8a4a60d8e4;hp=b304436387e46fc0bf0899583d19ddef9c32ec98;hb=0ebeec96313dd7edfca340f01f8fbbbac1f4aa1d;hpb=945721f48f74d5cfffef7c7cf3a3d6bc2521f5dd diff --git a/rt/bin/rt-mailgate b/rt/bin/rt-mailgate index b30443638..e6f0d95c5 100755 --- a/rt/bin/rt-mailgate +++ b/rt/bin/rt-mailgate @@ -1,587 +1,367 @@ -#!/usr/bin/perl -w -# BEGIN LICENSE BLOCK -# -# Copyright (c) 1996-2003 Jesse Vincent -# -# (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-mailgate - Mail interface to RT3. - -=begin testing - -use RT::I18N; - - -# {{{ Test new ticket creation by root who is privileged and superuser - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL <new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); -my $tick = $tickets->First(); -ok (UNIVERSAL::isa($tick,'RT::Ticket')); -ok ($tick->Id, "found ticket ".$tick->Id); -ok ($tick->Subject eq 'This is a test of new ticket creation', "Created the ticket"); +#!!!PERL!! -w -# }}} - - -# {{{This is a test of new ticket creation as an unknown user - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL <new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -$tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); -ok ($tick->Subject ne 'This is a test of new ticket creation as an unknown user', "failed to create the new ticket from an unprivileged account"); -my $u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist@example.com'); -ok( $u->Id == 0, " user does not exist and was not created by failed ticket submission"); - - -# }}} - -# {{{ now everybody can create tickets. can a random unkown user create tickets? - -my $g = RT::Group->new($RT::SystemUser); -$g->LoadSystemInternalGroup('Everyone'); -ok( $g->Id, "Found 'everybody'"); - -my ($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'CreateTicket'); -ok ($val, "Granted everybody the right to create tickets - $msg"); - -sleep(60); # gotta sleep so the remote process' ACL cache times out - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL < +# This software is redistributable under the terms of the GNU GPL -$tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id' ,OPERATOR => '>', VALUE => '0'); -$tick = $tickets->First(); -ok ($tick->Id, "found ticket ".$tick->Id); -ok ($tick->Subject eq 'This is a test of new ticket creation as an unknown user', "failed to create the new ticket from an unprivileged account"); -my $u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist@example.com'); -ok( $u->Id != 0, " user does not exist and was created by ticket submission"); +package RT; +use strict; +use vars qw($VERSION $Handle $Nobody $SystemUser); + +$VERSION="!!RT_VERSION!!"; + + +use lib "!!RT_LIB_PATH!!"; +use lib "!!RT_ETC_PATH!!"; + +use RT::Interface::Email qw(CleanEnv LoadConfig DBConnect + GetCurrentUser + GetMessageContent + CheckForLoops + CheckForSuspiciousSender + CheckForAutoGenerated + ParseMIMEEntityFromSTDIN + ParseTicketId + MailError + ParseCcAddressesFromHead + ParseSenderAddressFromHead + ParseErrorsToAddressFromHead + ); + +#Clean out all the nasties from the environment +CleanEnv(); + +#Load etc/config.pm and drop privs +LoadConfig(); + +#Connect to the database and get RT::SystemUser and RT::Nobody loaded +DBConnect(); + +#Drop setgid permissions +RT::DropSetGIDPermissions(); + +use RT::Ticket; +use RT::Queue; +use MIME::Parser; +use File::Temp; +use Mail::Address; + + +#Set some sensible defaults +my $Queue = 1; +my $time = time; +my $Action = "correspond"; + +my ($Verbose, $ReturnTid, $Debug); +my ($From, $TicketId, $Subject,$SquelchReplies); + +# using --owner-from-extension, this will let you set ticket owner on create +my $AssignTicketTo = undef; +my ($status, $msg); + +# {{{ parse commandline + +while (my $flag = shift @ARGV) { + if (($flag eq '-v') or ($flag eq '--verbose')) { + $Verbose = 1; + } + if (($flag eq '-t') or ($flag eq '--ticketid')) { + $ReturnTid = 1; + } + + if (($flag eq '-d') or ($flag eq '--debug')) { + $RT::Logger->debug("Debug mode enabled\n"); + $Debug = 1; + } + + if (($flag eq '-q') or ($flag eq '--queue')) { + $Queue = shift @ARGV; + } + if ($flag eq '--ticket-id-from-extension') { + $TicketId = $ENV{'EXTENSION'}; + } + if ($flag eq '--queue-from-extension') { + $Queue = $ENV{'EXTENSION'}; + } + if ($flag eq '--owner-from-extension') { + $AssignTicketTo = $ENV{'EXTENSION'}; + } + + if (($flag eq '-a') or ($flag eq '--action')) { + $Action = shift @ARGV; + } + + +} # }}} +# get the current mime entity from stdin +my ($entity, $head) = ParseMIMEEntityFromSTDIN(); -# {{{ can another random reply to a ticket without being granted privs? answer should be no. - - -#($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'CreateTicket'); -#ok ($val, "Granted everybody the right to create tickets - $msg"); -#sleep(60); # gotta sleep so the remote process' ACL cache times out - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL <Id]}] This is a test of a reply as an unknown user - -Blah! -Foob! -EOF -close (MAIL); - -$u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist-2@example.com'); -ok( $u->Id == 0, " user does not exist and was not created by ticket correspondence submission"); -# }}} -# {{{ can another random reply to a ticket after being granted privs? answer should be yes +#Get someone to send runtime errors to; +my $ErrorsTo = ParseErrorsToAddressFromHead($head); +#Get us a current user object. +my $CurrentUser = GetCurrentUser($head, $entity, $ErrorsTo); -($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'ReplyToTicket'); -ok ($val, "Granted everybody the right to reply to tickets - $msg"); -sleep(60); # gotta sleep so the remote process' ACL cache times out +# We've already performed a warning and sent the mail off to somewhere safe ($RTOwner). +# this is _exceedingly_ unlikely but we don't want to keep going if we don't have a current user -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); -print MAIL <Id]}] This is a test of a reply as an unknown user +unless ($CurrentUser->Id) { + exit(1); +} -Blah! -Foob! -EOF -close (MAIL); +my $MessageId = $head->get('Message-Id') || + ""; +#Pull apart the subject line +$Subject = $head->get('Subject') || "[no subject]"; +chomp $Subject; -$u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist-2@example.com'); -ok( $u->Id != 0, " user exists and was created by ticket correspondence submission"); +# Get the ticket ID unless it's already set +$TicketId = ParseTicketId($Subject) unless ($TicketId); -# }}} +#Set up a queue object +my $QueueObj = RT::Queue->new($CurrentUser); +$QueueObj->Load($Queue); +unless ($QueueObj->id ) { -# {{{ can another random comment on a ticket without being granted privs? answer should be no. + MailError(To => $RT::OwnerEmail, + Subject => "RT Bounce: $Subject", + Explanation => "RT couldn't find the queue: $Queue", + MIMEObj => $entity); +} -#($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'CreateTicket'); -#ok ($val, "Granted everybody the right to create tickets - $msg"); -#sleep(60); # gotta sleep so the remote process' ACL cache times out +# {{{ Lets check for mail loops of various sorts. -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action comment"), "Opened the mailgate - $@"); -print MAIL <Id]}] This is a test of a comment as an unknown user +my $IsAutoGenerated = CheckForAutoGenerated($head); -Blah! -Foob! -EOF -close (MAIL); +my $IsSuspiciousSender = CheckForSuspiciousSender($head); -$u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist-3@example.com'); -ok( $u->Id == 0, " user does not exist and was not created by ticket comment submission"); +my $IsALoop = CheckForLoops($head); -# }}} -# {{{ can another random reply to a ticket after being granted privs? answer should be yes +#If the message is autogenerated, we need to know, so we can not +# send mail to the sender +if ($IsSuspiciousSender || $IsAutoGenerated || $IsALoop) { + $SquelchReplies = 1; -($val,$msg) = $g->PrincipalObj->GrantRight(Right => 'CommentOnTicket'); -ok ($val, "Granted everybody the right to reply to tickets - $msg"); -sleep(60); # gotta sleep so the remote process' ACL cache times out + $ErrorsTo = $RT::OwnerEmail; + + #TODO: Is what we want to do here really + # "Make the requestor cease to get mail from RT"? + # This might wreak havoc with vacation-mailing users. + # Maybe have a "disabled for bouncing" state that gets + # turned off when we get a legit incoming message -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action comment"), "Opened the mailgate - $@"); -print MAIL <Id]}] This is a test of a comment as an unknown user - -Blah! -Foob! -EOF -close (MAIL); +} -$u = RT::User->new($RT::SystemUser); -$u->Load('doesnotexist-3@example.com'); -ok( $u->Id != 0, " user exists and was created by ticket comment submission"); +# {{{ Warn someone if it's a loop + +# Warn someone if it's a loop, before we drop it on the ground +if ($IsALoop) { + $RT::Logger->crit("RT Received mail ($MessageId) from itself."); + + #Should we mail it to RTOwner? + if ($RT::LoopsToRTOwner) { + MailError(To => $RT::OwnerEmail, + Subject => "RT Bounce: $Subject", + Explanation => "RT thinks this message may be a bounce", + MIMEObj => $entity); + + #Do we actually want to store it? + exit unless ($RT::StoreLoops); + } +} # }}} -# {{{ Testing preservation of binary attachments -# Get a binary blob (Best Practical logo) + #Don't let the user stuff the RT-Squelch-Replies-To header. + if ($head->get('RT-Squelch-Replies-To')) { + $head->add('RT-Relocated-Squelch-Replies-To', + $head->get('RT-Squelch-Replies-To')); + $head->delete('RT-Squelch-Replies-To') + } -# Create a mime entity with an attachment -use MIME::Entity; -my $entity = MIME::Entity->build( From => 'root@localhost', - To => 'rt@localhost', - Subject => 'binary attachment test', - Data => ['This is a test of a binary attachment']); +if ($SquelchReplies) { + ## TODO: This is a hack. It should be some other way to + ## indicate that the transaction should be "silent". -# currently in lib/t/autogen -$entity->attach(Path => '../../../html/NoAuth/images/spacer.gif', - Type => 'image/gif', - Encoding => 'base64'); - -# Create a ticket with a binary attachment -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); - -$entity->print(\*MAIL); - -close (MAIL); - -my $tickets = RT::Tickets->new($RT::SystemUser); -$tickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); - $tick = $tickets->First(); -ok (UNIVERSAL::isa($tick,'RT::Ticket')); -ok ($tick->Id, "found ticket ".$tick->Id); -ok ($tick->Subject eq 'binary attachment test', "Created the ticket - ".$tick->Id); - -my $file = `cat ../../../html/NoAuth/images/spacer.gif`; -ok ($file, "Read in the logo image"); - - - use Digest::MD5; -warn "for the raw file the content is ".Digest::MD5::md5_base64($file); - - - -# Verify that the binary attachment is valid in the database -my $attachments = RT::Attachments->new($RT::SystemUser); -$attachments->Limit(FIELD => 'ContentType', VALUE => 'image/gif'); -ok ($attachments->Count == 1, 'Found only one gif in the database'); -my $attachment = $attachments->First; -my $acontent = $attachment->Content; - - warn "coming from the database, the content is ".Digest::MD5::md5_base64($acontent); - -is( $acontent, $file, 'The attachment isn\'t screwed up in the database.'); -# Log in as root -use Getopt::Long; -use LWP::UserAgent; - - -# Grab the binary attachment via the web ui -my $ua = LWP::UserAgent->new(); - -my $full_url = "http://localhost/Ticket/Attachment/".$attachment->TransactionId."/".$attachment->id."/spacer.gif?&user=root&pass=password"; -my $r = $ua->get( $full_url); - - -# Verify that the downloaded attachment is the same as what we uploaded. -is($file, $r->content, 'The attachment isn\'t screwed up in download'); - - - -# }}} - -# {{{ Simple I18N testing - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); - -print MAIL <new($RT::SystemUser); -$unitickets->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$unitickets->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); -my $unitick = $unitickets->First(); -ok (UNIVERSAL::isa($unitick,'RT::Ticket')); -ok ($unitick->Id, "found ticket ".$unitick->Id); -ok ($unitick->Subject eq 'This is a test of I18N ticket creation', "Created the ticket - ". $unitick->Subject); - - - -my $unistring = "\303\241\303\251\303\255\303\263\303\272"; -Encode::_utf8_on($unistring); -is ($unitick->Transactions->First->Content, $unitick->Transactions->First->Attachments->First->Content, "Content is ". $unitick->Transactions->First->Attachments->First->Content); -ok($unitick->Transactions->First->Attachments->First->Content =~ /$unistring/i, $unitick->Id." appears to be unicode ". $unitick->Transactions->First->Attachments->First->Id); -# supposedly I18N fails on the second message sent in. - -ok(open(MAIL, "|/opt/rt3/bin/rt-mailgate --url http://localhost/ --queue general --action correspond"), "Opened the mailgate - $@"); - -print MAIL <new($RT::SystemUser); -$tickets2->OrderBy(FIELD => 'id', ORDER => 'DESC'); -$tickets2->Limit(FIELD => 'id', OPERATOR => '>', VALUE => '0'); -my $tick2 = $tickets2->First(); -ok (UNIVERSAL::isa($tick2,'RT::Ticket')); -ok ($tick2->Id, "found ticket ".$tick2->Id); -ok ($tick2->Subject eq 'This is a test of I18N ticket creation', "Created the ticket"); - - - -my $unistring = "\303\241\303\251\303\255\303\263\303\272"; -Encode::_utf8_on($unistring); - -ok ($tick2->Transactions->First->Content =~ $unistring, "It appears to be unicode - ".$tick2->Transactions->First->Content); + my ($Sender, $junk) = ParseSenderAddressFromHead($head); + $head->add('RT-Squelch-Replies-To', $Sender); +} # }}} -($val,$msg) = $g->PrincipalObj->RevokeRight(Right => 'CreateTicket'); -ok ($val, $msg); +# {{{ If we require that the sender be found in an external DB and they're not +# forward this message to RTOwner -=end testing +if ($RT::LookupSenderInExternalDatabase && + $RT::SenderMustExistInExternalDatabase ) { -=cut - - -use strict; -use Getopt::Long; -use LWP::UserAgent; - -use constant EX_TEMPFAIL => 75; - -my %opts; -GetOptions( \%opts, "queue=s", "action=s", "url=s", "jar=s", "help", "debug", "extension=s" ); - -if ( $opts{help} ) { - require Pod::Usage; - import Pod::Usage; - pod2usage("RT Mail Gateway\n"); - exit 1; # Don't want to succeed if this is really an email! + MailError(To => $RT::OwnerEmail, + Subject => "RT Bounce: $Subject", + Explanation => "RT couldn't find requestor via its external database lookup", + MIMEObj => $entity); + } -for (qw(url)) { - die "$0 invoked improperly\n\nNo $_ provided to mail gateway!\n" unless $opts{$_}; -} - -undef $/; -my $message = <>; -my $ua = LWP::UserAgent->new(); -$ua->cookie_jar( { file => $opts{jar} } ); - -my %args = ( - queue => $opts{queue}, - action => $opts{action}, - message => $message, - SessionType => 'REST', # Surpress login box -); - +# }}} -if ($opts{'extension'}) { - $args{$opts{'extension'}} = $ENV{'EXTENSION'}; +# {{{ elsif we don't have a ticket Id, we're creating a new ticket + + + +elsif (!defined($TicketId)) { + + # {{{ Create a new ticket + if ($Action =~ /correspond/) { + + # open a new ticket + my @Requestors = ($CurrentUser->id); + + my @Cc; + if ($RT::ParseNewMessageForTicketCcs) { + @Cc = ParseCcAddressesFromHead(Head => $head, + CurrentUser => $CurrentUser, + QueueObj => $QueueObj ); + } + + my $Ticket = new RT::Ticket($CurrentUser); + my ($id, $Transaction, $ErrStr) = + $Ticket->Create ( Queue => $Queue, + Subject => $Subject, + Owner => $AssignTicketTo, + Requestor => \@Requestors, + Cc => \@Cc, + MIMEObj => $entity + ); + if ($id == 0 ) { + MailError( To => $ErrorsTo, + Subject => "Ticket creation failed", + Explanation => $ErrStr, + MIMEObj => $entity + ); + $RT::Logger->error("Create failed: $id / $Transaction / $ErrStr "); + } + } + + # }}} + + else { + #TODO Return an error message + MailError( To => $ErrorsTo, + Subject => "No ticket id specified", + Explanation => "$Action aliases require a TicketId to work on", + MIMEObj => $entity + ); + + $RT::Logger->crit("$Action aliases require a TicketId to work on ". + "(from ".$CurrentUser->UserObj->EmailAddress.") ". + $MessageId); + } } -# Set up cookie here. - -my $full_url = $opts{'url'}. "/REST/1.0/NoAuth/mail-gateway"; -warn "Connecting to $full_url" if $opts{'debug'}; - - - -my $r = $ua->post( $full_url, {%args} ); -check_failure($r); - -my $content = $r->content; -warn $content if ($opts{debug}); - -if ( $content !~ /^(ok|not ok)/ ) { - - # It's not the server's fault if the mail is bogus. We just want to know that - # *something* came out of the server. - die <is_success(); - - # This ordinarily oughtn't to be able to happen, suggests a bug in RT. - # So only load these heavy modules when they're needed. - require HTML::TreeBuilder; - require HTML::FormatText; - - my $error = $r->error_as_HTML; - my $tree = HTML::TreeBuilder->new->parse($error); - $tree->eof; - - # It'll be a cold day in hell before RT sends out bounces in HTML - my $formatter = HTML::FormatText->new( leftmargin => 0, - rightmargin => 50 ); - warn $formatter->format($tree); - warn "This is $0 exiting because of an undefined server error" if ($opts{debug}); - exit EX_TEMPFAIL; +# {{{ If we've got a ticket ID, update the ticket + +else { + + # If the action is comment, add a comment. + if ($Action =~ /comment/i){ + + my $Ticket = new RT::Ticket($CurrentUser); + $Ticket->Load($TicketId); + unless ($Ticket->Id) { + MailError( To => $ErrorsTo, + Subject => "Comment not recorded", + Explanation => "Could not find a ticket with id $TicketId", + MIMEObj => $entity + ); + #Return an error message saying that Ticket "#foo" wasn't found. + } + + ($status, $msg) = $Ticket->Comment(MIMEObj=>$entity); + unless ($status) { + #Warn the sender that we couldn't actually submit the comment. + MailError( To => $ErrorsTo, + Subject => "Comment not recorded", + Explanation => $msg, + MIMEObj => $entity + ); + } + } + + # If the message is correspondence, add it to the ticket + elsif ($Action =~ /correspond/i) { + my $Ticket = RT::Ticket->new($CurrentUser); + $Ticket->Load($TicketId); + + #TODO: Check for error conditions + ($status, $msg) = $Ticket->Correspond(MIMEObj => $entity); + unless ($status) { + + #Return mail to the sender with an error + MailError( To => $ErrorsTo, + Subject => "Correspondence not recorded", + Explanation => $msg, + MIMEObj => $entity + ); + } + } + + else { + #Return mail to the sender with an error + MailError( To => $ErrorsTo, + Subject => "RT Configuration error", + Explanation => "'$Action' not a recognized action.". + " Your RT administrator has misconfigured ". + "the mail aliases which invoke RT" , + MIMEObj => $entity + ); + + $RT::Logger->crit("$Action type unknown for $MessageId"); + + } + } +# }}} -=head1 SYNOPSIS - - rt-mailgate --help : this text - -Usual invocation (from MTA): - - rt-mailgate --action (correspond|comment) --queue queuename - --url http://your.rt.server/ - [ --extension (queue|action|ticket) - -See C for more. - -=head1 OPTIONS - -=over 3 - -=item C<--action> - -Specifies whether this is a correspondence or comment address. - -=item C<--queue> - -Reflects which queue this address handles. - -=item C<--url> - -The location of the web server for your RT instance. - - -=item C<--extension> OPTIONAL - -Some MTAs will route mail sent to user-foo@host or user+foo@host to user@host -and present "foo" in the environment variable $EXTENSION. By specifying -the value "queue" for this parameter, the queue this message should be -submitted to will be set to the value of $EXTENSION. By specifying -"ticket", $EXTENSION will be interpreted as the id of the ticket this message -is related to. "action" will allow the user to specify either "comment" or -"correspond" in the address extension. - - -=head1 DESCRIPTION - -The RT mail gateway is the primary mechanism for communicating with RT -via email. This program simply directs the email to the RT web server, -which handles filing correspondence and sending out any required mail. -It is designed to be run as part of the mail delivery process, either -called directly by the MTA or C, or in a F<.forward> or -equivalent. - -=head1 SETUP - -Much of the set up of the mail gateway depends on your MTA and mail -routing configuration. However, you will need first of all to create an -RT user for the mail gateway and assign it a password; this helps to -ensure that mail coming into the web server did originate from the -gateway. - -Next, you need to route mail to C for the queues you're -monitoring. For instance, if you're using F and you have a -"bugs" queue, you will want something like this: - - bugs: "|/opt/rt3/bin/rt-mailgate --queue bugs --action correspond - --url http://rt.mycorp.com/" - - bugs-comment: "|/opt/rt3/bin/rt-mailgate --queue bugs --action comment - --url http://rt.mycorp.com/" - -Note that you don't have to run your RT server on your mail server, as -the mail gateway will happily relay to a different machine. - -=head1 CUSTOMIZATION - -By default, the mail gateway will accept mail from anyone. However, -there are situations in which you will want to authenticate users -before allowing them to communicate with the system. You can do this -via a plug-in mechanism in the RT configuration. - -You can set the array C<@RT::MailPlugins> to be a list of plugins. The -default plugin, if this is not given, is C - that is, -authentication of the person is done based on the C header of the -email. If you have additional filters or authentication mechanisms, you -can list them here and they will be called in order: - - @RT::MailPlugins = ( - "Filter::SpamAssassin", - "Auth::LDAP", - # ... - ); - -See the documentation for any additional plugins you have. - -You may also put Perl subroutines into the C<@RT::MailPlugins> array, if -they behave as described below. - -=head1 WRITING PLUGINS - -What's actually going on in the above is that C<@RT::MailPlugins> is a -list of Perl modules; RT prepends C to the name, -to form a package name, and then C's this module. The module is -expected to provide a C subroutine, which takes a hash of -several parameters: - -=over 4 - -=item Message - -A C object representing the email -=item CurrentUser - -An C object - -=item AuthStat - -The authentication level returned from the previous plugin. - -=item Ticket [OPTIONAL] - -The ticket under discussion - -=item Queue [OPTIONAL] - -If we don't already have a ticket id, we need to know which queue we're talking about +$RT::Handle->Disconnect(); -=item Action -The action being performed. At the moment, it's one of "comment" or "correspond" +# Everything below this line is a helper sub. most of them will eventually +# move to Interface::Email -=back 4 +#When we call die, trap it and log->crit with the value of the die. +$SIG{__DIE__} = sub { + unless ($^S || !defined $^S ) { + $RT::Logger->crit("$_[0]"); + MailError( To => $ErrorsTo, + Bcc => $RT::OwnerEmail, + Subject => "RT Critical error. Message not recorded!", + Explanation => "$_[0]", + MIMEObj => $entity + ); + exit(-1); + } + else { + #Get out of here if we're in an eval + die $_[0]; + } +}; -It returns two values, the new C object, and the new -authentication level. The authentication level can be zero, not allowed -to communicate with RT at all, (a "permission denied" error is mailed to -the correspondent) or one, which is the normal mode of operation. -Additionally, if C<-1> is returned, then the processing of the plug-ins -stops immediately and the message is ignored. -=cut +1;