Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for dynamic datasource resolution (file/url/classpath) for embedded images in HTML body #260

Closed
distributev opened this issue Apr 23, 2020 · 8 comments

Comments

@distributev
Copy link

Is there any API available to achieve this?

Currently, in order to embed an image a user would have to modify both the HTML template and the Java code like this

java

currentEmailBuilder.withEmbeddedImage("smiley", new FileDataSource("smiley.jpg"));

and then the corresponding HTML code

<p>Smile!</p><img src='cid:smiley'>

this is fine but in many situations users are allowed to modify the HTML template but the java code would not be available to be modified by the users; thus would be useful to allow dynamically embedding images in emails only by referencing the image files in the HTML code.

I also used the apache commons email and they provide the option, only be modifying the HTML template to include images available both locally and also on remote websites.

Apache commons email has something like a DatasourceResolver which could be either DataSourceFileResolver or DataSourceUrlResolver like this

email.setDataSourceResolver(new DataSourceUrlResolver(new URL("http://website.com")))

email.setDataSourceResolver(new DataSourceFileResolver(new File("./templates")))

and then the user would only be expected to provide the HTML code like this

<img src="template1/images/logo.png"/> - starting from the ./templates parent directory

or from the website

<img src="http://website.com/template1/images/logo.png"/>

Here is the apache commons email API for the resolver

https://commons.apache.org/proper/commons-email/javadocs/api-release/index.html

Is there something similar available in simple-java-mail?

P.S - I believe that simple-java-mail has a very good API and I intend switching from apache commons email for the additional features which your API provides like delivery / read receipt and other things. I also intend to use email-rfc2822-validator for validating email addresses. Thank you for the hard work you put in this project.

@bbottema
Copy link
Owner

Sorry, I see I forgot to reply to this. I think this is a very interesting feature and I'm considering adding it. I'll look into this DataSourceFileResolver.

My first thought is that I would have to parse the HTML for all the src attributes. I solve that (rather ugly) with regular expression.

@bbottema
Copy link
Owner

bbottema commented Jul 5, 2020

My first thought is that I would have to parse the HTML for all the src attributes. I solve that (rather ugly) with regular expression.

Looking an commons email, they indeed are using regex to find all images:

    // Regular Expression to find all <IMG SRC="..."> entries in an HTML
    // document.It needs to cater for various things, like more whitespaces
    // including newlines on any place, HTML is not case sensitive and there
    // can be arbitrary text between "IMG" and "SRC" like IDs and other things.

    /** Regexp for extracting {@code <img>} tags */
    public static final String REGEX_IMG_SRC =
            "(<[Ii][Mm][Gg]\\s*[^>]*?\\s+[Ss][Rr][Cc]\\s*=\\s*[\"'])([^\"']+?)([\"'])";

@bbottema
Copy link
Owner

bbottema commented Jul 5, 2020

What do you think about the lenient flag Commons Email uses? Lenient means no error will occur for datasources that cannot be resolved, resulting in missing images in the email. Personally, I find that a bad practice, especially because it is a silent process.

@bbottema bbottema changed the title Is it possible to embed images dynamically only by referencing images in the HTML code? Add support for dynamic datasource resolution (file/url/classpath) for embedded images in HTML body Jul 5, 2020
bbottema added a commit that referenced this issue Jul 6, 2020
@distributev
Copy link
Author

distributev commented Jul 7, 2020

I also think that out of the box, if a flag like lenient is not specifically configured, IO Exceptions should be raised that images are missing.

However, if the user will specifically configure lenient as being true, then no exception will be thrown and the emails will be sent with missing images. Warnings could be raised in the log files in this case, but the emails will be sent.

@bbottema
Copy link
Owner

bbottema commented Jul 7, 2020

I'm thinking of leaving the flag out completely.

@distributev
Copy link
Author

this works too

@bbottema
Copy link
Owner

bbottema commented Jul 9, 2020

I'm going all in with this feature, it's a very cool addition!

So here's what I've added and tested fully with junit:

builder
	// enable auto resolution
	.withEmbeddedImageAutoResolutionForFiles(true) // default false
	.withEmbeddedImageAutoResolutionForClassPathResources(true) // default false
	.withEmbeddedImageAutoResolutionForURLs(true) // default false

	// support for base dirs
	.withEmbeddedImageBaseDir(RESOURCES_PATH + "/images")
	.withEmbeddedImageBaseUrl("http://www.simplejavamail.org/static/")
	.withEmbeddedImageBaseClassPath("/images")

	// allow resources outside of basedir (careful, potential security attack surface!)
	.allowingEmbeddedImageOutsideBaseDir(true) // default false
	.allowingEmbeddedImageOutsideBaseClassPath(true) // default false
	.allowingEmbeddedImageOutsideBaseUrl(true) // default false

	// fail if a resource couldn't be resolved
	.embeddedImageAutoResolutionMustBeSuccesful(true) // default false (lenient)

Supported by config properties as well:

simplejavamail.embeddedimages.dynamicresolution.enable.dir=true
simplejavamail.embeddedimages.dynamicresolution.enable.url=true
simplejavamail.embeddedimages.dynamicresolution.enable.classpath=true
simplejavamail.embeddedimages.dynamicresolution.base.dir=...
simplejavamail.embeddedimages.dynamicresolution.base.url=http://www.simplejavamail.org/static/
simplejavamail.embeddedimages.dynamicresolution.base.classpath=/images
simplejavamail.embeddedimages.dynamicresolution.outside.base.dir=true
simplejavamail.embeddedimages.dynamicresolution.outside.base.classpath=true
simplejavamail.embeddedimages.dynamicresolution.outside.base.url=true
simplejavamail.embeddedimages.dynamicresolution.mustbesuccesful=true

Any thoughts on this API design? I think this is more robust than the Commons Email solution.

bbottema added a commit that referenced this issue Jul 10, 2020
…h mimetype when loading image from classpath/disk
bbottema added a commit that referenced this issue Jul 10, 2020
…le it, added api to force resolving only from basepath or allow outside, added option to enforce resolution or fail with exception that image source could not be resolved
@bbottema
Copy link
Owner

Feature released in 6.2.0!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants