Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Send Email With Picture Embedded in Body of Email (SOLVED)

by roho (Chancellor)
on Sep 09, 2020 at 19:34 UTC ( #11121523=perlquestion: print w/replies, xml ) Need Help??

roho has asked for the wisdom of the Perl Monks concerning the following question:

The code below sends an email with a JPG file as an attachment using the Outlook web email server. I need to send the email with the JPG picture embedded in the body of the email as well.

I must use module Net::SMTPS because it has the options required to connect to the Outlook web email server. I have not found another module that allows me to connect to the Outlook web email server.

I know there are a boatload of email modules that are higher level than Net::SMTPS (and I have tried many of them so far), but like I said, Net::SMTPS is the only module I have found with the options to allow me to connect to the Outlook web email server.

To run the code below, replace "tester@hotmail.com" with a valid Outlook web email userid, replace "foo" with a valid email password, and replace "test.jpg" with an existing JPG file.

Can anyone provide the additional code required to embed the JPG picture in the body of the email using Net::SMTPS? Thanks in advance for your help.

#!/usr/bin/perl use strict; use warnings; use Net::SMTPS; use MIME::Base64 qw( encode_base64 ); my $from = 'Tester <tester@hotmail.com>'; my $to = shift || 'tester@hotmail.com'; my $pic = shift || 'test.jpg'; # Email connection. my $username = 'tester@hotmail.com'; my $password = 'foo'; my $smtp = Net::SMTPS->new('outlook.com', Port => 587, doSSL => 'star +ttls', SSL_version=>'TLSv1'); $smtp->auth ( $username, $password ) or die "Could not authenticate wi +th Outlook.\n"; print "Sending mail\n"; # Email header. my $boundary = 'frontier'; $smtp->mail($from); $smtp->recipient($to, { SkipBad => 1 }); $smtp->data(); $smtp->datasend("To: $to\n"); $smtp->datasend("From: $from\n"); $smtp->datasend("Subject: Perl Test Email\n"); $smtp->datasend("MIME-Version: 1.0\n"); $smtp->datasend("Content-type: multipart/mixed;\n\tboundary=\"$boundar +y\"\n"); $smtp->datasend("\n"); # Email body. $smtp->datasend("--$boundary\n"); $smtp->datasend("Content-type: text/plain\n"); $smtp->datasend("Content-Disposition: quoted-printable\n"); $smtp->datasend("Testing Perl email.\n"); # Email attachment. $smtp->datasend("--$boundary\n"); $smtp->datasend("Content-Type: image/jpeg; name=\"$pic\"\n"); $smtp->datasend("Content-Transfer-Encoding: base64\n"); $smtp->datasend("Content-Disposition: attachment; filename=\"$pic\"\n" +); $smtp->datasend("\n"); open(my $fh2, '<', $pic) || die("Could not open Jpg file!"); binmode($fh2); local $/=undef; while (read($fh2, my $chunk, 72*57)) { my $buf = &encode_base64( $chunk ); $smtp->datasend($buf); } close($fh2); $smtp->datasend("\n"); $smtp->datasend("--$boundary--\n"); $smtp->dataend(); $smtp->quit; print "Mail sent\n"; exit;

"It's not how hard you work, it's how much you get done."

Replies are listed 'Best First'.
Re: Send Email With Picture Embedded in Body of Email
by pryrt (Monsignor) on Sep 09, 2020 at 19:43 UTC

    Can anyone provide the additional code required to embed the JPG picture in the body of the email using Net::SMTPS? Thanks in advance for your help.

    # Email body. $smtp->datasend("--$boundary\n"); $smtp->datasend("Content-type: text/plain\n");

    You have a conflict between your code and your problem description. Your problem description says that you want to embed an image, but your code shows that you are using plaintext. You cannot "embed an image" in plaintext. When Outlook sends an email with embedded images, it is either in rich text format, or in HTML. (I can see this when I compose a message in my Office 2016 Outlook client: the "Format Text" menu will show either HTML Text, Plain Text, or Rich Text. If you have an embedded image and select Plain Text, the embedded image goes away, because images are not plain text.)

    So instead of doing a Content-type: text/plain, use the right header for rich text or html, and format the data in that section of the email as either rich text or html. And sorry, I don't know how to set an HTML img src to point to an attachment in your email: if you send yourself a rich text email and an HTML text email, both with embedded images, from Outlook to someplace that can read the actual source of the email, then you can see how exactly the rich text or HTML are structured to link to the image.

      Sorry for the confusion. The plain text section is there as a placeholder. I need to know how to change the pain text section to embed a picture instead of displaying text. I have been unable to find a working example of the code required to do this, and that is what I am asking the Monastery for.

      "It's not how hard you work, it's how much you get done."

Re: Send Email With Picture Embedded in Body of Email
by LanX (Sage) on Sep 09, 2020 at 20:20 UTC
      Thanks LanX. There's lots of good info there, but unfortunately I am restricted to using Net::SMTPS because that is the only module I have found that allows me to connect to the Outlook web mail server.

      "It's not how hard you work, it's how much you get done."

        Have you had any luck doing what was suggested by pryrt in the second paragraph here: seeing what Outlook does with an e-mail having an embedded RTF/HTML image and doing likewise?


        Give a man a fish:  <%-{-{-{-<

Re: Send Email With Picture Embedded in Body of Email
by jcb (Parson) on Sep 10, 2020 at 02:53 UTC

    Instead of building a MIME message "by hand", have a look at MIME::Tools. You will still need to find how to reference an attached image from an HTML message part, however.

Re:Send Email With Picture Embedded in Body of Email
by roho (Chancellor) on Sep 10, 2020 at 00:01 UTC
    Here is my attempt to add a section to embed the picture in the body of the email. Unfortunately, it does not work.
    The email arrives with the raw base64 data displayed.
    ############################################################## # Embed JPG image in email body. # Note: This does NOT work. ############################################################## $smtp->datasend("MIME-Version: 1.0\n"); $smtp->datasend("Content-Type: text/html; boundary=$boundary\n"); $smtp->datasend("Content-Transfer-Encoding: base64\n"); $smtp->datasend("Content-Disposition: inline\n"); $smtp->datasend("\n"); $smtp->datasend("<body><img alt=\"My Picture\" img src=\""); open(my $fh2, '<', $pic) || die("Could not open Jpg file!"); binmode($fh2); local $/=undef; while (read($fh2, my $chunk, 72*57)) { my $buf = &encode_base64( $chunk ); $smtp->datasend($buf); } close($fh2); $smtp->datasend("\"></body>");

    "It's not how hard you work, it's how much you get done."

      Here is my attempt to add a section to embed the picture in the body of the email. Unfortunately, it does not work. The email arrives with the raw base64 data displayed.

      ############################################################## # Embed JPG image in email body. # Note: This does NOT work. ############################################################## $smtp->datasend("MIME-Version: 1.0\n"); $smtp->datasend("Content-Type: text/html; boundary=$boundary\n"); $smtp->datasend("Content-Transfer-Encoding: base64\n"); $smtp->datasend("Content-Disposition: inline\n"); $smtp->datasend("\n"); $smtp->datasend("<body><img alt=\"My Picture\" img src=\""); open(my $fh2, '<', $pic) || die("Could not open Jpg file!"); binmode($fh2); local $/=undef; while (read($fh2, my $chunk, 72*57)) { my $buf = &encode_base64( $chunk ); $smtp->datasend($buf); } close($fh2); $smtp->datasend("\"></body>");

      In the mail header, you claim to encode the entire mail as base64, but you send it in plain text. That won't work.

      A little bit later, you use a base64 encoded file as URL of that file in an IMG tag. Of course, that also won't work. For an image URL containing the image instead of pointing to it, use a data URI. You would at least need to prefix the bas64 encoded image with "data:image/jpeg;base64,".

      Note that several HTML viewers have size limits on data URIs, others don't accept them at all.

      The RFC way of sending HTML mails with images is to append the image to the mail, give it a CID, and use the CID to as the URI of the image in the HTML part. See RFC2111.

      MIME::Lite (yes, I know this will trigger tons of "do not use that module" warnings) has a quite easy way to do that:

      $msg = MIME::Lite->new( To =>'you@yourhost.com', Subject =>'HTML with in-line images!', Type =>'multipart/related' ); $msg->attach( Type => 'text/html', Data => qq{ <body> Here's <i>my</i> image: <img src="cid:myimage.gif"> </body> }, ); $msg->attach( Type => 'image/gif', Id => 'myimage.gif', Path => '/path/to/somefile.gif', ); $msg->send();

      (Copied from "Send an HTML document... with images included!" in the MIME::Lite pod)

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
        Thank you for your reply afoken. I would like very much to use a higher level module than "Net::SMTPS" (even the deprecated MIME::Lite), but "Net::SMTPS" is the only module I have found with the options that allow me to connect to the Outlook web email server.

        "It's not how hard you work, it's how much you get done."

        Thank you huck. That got me a step closer. The embedded image no longer displays as raw base64 data in the email. The image still does not display in the body of the email. It appears as separate HTML attachment. When I downloaded the HTML attachment to check it in my browser (Chrome), the browser displays raw base64 code instead of the image. I'm sure this should not be this hard, but there are a lot of moving parts. Here is the latest attempt to display an embedded image in the body of the email using <img src=\"data:image/jpeg; base64," in the reference you provided:

        ############################################################## # Email - body (image) [NOT working] ############################################################## $smtp->datasend("--$boundary\n"); $smtp->datasend("MIME-Version: 1.0\n"); $smtp->datasend("Content-Type: text/html\n"); $smtp->datasend("Content-Transfer-Encoding: base64\n"); $smtp->datasend("Content-Disposition: inline\n"); $smtp->datasend("\n"); $smtp->datasend("<body><img src=\"data:image/jpeg; base64,"); open(my $fh2, '<', $pic) || die("Could not open Jpg file!"); binmode($fh2); local $/=undef; while (read($fh2, my $chunk, 72*57)) { my $buf = &encode_base64( $chunk ); $smtp->datasend($buf); } $smtp->datasend("\"></body>"); $smtp->datasend("\n"); close($fh2);

        "It's not how hard you work, it's how much you get done."

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11121523]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (7)
As of 2022-05-16 11:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you prefer to work remotely?



    Results (63 votes). Check out past polls.

    Notices?