Index: lib/Mail/SpamAssassin/Plugin/FreeMail.pm
===================================================================
--- lib/Mail/SpamAssassin/Plugin/FreeMail.pm	(revision 1790797)
+++ lib/Mail/SpamAssassin/Plugin/FreeMail.pm	(working copy)
@@ -348,7 +348,8 @@
             s#<?(?<!mailto:)$self->{email_regex}(?:>|\s{1,10}(?!(?:fa(?:x|csi)|tel|phone|e?-?mail))[a-z]{2,11}:)# #gi;
             while (/$self->{email_regex}/g) {
                 my $email = lc($1);
-                push(@body_emails, $email) unless defined $seen{$email};
+                utf8::encode($email) if utf8::is_utf8($email); # chars to UTF-8
+                push(@body_emails, $email) unless $seen{$email};
                 $seen{$email} = 1;
                 last BODY if scalar @body_emails >= 40; # sanity
             }
@@ -355,7 +356,7 @@
         }
         my $count_all = 0;
         my $count_fm = 0;
-        foreach my $email (@body_emails) {
+        foreach my $email (@body_emails) {  # as UTF-8 octets
             if (++$count_all == $pms->{main}->{conf}->{freemail_max_body_emails}) {
                 if ($pms->{main}->{conf}->{freemail_skip_when_over_max}) {
                     $pms->{freemail_skip_body} = 1;
Index: lib/Mail/SpamAssassin/Plugin/TextCat.pm
===================================================================
--- lib/Mail/SpamAssassin/Plugin/TextCat.pm	(revision 1790797)
+++ lib/Mail/SpamAssassin/Plugin/TextCat.pm	(working copy)
@@ -51,7 +51,7 @@
 use Mail::SpamAssassin::Logger;
 use strict;
 use warnings;
-use bytes;
+# use bytes;
 use re 'taint';
 
 use vars qw(@ISA);
@@ -473,14 +473,22 @@
   my %ngram;
   my @sorted;
 
+  # Note that $$inputptr may or may not be in perl characters (utf8 flag set)
+  my $is_unicode = utf8::is_utf8($$inputptr);
+
   # my $non_word_characters = qr/[0-9\s]/;
-  for my $word (split(/[0-9\s]+/, ${$_[0]}))
+  for my $word (split(/[0-9\s]+/, $$inputptr))
   {
-    # Bug 6229: Current TextCat database only works well with
-    # lowercase input, lets work around it until it's properly
-    # generated and/or locale issues are resolved..
-    $word =~ tr/A-Z\xc0-\xd6\xd8-\xde/a-z\xe0-\xf6\xf8-\xfe/
-        if $word =~ /[A-Z]/ && $word =~ /[a-zA-Z\xc0-\xd6\xd8-\xde\xe0-\xf6\xf8-\xfe]{4}/;
+    # Bug 6229: Current TextCat database only works well with lowercase input
+    if ($is_unicode) {
+      # Unicode rules are used for the case change
+      $word = lc $word  if $word =~ /\w{4}/;
+      utf8::encode($word);  # encode Unicode characters to UTF-8 octets
+    } elsif ($word =~ /[A-Z]/ &&
+             $word =~ /[a-zA-Z\xc0-\xd6\xd8-\xde\xe0-\xf6\xf8-\xfe]{4}/) {
+      # assume ISO 8859-1 / Windows-1252
+      $word =~ tr/A-Z\xc0-\xd6\xd8-\xde/a-z\xe0-\xf6\xf8-\xfe/;
+    }
     $word = "\000" . $word . "\000";
     my $len = length($word);
     my $flen = $len;
Index: lib/Mail/SpamAssassin/Plugin/VBounce.pm
===================================================================
--- lib/Mail/SpamAssassin/Plugin/VBounce.pm	(revision 1790797)
+++ lib/Mail/SpamAssassin/Plugin/VBounce.pm	(working copy)
@@ -162,6 +162,7 @@
 sub _relay_is_in_list {
   my ($self, $list, $pms, $relay) = @_;
   $relay = lc $relay;
+  utf8::encode($relay) if utf8::is_utf8($relay);  # encode chars to UTF-8
 
   if (defined $list->{$relay}) { return 1; }
 
