Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.mail; import javax.activation.DataSource; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * <p>Small wrapper class on top of HtmlEmail which encapsulates the required logic * to retrieve images that are contained in "<img src=../>" elements in the HTML * code. This is done by replacing all img-src-elements with "cid:"-entries and * embedding images in the email. * </p> * <p> * For local files the class tries to either load them via an absolute path or - * if available - use a relative path starting from a base directory. For files * that are not found locally, the implementation tries to download * the element and link it in. * </p> * <p> * The image loading is done by an instance of <code>DataSourceResolver</code> * which has to be provided by the caller. * </p> * * @since 1.3 * @version $Id: ImageHtmlEmail.java 1665692 2015-03-10 20:59:29Z tn $ */ public class ImageHtmlEmail extends HtmlEmail { // 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*[\"'])([^\"']+?)([\"'])"; /** regexp for extracting {@code <script>} tags */ public static final String REGEX_SCRIPT_SRC = "(<[Ss][Cc][Rr][Ii][Pp][Tt]\\s*.*?\\s+[Ss][Rr][Cc]\\s*=\\s*[\"'])([^\"']+?)([\"'])"; // this pattern looks for the HTML image tag which indicates embedded images, // the grouping is necessary to allow to replace the element with the CID /** pattern for extracting <img> tags */ private static final Pattern IMG_PATTERN = Pattern.compile(REGEX_IMG_SRC); /** pattern for extracting <script> tags */ private static final Pattern SCRIPT_PATTERN = Pattern.compile(REGEX_SCRIPT_SRC); /** resolve the images and script resources to a DataSource */ private DataSourceResolver dataSourceResolver; /** * Get the data source resolver. * * @return the resolver */ public DataSourceResolver getDataSourceResolver() { return dataSourceResolver; } /** * Set the data source resolver. * * @param dataSourceResolver the resolver */ public void setDataSourceResolver(final DataSourceResolver dataSourceResolver) { this.dataSourceResolver = dataSourceResolver; } /** * Does the work of actually building the MimeMessage. * * @see org.apache.commons.mail.HtmlEmail#buildMimeMessage() * @throws EmailException building the MimeMessage failed */ @Override public void buildMimeMessage() throws EmailException { try { // embed all the matching image and script resources within the email String temp = replacePattern(super.html, IMG_PATTERN); temp = replacePattern(temp, SCRIPT_PATTERN); setHtmlMsg(temp); super.buildMimeMessage(); } catch (final IOException e) { throw new EmailException("Building the MimeMessage failed", e); } } /** * Replace the regexp matching resource locations with "cid:..." references. * * @param htmlMessage the HTML message to analyze * @param pattern the regular expression to find resources * @return the HTML message containing "cid" references * @throws EmailException creating the email failed * @throws IOException resolving the resources failed */ private String replacePattern(final String htmlMessage, final Pattern pattern) throws EmailException, IOException { DataSource dataSource; final StringBuffer stringBuffer = new StringBuffer(); // maps "cid" --> name final Map<String, String> cidCache = new HashMap<String, String>(); // maps "name" --> dataSource final Map<String, DataSource> dataSourceCache = new HashMap<String, DataSource>(); // in the String, replace all "img src" with a CID and embed the related // image file if we find it. final Matcher matcher = pattern.matcher(htmlMessage); // the matcher returns all instances one by one while (matcher.find()) { // in the RegEx we have the <src> element as second "group" final String resourceLocation = matcher.group(2); // avoid loading the same data source more than once if (dataSourceCache.get(resourceLocation) == null) { // in lenient mode we might get a 'null' data source if the resource was not found dataSource = getDataSourceResolver().resolve(resourceLocation); if (dataSource != null) { dataSourceCache.put(resourceLocation, dataSource); } } else { dataSource = dataSourceCache.get(resourceLocation); } if (dataSource != null) { String name = dataSource.getName(); if (EmailUtils.isEmpty(name)) { name = resourceLocation; } String cid = cidCache.get(name); if (cid == null) { cid = embed(dataSource, name); cidCache.put(name, cid); } // if we embedded something, then we need to replace the URL with // the CID, otherwise the Matcher takes care of adding the // non-replaced text afterwards, so no else is necessary here! matcher.appendReplacement(stringBuffer, Matcher.quoteReplacement(matcher.group(1) + "cid:" + cid + matcher.group(3))); } } // append the remaining items... matcher.appendTail(stringBuffer); cidCache.clear(); dataSourceCache.clear(); return stringBuffer.toString(); } }