How do I add pictures to an email

Hi everybody,
I want to add a picture to the email I send, but how do I do that?
Thanks in advance.

2 Likes

Hi @Banksy,

you can add pictures via the report designer image.
Here you can find a tutorial.

br,
Sven

1 Like

Hi @sven-abx ,

My KNIME does not have this icon, do I need to install something?
Thanks in advance.

BR,
Banksy

hi @Banksy,

you need to install the KNIME Report Designer Extension.

File >> Install KNIME Extension >> KNIME & Extensions >> KNIME Report Designer
or type Report Designer in the search field.

br,
Sven

You can also just drag it to your workflow from this page:

Knime will install the proper package for you automatically.

And we’re assuming that @Banksy is sending these emails via Knime…

Hi @sven-abx
I’m so sorry, I’m a green hand.
I read the explanation of using KNIME Report Designer Extension in your reply, but I still don’t know how to add the picture to the Email and Send it through the Send Email Node. Could you tell me how to use it in detail?
Thanks in advance.

BR,
Banksy

Hi, @bruno29a ,

Thank you for your help, I have installed it successfully. But I don’t know how to use KNIME Report Designer to add pictures to Send Email Node.

Thanks in advance.

Br
Banksy

hello @Banksy,

you can also have a look here. It is a link to the Youtube-Channel of KNIME.

br,
Sven

Hi @sven-abx

Thank your share link and I watched the video. I don’t think I’m making it clear. I want to add an image like a logo to the body of the email and send it using the Send Email node. The rest of the body of the email is from the Table to HTML String node. So I don’t understand how Report Designer can realize this requirement.

Thank you for your help anyway.

BR,
Banksy

This is actually a harder problem than one would think and maybe we should add this to the Features and ideas area? Currently it is way to complex.

The report designer lets you create a report and then send that report but only as attachment. I fully agree with you that usually this is simply not really what you want. The report should be the email body and I think knime should somehow give us options for that instead of sending pdf attachments.

How can you do it with the Send email node? I don’t think you can at least last time I checked. Search how images in email works. it is actually different form html even if you send an html email. I’m doing this in 3 main steps:

  1. Build the html email with Python Script (probably not needed in your case)
  2. generate base64 encoded images in java snippet
  3. sending the email from java snippet.

I’m sending a table with 1 image per row. In your case it’s probably easier because you just want a header image and not 1 image per table row so the first step is likley much simpler.

Details

You need javax.mail.jar and jakarta.activation-1.2.2.jar (if you are on KNIME 4.5.1, different for older versions that use Java 8)

In your email html code you need something like this:

<img src="cid:image-0">

The actual cid doesn’t matter you can change it to cid:banner or whatever but you need to reuse it in the java code when sending the email,

base64encode image

First you need to convert your image to a binary object, then you need to base64 encode it.

image

The Java code I use. You might need to adjust to bit your column names.

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;

// system variables
public class JSnippet extends AbstractJSnippet {
  // Fields for input columns
  /** Input column: "Image" */
  public InputStream c_image;

