RT-Extension-Conservancy/lib/RT/Interface/Email/OneTicketPerRequestor.pm

112 lines
3.5 KiB
Perl

package RT::Interface::Email::OneTicketPerRequestor;
use strict;
use warnings;
use Role::Basic 'with';
with 'RT::Interface::Email::Role';
use Email::Address;
use Encode;
use RT::Interface::Email ();
use RT::Plugin;
use RT::Tickets;
use YAML::Tiny;
my %QUEUES = ();
my $plugin_self = RT::Plugin->new(name => "RT-Extension-Conservancy");
foreach my $confdir ($plugin_self->Path("etc"), $RT::LocalEtcPath, $RT::EtcPath) {
next unless (defined($confdir) && $confdir);
my $conf_path = "$confdir/OneTicketPerRequestor.yml";
if (-r $conf_path) {
%QUEUES = %{YAML::Tiny->read($conf_path)->[0]};
last if (%QUEUES);
}
}
# Compile the user's configuration into arguments for RT::Tickets->OrderBy.
while (my ($key, $sort_orders) = each %QUEUES) {
if (!ref($sort_orders)) {
$sort_orders = [($sort_orders ? $sort_orders : ())];
}
if (!@$sort_orders) {
push(@$sort_orders, "Created DESC");
}
$QUEUES{$key} = [map {
my ($field, $order) = split;
$order = uc($order || "ASC");
[FIELD => $field, ORDER => $order];
} @$sort_orders];
}
sub ReadHeader {
my $headers = shift;
my $header_name = shift;
return Encode::decode("UTF-8", $headers->get($header_name) || "");
}
sub BeforeDecrypt {
$RT::Logger->debug("Entered OneTicketPerRequestor BeforeDecrypt");
my %args = (
Message => undef,
RawMessage => undef,
Actions => undef,
Queue => undef,
@_
);
my $queue_name = $args{Queue}->Name;
my $sort_orders = $QUEUES{$queue_name};
if (!defined($sort_orders)) {
$RT::Logger->debug("OTPR stopping: Not configured for $queue_name");
return;
}
elsif (RT::Interface::Email::ExtractTicketId($args{Message})) {
$RT::Logger->debug("OTPR stopping: Message already has ticket ID");
return;
}
my $headers = $args{Message}->head();
my @from_addrs = Email::Address->parse(ReadHeader($headers, "From"));
my $from_address;
foreach my $address (@from_addrs) {
$from_address = $address->address;
last if $from_address;
}
unless (defined($from_address) && $from_address) {
$RT::Logger->debug("OTPR stopping: Message has no From address (?!)");
return;
}
my $dest_ticket = eval {
my $ticket_search = RT::Tickets->new($RT::SystemUser);
$ticket_search->LimitQueue(
OPERATOR => "=",
VALUE => $queue_name,
);
$ticket_search->LimitWatcher(
TYPE => "Requestor",
OPERATOR => "=",
VALUE => $from_address,
);
foreach my $sort_args (@$sort_orders) {
$ticket_search->OrderBy(@$sort_args);
}
$RT::Logger->debug("OTPR search: " . $ticket_search->BuildSelectQuery());
$ticket_search->First;
};
if ($@) {
$RT::Logger->debug("OTPR stopping: Ticket search died: $@");
return;
}
elsif (!defined($dest_ticket)) {
$RT::Logger->debug(sprintf("OTPR stopping: No ticket found from <%s> in queue %s",
$from_address, $queue_name));
return;
}
$RT::Logger->info(sprintf("OTPR: Redirecting email from <%s> to ticket #%s",
$from_address, $dest_ticket->id));
my $subject = ReadHeader($headers, "Subject");
$headers->replace("Subject", RT::Interface::Email::AddSubjectTag($subject, $dest_ticket->id));
}
1;