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"; eval { %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;