[rt-devel] More conservative charsets

Florian Weimer fw at deneb.enyo.de
Tue Nov 18 16:05:40 EST 2003


The patch below simplifies charsets of text/plain parts in outgoing
email.

Believe it or not, we have received numerous reports that umlauts are
broken.  In our constituency, MUAs without UTF-8 support are still far
too common.  Therefore, our RT instance tries to recode attachments
using a preferred charset list and uses the first possible charset.

What do you think about this approach?  (The actual patch should
probably go into MIME::Tools, but that's just a detail.)

* modified files

--- orig/lib/RT/Action/SendEmail.pm
+++ mod/lib/RT/Action/SendEmail.pm
@@ -33,6 +33,7 @@
 use MIME::Words qw(encode_mimeword);
 
 use RT::EmailParser;
+use Encode;
 
 =head1 NAME
 
@@ -257,6 +258,9 @@
         $RT::Logger->info($msgid.  " No recipients found. Not sending.\n");
         return (1);
     }
+    
+    # Canonify charsets.
+    &reencode ($MIMEObj);
 
     # PseudoTo	(fake to headers) shouldn't get matched for message recipients.
     # If we don't have any 'To' header, drop in the pseudo-to header.
@@ -676,6 +680,63 @@
 
 # }}}
 
+my @Charset_List = ("us-ascii", "iso-8859-1", "iso-8859-15", "windows-1252");
+
+sub reencode ($) {
+    my $entity = shift;
+
+    if ($entity->is_multipart) {
+	for my $part ($entity->parts) {
+	    &reencode ($part);
+	}
+    } else {
+	my $body = $entity->bodyhandle;
+
+	my $content_type = new Mail::Field 
+	    ('content-type', $entity->head->get ('content-type'));
+
+
+	unless ($content_type->type =~ m,^text/,i) {
+	    return;
+	}
+
+	my $decoded;
+	my $source_charset = $entity->head->mime_attr('content-type.charset');
+	unless ($source_charset) {
+	    $source_charset = 'utf-8';
+	}
+	
+	eval {
+	    $decoded = decode($source_charset, $body->as_string, Encode::FB_CROAK);
+	};
+	if ($@) {
+	    # Can't decode, don't touch it.
+	    return;
+	}
+		
+      CHARSET:
+	for my $charset (@Charset_List) {
+	    my $octets;
+	    eval {
+		$octets = encode($charset, $decoded, Encode::FB_CROAK);
+	    };
+	    if ($@) {
+		next CHARSET;
+	    }
+
+	    my $IO = $body->open ("w");
+	    $IO->print ($octets);
+	    $IO->close;
+
+	    $content_type->param('charset', $charset);
+	    $entity->head->replace('content-type', $content_type->stringify);
+
+	    last CHARSET;
+	}
+    }
+}
+
+
 eval "require RT::Action::SendEmail_Vendor";
 die $@ if ($@ && $@ !~ qr{^Can't locate RT/Action/SendEmail_Vendor.pm});
 eval "require RT::Action::SendEmail_Local";






More information about the Rt-devel mailing list