Use multipart/alternative sub-attachment for HTML and text body
authorJamie Cameron <jcameron@webmin.com>
Thu, 20 Aug 2009 06:35:22 +0000 (23:35 -0700)
committerJamie Cameron <jcameron@webmin.com>
Thu, 20 Aug 2009 06:35:22 +0000 (23:35 -0700)
mailboxes/boxes-lib.pl
mailboxes/folders-lib.pl
mailboxes/send_mail.cgi

index 553273a..5f16aef 100755 (executable)
@@ -1087,6 +1087,44 @@ if (!close(MAIL)) {
 return $lnum;
 }
 
+# unparse_mail(&attachments, eol, boundary)
+# Convert an array of attachments into MIME format, and return them as an
+# array of lines.
+sub unparse_mail
+{
+local ($attach, $eol, $bound) = @_;
+local @rv;
+foreach my $a (@$attach) {
+       push(@rv, $eol);
+       push(@rv, "--".$bound.$eol);
+       local $enc;
+       foreach my $h (@{$a->{'headers'}}) {
+               push(@rv, $h->[0].": ".$h->[1].$eol);
+               $enc = $h->[1]
+                       if (lc($h->[0]) eq 'content-transfer-encoding');
+               }
+       push(@rv, $eol);
+       if (lc($enc) eq 'base64') {
+               local $enc = &encode_base64($a->{'data'});
+               $enc =~ s/\r//g;
+               foreach my $l (split(/\n/, $enc)) {
+                       push(@rv, $l.$eol);
+                       }
+               }
+       else {
+               $a->{'data'} =~ s/\r//g;
+               $a->{'data'} =~ s/\n\.\n/\n\. \n/g;
+               foreach my $l (split(/\n/, $a->{'data'})) {
+                       push(@rv, $l.$eol);
+                       }
+               }
+       }
+push(@rv, $eol);
+push(@rv, "--".$bound."--".$eol);
+push(@rv, $eol);
+return @rv;
+}
+
 # mail_size(&mail, [textonly])
 # Returns the size of an email message in bytes
 sub mail_size
index ef13d93..455e4ea 100755 (executable)
@@ -3094,7 +3094,7 @@ for(my $i=0; $i<scalar(@rv); $i++) {
                                $rv[$i] = 1;
                                }
                        }
-               else {
+               elsif ($a->{'type'} !~ /^multipart\/(mixed|alternative)/) {
                        # Non-text .. assume this means we have an attachment
                        $rv[$i] = 1;
                        }
index 288497e..dec9892 100755 (executable)
@@ -97,17 +97,19 @@ if ($in{'body'} =~ /\S/) {
        $bodyattach = $attach[0];
 
        if ($in{'html_edit'}) {
-               # Add the plain-text body
-               local $mt = "text/plain";
+               # Create an attachment which contains both the HTML and plain
+               # bodies as alternatives
+               local @alts = ( $attach[0] );
+               local $mt = "text/plain; charset=$charset";
                if ($plainbody =~ /[\177-\377]/) {
-                       unshift(@attach,
+                       push(@alts,
                          { 'headers' => [ [ 'Content-Type', $mt ],
                                           [ 'Content-Transfer-Encoding',
                                             'quoted-printable' ] ],
                            'data' => quoted_encode($plainbody) });
                        }
                else {
-                       unshift(@attach,
+                       push(@alts,
                          { 'headers' => [ [ 'Content-Type', $mt ],
                                           [ 'Content-Transfer-Encoding',
                                             '7bit' ] ],
@@ -116,8 +118,15 @@ if ($in{'body'} =~ /\S/) {
 
                # Set content type to multipart/alternative, to tell mail
                # clients about the optional body
-               push(@{$mail->{'headers'}}, [ 'Content-Type',
-                                             'multipart/alternative' ]);
+               local $bound = "altsbound".time();
+               $attach[0] = {
+                       'headers' => [ [ 'Content-Type',
+                                        'multipart/alternative; '.
+                                        'boundary="'.$bound.'"' ],
+                                      [ 'Content-Transfer-Encoding',
+                                        '7bit' ] ],
+                       'data' => join("", &unparse_mail(\@alts, "\n", $bound))
+                       };
                }
        }
 $attachsize = 0;