Sending an html mail

Top Japanese page




Overview

Send an html mail using sendmail.

Flow

  1. Load Jcode
  2. Setup properly
  3. Set mail contents
  4. Set mail header
  5. Make attachment for images
  6. Send a mail
  7. Display a completion message

A sample code

 use File::Basename;
 use Jcode;
 use MIME::Base64 qw(encode_base64);
 
 my $to_mail = 'tomail@dummy.com';
 my $from_mail = 'frommail@dummy.com';
 my $subject = 'HTML mail with images';
 my $mail_cmd = 'sendmail -t';
 
 my $image1 = "image1.jpg";
 my $image2 = "image2.jpg";
 
 my $contents = '
 <html><body>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
 <h1>This is an HTML mail.</h1>
 <center>I attach two photos. Take a look!</center><p>
 
 Photo 1
 <img src="cid:image1"><br>
 
 Pohto 2
 <img src="cid:image2"><br>
 </body>
 </html>
 ';
 
 $contents = jcode($contents)->jis;
 
 my $header;
 $header = "From: " . jcode("$from_mail")->mime_encode . "\n";
 $header .= "To: " . jcode("$to_mail")->mime_encode . "\n";
 $header .= "Subject: " . jcode($subject)->mime_encode . "\n";
 $header .= "MIME-Version: 1.0\n";
 $header .= "Content-type: multipart/related; boundary=\"boundary-here--\";type=Text/HTML;\n";
 $header .= "Content-Transfer-Encoding: 7bit\n\n";
 
 $header .= "--boundary-here--\n";
 $header .= "Content-type: Text/HTML; charset=ISO-2022-JP\n\n";
 
 my $buf;
 my $footer = "\n";;
 foreach my $im ($image1,$image2){
     my ($body, $path, $ext) = fileparse($im, '\.\w+');
     my %type = (jpg => 'JPEG',
                 gif => 'GIF',
                 png => 'PNG');
     $ext =~ s/\.//;
     $footer .= "--boundary-here--\n";
     $footer .= "Content-Disposition: attachment; filename=\"$im\"\n";
     $footer .= "Content-Type: IMAGE/$type{$ext}\n";
     $footer .= "Content-ID: $body\n";
     $footer .= "Content-Transfer-Encoding: BASE64\n\n";
     open(FILE, "< $im");
     while (read(FILE, $buf, 60*57)) {
            $footer .= encode_base64($buf);
     }
     close(FILE);
 }
 
 if (open(SMAIL, "| $mail_cmd")){
        print SMAIL $header;
        print SMAIL $contents;
        print SMAIL $footer;
        close(SMAIL);
 } else {
        &error("Cannot send the mail<br>Check $mail_cmd");
 }
 
 prnit "Content-Type: text/html\n\n";
 print "Completed to send";

Description of the code

 use File::Basename;
 use Jcode;
 use MIME::Base64 qw(encode_base64);

Load Jcode, Basename, MIME::Base64.

 my $to_mail = 'tomail@dummy.com';
 my $from_mail = 'frommail@dummy.com';
 my $subject = 'HTML mail with images';
 my $mail_cmd = 'sendmail -t';

Set mail address to be sent and from. Set the subject and mail command. Due to mail header is embedded, sendmail needs the -t optoin.

 my $image1 = "image1.jpg";
 my $image2 = "image2.jpg";

Specify image files to be attached into the mail. In this example two images will be attached. The image files usually passed form input form of an HTML page.

 my $contents = '
 <html><body>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
 <h1>This is an HTML mail.</h1>
 <center>I attach two photos. Take a look!</center><p>
 
 Photo 1
 <img src="cid:image1"><br>
 
 Pohto 2
 <img src="cid:image2"><br>
 </body>
 </html>
 ';

This is mail contents. Usually passed from a mail from of an HTML page. The src of img tag is not file name, but ID. This ID corresponds to Content-ID in the attachment.

 $contents = jcode($contents)->jis;

Convert contents to JIS. This is not necessarily to be JIS. Just need to match with header encode.

 my $header;
 $header = "From: " . jcode("$from_mail")->mime_encode . "\n";
 $header .= "To: " . jcode("$to_mail")->mime_encode . "\n";
 $header .= "Subject: " . jcode($subject)->mime_encode . "\n";

Specify the headers. In thsi example, put them into a variable. Using jcode()->mime_encode, encoding the headers. This allows to send proper Japanese code through email.

 $header .= "MIME-Version: 1.0\n";
 $header .= "Content-type: multipart/related; boundary=\"boundary-here--\";type=Text/HTML;\n";
 $header .= "Content-Transfer-Encoding: 7bit\n\n";

This is also header. Content-type is multipart/related so that attachment can be sent. The boundary part separates mail contents and attachment. The separater must start "--" followed by some letteres. In this example, the separater is "--boundary-here--".

 $header .= "--boundary-here--\n";
 $header .= "Content-type: Text/HTML; charset=ISO-2022-JP\n\n";

This part is actually included in the mail contents because this comes after the separater. Charset is treated as JIS. The header is finished by the last two new-line codes.

 my $buf;
 my $footer = "\n";;
 foreach my $im ($image1,$image2){
     my ($body, $path, $ext) = fileparse($im, '\.\w+');
     my %type = (jpg => 'JPEG',
                 gif => 'GIF',
                 png => 'PNG');
     $ext =~ s/\.//;
     $footer .= "--boundary-here--\n";
     $footer .= "Content-Disposition: attachment; filename=\"$im\"\n";
     $footer .= "Content-Type: IMAGE/$type{$ext}\n";
     $footer .= "Content-ID: $body\n";
     $footer .= "Content-Transfer-Encoding: BASE64\n\n";
     open(FILE, "< $im");
     while (read(FILE, $buf, 60*57)) {
            $footer .= encode_base64($buf);
     }
     close(FILE);
 }

Make attachment files here. The files are encoded with Base64. Since two files are attached, repeat it twice. Beofre encoding it has a separater and a header. The image is displayed when the letter specified in Content-ID: and <img src=cid"..."> match. In this example, the body name of the file is used as ID.

 read(FILE, $buf, 60*57)

When the size of the file is big, encode it with multiples of 57-byte so that end of the line aligned.

 if (open(SMAIL, "| $mail_cmd")){
        print SMAIL $header;
        print SMAIL $contents;
        print SMAIL $footer;
        close(SMAIL);
 } else {
        &error("Cannot send the mail<br>Check $mail_cmd");
 }

Send the mail here.

 prnit "Content-Type: text/html\n\n";
 print "Completed to send";

If necessary, display the completion message.