In this blogpost, I am going to explain different ways using which we can include images as part of the email content.
CID Attachments
In this approach images are sent as attachment to the email and then images are referred in email content using attached filename. For e.g. if you want to include image "ironman.jpg", then you need to attach this image file to the email. Then you can refer the attached image using below syntax in "img" tag "src" attribute.
<img src="cid:ironman.jpg" alt="ironman"/>
Sample PL/SQL code to use this approach
DECLARE l_body CLOB; l_body_html CLOB; l_img_html CLOB; l_id NUMBER; BEGIN -- build html email body l_body_html := '<!DOCTYPE HTML>' || '<html>' || '<head>' || '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' || '<meta name="viewport" content="width=device-width">' || '</head>' || '<body style="background-color: #efefef; line-height: 1.5;">'; -- sending image as CID attachment -- observe image src attribute src="cid:ironman.jpg", here we are saying email client to get image from email attachments and look for file name ironman.jpg l_img_html := '<h1>Below image is sent as CID attachment.</h1><img src="cid:ironman.jpg" alt="ironman"/>'; l_body_html := l_body_html || l_img_html; l_body_html := l_body_html || '</body>' || '</html>'; l_body := 'Please use HTML enabled email client to view this message.'; l_id := apex_mail.send( p_to => :P30_EMAIL_TO ,p_from => 'noreply@oracle.com' ,p_body => l_body ,p_body_html => l_body_html ,p_subj => 'Including images as CID attachment' ); -- attach image file for CID attachment -- here I am taking one image from "Static Application Files" uploaded in shared components -- filename we are attaching should match with filename specified at img src -- if filename does not match, then below image will be displayed as normal attachment FOR img IN( SELECT filename ,blob_content ,mime_type FROM apex_application_files WHERE filename = 'ironman.jpg' AND flow_id = :APP_ID )LOOP apex_mail.add_attachment( p_mail_id => l_id ,p_attachment => img.blob_content ,p_filename => img.filename ,p_mime_type => img.mime_type ); END LOOP; -- optionally push email apex_mail.push_queue; END;
Since images are included as attachments, your email size will grow based on size of images used. This approach works well in most of the desktop clients but may not work well in web-based email clients. In my testing, this approach is working fine with Microsoft Outlook client, but not working as expected with Gmail web client. In Gmail, I can see it as normal attachment, but not as inline image.
Note: If you are using Oracle APEX 21.2 or later, then please refer Inline Attachments for Oracle APEX Emails blogpost.
Inline embedding using base64 encoding
In this approach images are converted to text format using base64 encoding and then they are directly used in "img" tag "src" attribute.
<img src="data:image/png;base64,<base64_image_text>" alt="ironman"/>
Sample PL/SQL code to use this approach
DECLARE l_body CLOB; l_body_html CLOB; l_img_html CLOB; l_img_base64 CLOB; l_mime_type VARCHAR2(255); l_img_blob BLOB; BEGIN -- build html email body l_body_html := '<!DOCTYPE HTML>' || '<html>' || '<head>' || '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' || '<meta name="viewport" content="width=device-width">' || '</head>' || '<body style="background-color: #efefef; line-height: 1.5;">'; -- here I am taking one image from "Static Application Files" uploaded in shared components -- convert image to base64 encoding SELECT blob_content ,mime_type INTO l_img_blob ,l_mime_type FROM apex_application_files WHERE filename = 'ironman.jpg' AND flow_id = :APP_ID; l_img_base64 := apex_web_service.blob2clobbase64(l_img_blob); -- sending image as text using base64 encoding -- observe image src attribute src="data:image/png;base64,<base64_image_text>" l_img_html := '<h1>Below image is sent as inline image by converting image to text using base64 encoding.</h1><img src="data:' || l_mime_type || ';base64,' || l_img_base64 || '" alt="ironman"/>'; l_body_html := l_body_html || l_img_html; l_body_html := l_body_html || '</body>' || '</html>'; l_body := 'Please use HTML enabled email client to view this message.'; apex_mail.send( p_to => :P30_EMAIL_TO ,p_from => 'noreply@oracle.com' ,p_body => l_body ,p_body_html => l_body_html ,p_subj => 'Embedding images inline using base64 encoding' ); -- optionally push email apex_mail.push_queue; END;
Again, since images are included as part of email content, your email size will grow based on size of images used. In my testing, this approach is working fine with Microsoft Outlook client, but not working at all with Gmail web client. I can only see image alt text in Gmail.
Hosted Images
DECLARE l_body CLOB; l_body_html CLOB; l_img_html CLOB; BEGIN -- build html email body l_body_html := '<!DOCTYPE HTML>' || '<html>' || '<head>' || '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' || '<meta name="viewport" content="width=device-width">' || '</head>' || '<body style="background-color: #efefef; line-height: 1.5;">'; -- referring to image hosted in server -- here I am taking one image from "Static Application Files" uploaded in shared components -- filename ironman.jpg l_img_html := '<h1>Below image is referred from external server. Size of this email should be small compared to other two approaches.</h1><img src="' || apex_mail.get_instance_url || :app_images || 'ironman.jpg" alt="ironman"/>'; l_body_html := l_body_html || l_img_html; l_body_html := l_body_html || '</body>' || '</html>'; l_body := 'Please use HTML enabled email client to view this message.'; apex_mail.send( p_to => :P30_EMAIL_TO ,p_from => 'noreply@oracle.com' ,p_body => l_body ,p_body_html => l_body_html ,p_subj => 'Referring hosted images' ); -- optionally push email apex_mail.push_queue; END;
Comments
Question please, how do you work with CSS positioning?
E.g. I'm trying to add some text on top of an image using style="position: absolute; top: 20px; left: 50px;"
But it does nothing.
On the same topic, adding text positioning (not on an image) doesn't seem to have any effect either.
Do you know why? or how to fix it?
Thanks