ValidateEmail

From Request Tracker Wiki
Jump to navigation Jump to search

This patch applies to 3.6.3, but should work on other versions without much (if any) modification.

Problem

Users mistype addresses in the Requestor, CC, and AdminCC address fields, causing the notifications to fail and preventing that person from seeing the ticket.

As far as I could tell, RT does not validate addresses typed into those fields, and offers no hooks for administrators to create their own validation.

Solution

I created a Mason component to perform the email validation, the same way custom fields are validated. First, emails without '@' signs are invalid in my environment, so I reject them. Second, I connect to the local SMTP server and submit the email address as a recipient. If the recipient is accepted, then I consider it a valid address. (No actual message is sent during the validation.)

Details

First, create /opt/rt3/local/html/Elements/ValidateEmails. You should customize the first part of this file, where the SMTP server is specified.

<%INIT>
sub check_address
{
        my $address = shift;

        my $REQUIRE_AT_SIGN = 1;
        my $SMTP_HOST = 'smtp.messiah.edu';
        my $SMTP_FROM = 'nobody@messiah.edu';

        return 0 if ($REQUIRE_AT_SIGN && $address !~ /\@/);

        # check address against specified SMTP server
        use Net::SMTP;
        my $smtp = Net::SMTP->new($SMTP_HOST);

        $smtp->mail($SMTP_FROM);
        my $valid = $smtp->to($address);
        $smtp->quit;
        return $valid;
}

my $valid = 1;
foreach my $field (@{$EmailFields})
{
        my $value = $ARGSRef->{$field};
        foreach my $address (split /,/, $value)
        {
                # trim whitespace
                $address =~ s/^\s+//;
                $address =~ s/\s+$//;

                next if $address eq "";
                unless (check_address($address))
                {
                        $valid = 0;
                        $m->notes("InvalidField-$field"
                                => "Bad address ($address)");
                }
        }
}
$m->notes('ValidEmails', $valid);
return $valid;
</%INIT>
<%ARGS>
$EmailFields => [ "Requestors", "Cc", "AdminCc" ]
$ARGSRef
</%ARGS>

Next, to configure the Create Ticket page to require validation, copy /opt/rt3/share/html/Ticket/Create.html to /opt/rt3/local/html/Ticket/Create.html and make the following modifications:

--- Create.html.orig    2007-02-20 10:19:32.000000000 -0500
+++ Create.html 2007-02-20 10:32:04.000000000 -0500
@@ -250,6 +250,10 @@
     CustomFields => $CFs,
     ARGSRef => \%ARGS
 );
+my $ValidEmails = $m->comp(
+    '/Elements/ValidateEmails',
+    ARGSRef => \%ARGS
+);

 # if no due date has been set explicitly, then use the
 # queue's default if it exists
@@ -297,7 +301,7 @@
 # }}}

 if ((!exists $ARGS{'AddMoreAttach'}) and ($ARGS{'id'} eq 'new')) { # new ticket?
-    if ($ValidCFs) {
+    if ($ValidCFs and $ValidEmails) {
         $m->comp('Display.html', %ARGS);
         $RT::Logger->crit("After display call; error is $@");
         $m->abort();
@@ -308,6 +312,11 @@
             my $msg = $m->notes('InvalidField-' . $CF->Id) or next;
             push @results, $CF->Name . ': ' . $msg;
         }
+       foreach my $field ("Requestors", "Cc", "AdminCc")
+       {
+           my $msg = $m->notes("InvalidField-$field") or next;
+           push @results, $field . ": " . $msg;
+       }
     }
 }

Finally, restart Apache and try it out. The Create Ticket page should now reject any email addresses that your SMTP server would reject.

TODO - there are other places where email addresses can be entered. They should be validated too.

Email me at jlong@messiah.edu if you have questions or comments on this page.