summaryrefslogtreecommitdiff
path: root/rt/bin/rt-mailgate
diff options
context:
space:
mode:
Diffstat (limited to 'rt/bin/rt-mailgate')
-rwxr-xr-xrt/bin/rt-mailgate367
1 files changed, 367 insertions, 0 deletions
diff --git a/rt/bin/rt-mailgate b/rt/bin/rt-mailgate
new file mode 100755
index 000000000..e6f0d95c5
--- /dev/null
+++ b/rt/bin/rt-mailgate
@@ -0,0 +1,367 @@
+#!!!PERL!! -w
+
+# $Header: /home/cvs/cvsroot/freeside/rt/bin/rt-mailgate,v 1.1 2002-08-12 06:17:07 ivan Exp $
+# (c) 1996-2001 Jesse Vincent <jesse@fsck.com>
+# This software is redistributable under the terms of the GNU GPL
+
+
+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();
+
+#Get someone to send runtime errors to;
+my $ErrorsTo = ParseErrorsToAddressFromHead($head);
+
+#Get us a current user object.
+my $CurrentUser = GetCurrentUser($head, $entity, $ErrorsTo);
+
+# 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
+
+unless ($CurrentUser->Id) {
+ exit(1);
+}
+
+my $MessageId = $head->get('Message-Id') ||
+ "<no-message-id-".time.rand(2000)."\@.$RT::Organization>";
+
+#Pull apart the subject line
+$Subject = $head->get('Subject') || "[no subject]";
+chomp $Subject;
+
+# 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 ) {
+
+ MailError(To => $RT::OwnerEmail,
+ Subject => "RT Bounce: $Subject",
+ Explanation => "RT couldn't find the queue: $Queue",
+ MIMEObj => $entity);
+
+}
+
+# {{{ Lets check for mail loops of various sorts.
+
+my $IsAutoGenerated = CheckForAutoGenerated($head);
+
+my $IsSuspiciousSender = CheckForSuspiciousSender($head);
+
+my $IsALoop = CheckForLoops($head);
+
+
+#If the message is autogenerated, we need to know, so we can not
+# send mail to the sender
+if ($IsSuspiciousSender || $IsAutoGenerated || $IsALoop) {
+ $SquelchReplies = 1;
+
+ $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
+
+}
+
+
+# {{{ 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);
+ }
+}
+
+# }}}
+
+
+ #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')
+ }
+
+
+if ($SquelchReplies) {
+ ## TODO: This is a hack. It should be some other way to
+ ## indicate that the transaction should be "silent".
+
+ my ($Sender, $junk) = ParseSenderAddressFromHead($head);
+ $head->add('RT-Squelch-Replies-To', $Sender);
+}
+
+# }}}
+
+
+# {{{ If we require that the sender be found in an external DB and they're not
+# forward this message to RTOwner
+
+
+
+if ($RT::LookupSenderInExternalDatabase &&
+ $RT::SenderMustExistInExternalDatabase ) {
+
+ MailError(To => $RT::OwnerEmail,
+ Subject => "RT Bounce: $Subject",
+ Explanation => "RT couldn't find requestor via its external database lookup",
+ MIMEObj => $entity);
+
+}
+
+# }}}
+
+# {{{ 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);
+ }
+}
+
+# }}}
+
+# {{{ 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");
+
+ }
+
+}
+
+# }}}
+
+$RT::Handle->Disconnect();
+
+
+# Everything below this line is a helper sub. most of them will eventually
+# move to Interface::Email
+
+#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];
+ }
+};
+
+
+
+1;