  // Fields for output columns
  /** Output column: "base64_image" */
  public String out_base64_image;

// Your custom variables:

// expression start
    public void snippet() throws TypeException, ColumnException, Abort {
// Enter your code here:
try {
	ByteArrayOutputStream buffer = new ByteArrayOutputStream();
	
	int nRead;
	byte[] data = new byte[4096];
	
	while ((nRead = c_image.read(data, 0, data.length)) != -1) {
	  buffer.write(data, 0, nRead);
	}
	
	out_base64_image = Base64.getEncoder().encodeToString(buffer.toByteArray());
	
	
} catch (IOException ex) {
	throw new Abort(ex);
}

Send the email

Then having your email body, base64 image and your recipients in the same table row you can use another java snippet to send the email. Note that this snippet requires the 2 additional libraries mentioned above added to the java snippet.

// Your custom imports:
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Message.RecipientType;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.PreencodedMimeBodyPart;
import javax.mail.internet.InternetAddress;
import javax.mail.Transport;
import javax.mail.Message;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

// system variables
public class JSnippet extends AbstractJSnippet {
  // Fields for input columns
  /** Input column: "HTML" */
  public String c_HTML;
  /** Input column: "base64_image" */
  public String c_base64_image;
  /** Input column: "email" */
  public String[] c_email; // array of email addresses


// Your custom variables:

// expression start
    public void snippet() throws TypeException, ColumnException, Abort {
// Enter your code here:
try {	
	
	Properties mailProps = new Properties();
     mailProps.put("mail.transport.protocol", "smtp");
     mailProps.put("mail.host", "smtp.mycompany.com");
     mailProps.put("mail.smtp.port", "25"); // might need to change to different port for tls
     mailProps.put("mail.smtp.auth", "false"); // might need to authenticate making this part harder

	Session session = Session.getDefaultInstance(mailProps);
	Message m = new MimeMessage(session);
  	MimeMultipart content = new MimeMultipart();
  	MimeBodyPart mainPart = new MimeBodyPart();
 	mainPart.setText(c_HTML, "UTF-8", "html"); // this is your email in html
  	content.addBodyPart(mainPart);  
    
    // add the banner image    
    MimeBodyPart imgPart = new PreencodedMimeBodyPart("base64");
    imgPart.setContent(c_base64_image, "image/png");
    imgPart.setContentID("<image-0>"); // must match cid in your html email, <> seems to be required
    imgPart.setDisposition(MimeBodyPart.INLINE);
    content.addBodyPart(imgPart);
  			
 	m.setContent(content);
  	m.setSubject("Daily chassis output");
  	m.setFrom(new InternetAddress("knime@mycompany.com"));
  	
	for (String email : c_email) {
		m.addRecipient(RecipientType.TO, new InternetAddress(email));
	}
    Transport.send(m);

} catch (MessagingException ex) {
	throw new Abort(ex);
} 
2 Likes

hello @Banksy,

this workflow from @Iris was posted on the hub.

to get it clear, you want to send the workflow data as a email formated in html?

br,
sven

1 Like

hi @Banksy

just try converting your image to Base64.

https://www.base64-image.de/

and insert the base64 code of the image in the tag:

<img src="base64code" width: height> 
1 Like

Hi @Banksy , since you are still struggling with this, I decided to have a go at it.

As per @kienerj , with the report, it would be sending the email content as an attached report rather than as an html body email. And as pointed out by both @kienerj and @natanaeldgsantos , you need to convert the images to base64 in order to be able to include the image in the body of the email.

I think @kienerj is a good solution. I have, however, implemented something that does all this directly in Knime nodes without Java Snippet (hence avoiding you have to look and install additional jar files), and where you can send via the Send Email node.

Here’s what the workflow looks like:

For the sake of the example, I have 3 images I want to include in my emails:
image

And I purposely used different image types (png and jpg). I will also use the file names as variable names that holds the value to be used.

After converting, these are the variables and their respective values:

I can just refer to these variables in my email HTML template. For example:

You can find my workflow here:

3 Likes

Here’s a screenshot of what the email I received looks like (from my phone):

These are exactly the 3 images that I used in the workflow. The first image was meant to be an email header with the logo, which turned out to be quite big lol. Of course, you can change the size of the element (that’s more of an HTML topic than the one in the thread)

4 Likes

Just for everyone to be aware to read the license of the Palladian nodes (Base 64 encoder). In a business context you can’t use the free license AFAIK.

EDIT:

And second point why I use my convoluted way: it’s the official way. Your way work fine in email clients in your case iphone or in my case Thunderbird.

However in gmail (web site and apps) it looks like this:

eg. no image just the base64image as plain text.

hence my comment it is more complex than it seems. In my case we use gmail so my way works for gmail, if your recipients all use say outlook and it works in outlook then fine. If however you have no idea what client they use, you need to go the official way with cid.

Link to explain the issue:

Hey @kienerj , thanks for the additional info.

I’m guessing you mean web-based email clients or webmail when you said “gmail (web site and apps)”, correct?

Based on what I see, there’s no “official” way. And as per the sendgrid resource that you provided “there’s no one way to do this”. and it also seems to contradict what you are saying about using CID: “The problem with CID embedded images is that they don’t always display properly in email clients. The rule of thumb I use is that CID embedding will work fine in the majority of desktop email clients, but most likely not at all in web-based email clients such as Gmail or Yahoo! Mail. Bummer.”

You are correct in that the inline embedding that I used has limitations, but so does the CID method as exposed in the Sendgrid resource.

The best way for me remains the Linked method, which is what most companies use when sending emails where all images are simply referenced to where the images are hosted on a server. This has never failed for me, regardless of the email client you use. Of course, you need internet to view the images, but it is assumed that you are connected if you are viewing the email, except if you are viewing it offline after having downloaded the email.

As for the license for Palladian nodes, adding @qqilihq as he is the owner of Palladian. The worst case if it cannot be used, we can do the conversion via Java snippet using the included apache commons libraries (The Palladian nodes are java-based)

EDIT: I just did a test with CID, and when I open it in my webmail, the images are not inline embedded. They’re added as attachment for me. It might show properly in other webmail. That’s to say that it’s not guaranteed to work, and it’s not the “official” way.

On the other hand, this piece of html email would work:

<html>
<body>
<img src="https://forum-cdn.knime.com/uploads/default/optimized/3X/8/8/8841d8dcce83f8b7c0b316b7d4244d4d464b1d9a_2_690x125.png"><br />
You should see the logo above, whether you open in an email client or a web-based/webmail email
</body>
</html>
2 Likes

Thanks to @bruno29a for the notification!

That’s definitely not the case. Quoting from the license:

Exception of sections 2 and 6 for the use of Palladian within KNIME: You may use the Palladian KNIME Nodes (“Palladian for KNIME”) in conjunction with free versions of KNIME free of charge for any purpose, including commercial and production use. This also includes output generated with the Palladian KNIME Nodes and free versions of KNIME.

Paraphrased: You can use Palladian in any context (private, business, education, …) free of charge, as long as you run it on a free version of KNIME Desktop.

If you want to run it on a KNIME Server (the one for which you pay :dollar:), a commercial license is required. (and compared to what you pay for a KNIME Server, it’s a very fair price, you support the development which happens independently from the KNIME company, and you get world-class support :slightly_smiling_face: ).

Any further questions let me know.

6 Likes

Hi @natanaeldgsantos

Why can only half of my image be displayed? Is there something wrong with my Settings?
Thank you in advance!

I really meant the gmail web client and the gmail app (on android). Both only work with the CID thing but not the inline images. As you say could be the exact opposite with different web client.

But yeah I agree it is hit and miss. If one is sending company internal mails, then you are all good as you can choose the methods that works for the used client be it gmail, outlook or something else.

Linked images probably do work most universally as in the probably work in all clients if they aren’t blocked. Which in my case I do. linked images are used in marketing mails because they are also great to track users by appending a unique id to the link. Plus you need a place to host them.

All in all it is much more complex than one would expect.

Hi @bruno29a ,

Thank you so much for your workflow, it worked successful.
You’ve been a great help.

1 Like