Bugzilla and SMTP Authentication

The last few months I’ve been helping out in an effort to upgrade Shotokan Karate of America‘s membership management system. They’re rewriting the system from scratch, as the old system has grown to be unmaintainable. The code for the new system was about 85% complete when I signed up, so I offered to start testing the system while the sole developer working on the project finished up the code. There were no unit tests, so I figured that would be a good place to start. This naturally brought up the issue of how we would communicate problems and fixes, so I offered to install Bugzilla on my Linux box and suggested we use that.

It wasn’t until later that I found out that Bugzilla and SMTP Authentication do not get along (although I see that there is a fix in the pipeline). Bugzilla supports SMTP, but without authentication. It also supports sendmail, but my ISP isn’t too keen on people running their own mail servers, making the use of sendmail difficult. Since my ISP has a SMTP server for me to use, I figured I would use that. But, authentication is required on that server.

I toyed around with some ideas in an attempt to keep me from hacking the Bugzilla code. One involved parsing the data/mailer.testfile file (where mail is sent when the “testfile” mail option is set) for the To address and the email body, and sending the email via a custom script. But, that brought up some interesting race conditions if multiple users made a change that triggered an email at approximately the same time. We would need to periodically read that file to send the email, wiping out the contents afterward to avoid resending the same messages. If the timing was right, we could potentially wipe out a message that was never sent.

I took a look at the Bugzilla code, and found the module that was responsible for sending the email. The code was clean, and pretty easy to follow, even though I know very little perl. I found the point in the module where it calls out to the Mail Transport Agent to deliver the mail. I figured I could easily insert a call to a script to deliver the mail, using SMTP Authentication. That is exactly what I did. I modified BugMail.pm to include the “system” call below.

sub MessageToMTA {
    ....

    # --- Begin New Lines ---
    system('send-bugzilla-email.rb', $msg);
    # --- End New Lines ---

    $mailer->open($headers->header_hashref);
    print $mailer $body;
    $mailer->close;
}

$msg is a variable that contains the SMTP message to send. That message includes the To address, the subject of the email, and the body of the email. In other words, everything we would need to send the mail ourselves. I then wrote a ruby script to parse the message, and send the email. Here’s the script.

#!/usr/bin/ruby

require 'net/smtp'

from_address = 'username@my_isp.com'

# Break the message up into an array of strings
message_array = ARGV.first.split("\n")

# Pull out the To address and the subject
message_array[1] =~ /^To: (.*)$/
to_address = $1

message_array[2] =~ /^Subject: (.*)$/
subject = $1

# Delete some crap that we do not care about
4.times { |i| message_array.delete_at(0) }

# Combine what remains back into the body
body = message_array.join("\n")

message =  "From: Bugzilla <#{from_address}>\n"
message << "To: #{to_address}\n"
message << "Subject: #{subject}\n"
message << body

# Send the email
Net::SMTP.start('smtp.my_isp.com', 25, 'my_isp.com', 'username', 'password', :login) do |smtp|
  smtp.send_message message, from_address, to_address
end

File.open('/var/log/bugzilla_email.log', 'a+') do |file|
  file.puts("\n-----------------------------------------\n")
  file.puts(message)
end

Although not ideal, it does the job. And, if I do say so myself, it works quite well. I’ll be looking forward to upgrading to the new version of Bugzilla once it supports SMTP authentication. In the meantime, this will keep things rolling.