This is the mail archive of the mailing list for the GNATS project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

MIME mail filter for GNATS

This is a followup to the little Perl snippet I posted a couple of months 
ago to translate quoted printables (those ugly =F9, =E8 and so on which 
appear in messages that use international character sets.) The script I 
posted had several grave shortcomings and bugs. For instance, it transpired 
that it was the script itself which broke recognition of PR numbers in 
Subject lines with international characters, resulting in the creation of a 
new PR each time a reply to a PR with such a Subject line was received.

After spending some time studying the relevant RFCs (especially 822 and 
2047), I have now come up with a much more watertight and robust script. I 
have done quite a bit of testing, and it seems to work very well. PR number 
recognition now seems to work exactly as it should.

Warning: Using this filter causes PRs to be stored in the Gnats database in 
a decoded format which might not be supported properly by all UNIXes. 
Outgoing mail from GNATS will also be unencoded, possibly resulting in 
problems when mail is transferred over the Internet. Some mail clients may 
also have problems with it. In short: your mileage may vary. Anyone wanna 
start looking into proper internationalization of Gnats itself, allowing us 
to avoid kludges such as this script?

Script attached below. It will also be posted to The Perl MIME tools module is required, 
you can get it from

In order to use the script, set up the mail alias which receives bug 
reports to pipe messages through this script before it is piped into 
queue-pr. Like this:

| /path-to-script/ | /usr/local/libexec/gnats/queue-pr -q

# Script to translate quoted-printables in MIME-encoded mail messages
# Fully decodes header fields according to RFC2047
# Merges multi-line header fields into single lines

undef $/; # We want to treat everything read from STDIN as one line
$input = <>;
($headers, $body) = split (/\n\n/, $input, 2);

# Process the headers:
$headers =~ s/\?=\s\n/\?=\n/g; # Lines ending with an encoded-word
                                # have an extra space at the end. Remove it.
$headers =~ s/\n[ |\t]//g; # Merge multi-line headers into a single line.
$transheaders = '';

foreach $line (split(/\n/, $headers))
   while ($line =~ m/=\?[^?]+\?(.)\?([^?]*)\?=/)
     $encoding   = $1;
     $txt        = $2;
     $str_before = $`;
     $str_after  = $';

# Base64
     if ($encoding =~ /b/i)
       require MIME::Base64;
       $txt = decode_base64($txt);

# QP
     elsif ($encoding =~ /q/i)
       require MIME::QuotedPrint;
       $txt = decode_qp($txt);

     $line = $str_before . $txt . $str_after;
   # The decode above does not do underline-to-space translation:
   $line =~ tr/_/ /;
   $transheaders .= $line . "\n";

# Process the body:
$transbody = MIME::QuotedPrint::decode($body);

# Output the combined results. We got a free \n from
# the transheaders concatenation.
print $transheaders . "\n" . $transbody;
# Script ends here.

Yngve Svendsen
IS Engineer
Clustra AS, Trondheim, Norway

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]