emailBean : Send DominoDocument HTML Emails c/w Embedded Images, Attachments, Custom Header/Footer


Code 1 - EmailBean.java

/**
 * @author Tony McGuckin, IBM
 */
 
package com.ibm.xsp.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.faces.context.FacesContext;

import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.EmbeddedObject;
import lotus.domino.MIMEEntity;
import lotus.domino.MIMEHeader;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.Stream;

import com.ibm.commons.util.NotImplementedException;
import com.ibm.domino.xsp.module.nsf.NotesContext;
import com.ibm.xsp.model.FileRowData;
import com.ibm.xsp.model.domino.wrapped.DominoDocument;
import com.ibm.xsp.model.domino.wrapped.DominoRichTextItem;
import com.ibm.xsp.model.domino.wrapped.DominoDocument.AttachmentValueHolder;
import com.ibm.xsp.persistence.PersistedContent;

public class EmailBean {
	
	private ArrayList<String> sendTo;
	private ArrayList<String> ccList;
	private ArrayList<String> bccList;
	private String senderEmail;
	private String senderName;
	private String subject;
	
	private DominoDocument document;
	private String fieldName;
	
	private String bannerHTML;
	private String footerHTML;
	
	private boolean debugMode = false;
	
	private static final Pattern imgRegExp = Pattern.compile("<img[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>");
	
	//-------------------------------------------------------------------------
	
	public EmailBean(){
		this.subject = "";
		this.sendTo = new ArrayList<String>();
		this.ccList = new ArrayList<String>();
		this.bccList = new ArrayList<String>();
	}
	
	//-------------------------------------------------------------------------

	public String getSendTo(){
		if(this.isDebugMode()){
			System.out.println("getSendTo() : " + this.sendTo.toString());
		}
		return this.sendTo.toString().replace("[", "").replace("]", "");
	}
	
	public void setSendTo(final String sendTo){
		this.sendTo.add(sendTo);
	}
	
	//-------------------------------------------------------------------------

	public String getCcList(){
		if(this.isDebugMode()){
			System.out.println("getCcList() : " + this.ccList.toString());
		}
		return this.ccList.toString().replace("[", "").replace("]", "");
	}
	
	public void setCcList(final String ccList){
		this.ccList.add(ccList);
	}
	
	//-------------------------------------------------------------------------

	public String getBccList(){
		if(this.isDebugMode()){
			System.out.println("getBccList() : " + this.bccList.toString());
		}
		return this.bccList.toString().replace("[", "").replace("]", "");
	}
	
	public void setBccList(final String bccList){
		this.bccList.add(bccList);
	}
	
	//-------------------------------------------------------------------------

	public String getSenderEmail(){
		return this.senderEmail;
	}
	
	public void setSenderEmail(final String senderEmail){
		this.senderEmail = senderEmail;
	}
	
	//-------------------------------------------------------------------------

	public String getSenderName(){
		return this.senderName;
	}
	
	public void setSenderName(final String senderName){
		this.senderName = senderName;
	}
	
	//-------------------------------------------------------------------------

	public String getSubject(){
		return this.subject;
	}
	
	public void setSubject(final String subject){
		this.subject = subject;
	}
	
	//-------------------------------------------------------------------------

	public boolean isDebugMode(){
		return this.debugMode;
	}
	
	public void setDebugMode(final boolean debugMode){
		this.debugMode = debugMode;
	}
	
	//-------------------------------------------------------------------------
	
	private Session getCurrentSession(){
		NotesContext nc = NotesContext.getCurrentUnchecked();
    	return (null != nc) ? nc.getCurrentSession() : null;
	}
	
	//-------------------------------------------------------------------------
	
	private Database getCurrentDatabase(){
		NotesContext nc = NotesContext.getCurrentUnchecked();
    	return (null != nc) ? nc.getCurrentDatabase() : null;
	}
	
	//-------------------------------------------------------------------------
	
	public void send() throws NotesException, IOException, Exception{
		Session session = getCurrentSession();
		Database database = getCurrentDatabase();
		if(null != session && null != database &&
			null != this.sendTo && null != this.subject &&
				null != this.senderEmail
		){
			try {
				if(this.isDebugMode()){
					System.out.println("Started send()");
				}
				session.setConvertMime(false);
				Document emailDocument = database.createDocument();

				MIMEEntity emailRoot = emailDocument.createMIMEEntity("Body");
				if(null != emailRoot){
					MIMEHeader emailHeader = emailRoot.createHeader("Reply-To");
					emailHeader.setHeaderVal(this.getSenderEmail());
					
					emailHeader = emailRoot.createHeader("Return-Path");
					emailHeader.setHeaderVal(this.getSenderEmail());
					
					final String fromSender = (null == this.getSenderName()) ?
							this.getSenderEmail() :
								"\"" + this.getSenderName() + "\" <" + this.getSenderEmail() + ">";
					
					emailHeader = emailRoot.createHeader("From");
					emailHeader.setHeaderVal(fromSender);
						
					emailHeader = emailRoot.createHeader("Sender");
					emailHeader.setHeaderVal(fromSender);
				
					emailHeader = emailRoot.createHeader("To");
					emailHeader.setHeaderVal(this.getSendTo());
					
					if(!this.ccList.isEmpty()){
						emailHeader = emailRoot.createHeader("CC");
						emailHeader.setHeaderVal(this.getCcList());
					}
					
					if(!this.bccList.isEmpty()){
						emailHeader = emailRoot.createHeader("BCC");
						emailHeader.setHeaderVal(this.getBccList());
					}
					
					emailHeader = emailRoot.createHeader("Subject");
					emailHeader.setHeaderVal(this.getSubject());
					
					MIMEEntity emailRootChild = emailRoot.createChildEntity();
					if(null != emailRootChild){
						final String boundary = System.currentTimeMillis() + "-" + this.document.getDocumentId();
						emailHeader = emailRootChild.createHeader("Content-Type");
						emailHeader.setHeaderVal("multipart/alternative; boundary=\"" + boundary + "\"");
						
						MIMEEntity emailChild = emailRootChild.createChildEntity();
						if(null != emailChild){
							final String contentAsText = this.document.getRichTextItem(this.fieldName).getContentAsText();
							Stream stream = session.createStream();
							stream.writeText(contentAsText);
							emailChild.setContentFromText(stream, "text/plain; charset=\"UTF-8\"", MIMEEntity.ENC_NONE);
							stream.close();
							
							emailChild = emailRootChild.createChildEntity();
							stream = session.createStream();
							stream.writeText(this.getHTML());
							emailChild.setContentFromText(stream, "text/html; charset=\"UTF-8\"", MIMEEntity.ENC_NONE);
							stream.close();
							stream.recycle();
							stream = null;
						}
						
						// add embedded images....
						final List<FileRowData> embeddedImages = this.getEmbeddedImagesList();
						if(null != embeddedImages && !embeddedImages.isEmpty()){
							if(this.isDebugMode()){
								System.out.println("Adding Embedded Images...");
							}
					    	for(FileRowData embeddedImage : embeddedImages) {
								emailRootChild = emailRoot.createChildEntity();
								if(null != emailRootChild && embeddedImage instanceof AttachmentValueHolder){
									InputStream is = null;
									try {
										String persistentName = ((AttachmentValueHolder)embeddedImage).getPersistentName();
										String cid = ((AttachmentValueHolder)embeddedImage).getCID();
										emailHeader = emailRootChild.createHeader("Content-Disposition");
										emailHeader.setHeaderVal("inline; filename=\"" + persistentName + "\"");
										emailHeader = emailRootChild.createHeader("Content-ID");
										emailHeader.setHeaderVal("<" + cid + ">");
										is = this.getEmbeddedImageStream(persistentName);
										Stream stream = session.createStream();
										stream.setContents(is);
										emailRootChild.setContentFromBytes(stream, embeddedImage.getType(), MIMEEntity.ENC_IDENTITY_BINARY);
										if(this.isDebugMode()){
											System.out.println("Added Embedded Image : " + persistentName);
										}
									} catch (IOException e) {
										if(this.isDebugMode()){
											System.out.println("Adding Embedded Image failed : " + e.getMessage());
										}
										throw e;
									} finally {
										if(null != is){
											is.close();
											is = null;
										}
									}
								}
					    	}
							if(this.isDebugMode()){
								System.out.println("Completed Adding Embedded Images");
							}
						}
						
						// add attachments....
						final List<FileRowData> attachments = this.getDocument().getAttachmentList(this.getFieldName());
						if(null != attachments && !attachments.isEmpty()){
							if(this.isDebugMode()){
								System.out.println("Adding Attachments...");
							}
					    	for(FileRowData attachment : attachments) {
								emailRootChild = emailRoot.createChildEntity();
								if(null != emailRootChild && attachment instanceof AttachmentValueHolder){
									InputStream is = null;
									try {
										String persistentName = ((AttachmentValueHolder)attachment).getPersistentName();
										String cid = ((AttachmentValueHolder)attachment).getCID();
										EmbeddedObject eo = this.getDocument().getDocument().getAttachment(persistentName);
										if(null != eo){
											emailHeader = emailRootChild.createHeader("Content-Disposition");
											emailHeader.setHeaderVal("attachment; filename=\"" + persistentName + "\"");
											emailHeader = emailRootChild.createHeader("Content-ID");
											emailHeader.setHeaderVal("<" + cid + ">");
											is = eo.getInputStream();
											Stream stream = session.createStream();
											stream.setContents(is);
											emailRootChild.setContentFromBytes(stream, attachment.getType(), MIMEEntity.ENC_IDENTITY_BINARY);
											if(this.isDebugMode()){
												System.out.println("Added Attachment : " + persistentName);
											}
										}
									} catch (Exception e) {
										if(this.isDebugMode()){
											System.out.println("Adding Attachment failed : " + e.getMessage());
										}
										throw e;
									} finally {
										if(null != is){
											is.close();
											is = null;
										}
									}
								}
					    	}
							if(this.isDebugMode()){
								System.out.println("Completed Adding Attachments");
							}
						}
					}
				}
				emailDocument.send();
				session.setConvertMime(true);
				if(this.isDebugMode()){
					System.out.println("Completed send()");
				}
			} catch (NotesException e) {
				if(this.isDebugMode()){
					System.out.println("Failed send() with NotesException" + e.getMessage());
				}
				throw e;
			} catch (IOException e) {
				if(this.isDebugMode()){
					System.out.println("Failed send() with IOException" + e.getMessage());
				}
				throw e;
			} catch (Exception e) {
				if(this.isDebugMode()){
					System.out.println("Failed send() with Exception" + e.getMessage());
				}
				throw e;
			}
		}
	}
	
	//-------------------------------------------------------------------------
	
	public DominoDocument getDocument(){
		return this.document;
	}
	
	public void setDocument(final DominoDocument document){
		this.document = document;
	}
	
	//-------------------------------------------------------------------------

	public String getFieldName(){
		return this.fieldName;
	}
	
	public void setFieldName(final String fieldName){
		this.fieldName = fieldName;
	}
	
	//-------------------------------------------------------------------------
	
	public List<FileRowData> getEmbeddedImagesList() throws NotesException{
		if(null != document && null != fieldName){
			return document.getEmbeddedImagesList(fieldName);
		}
		return null;
	}
	
	//-------------------------------------------------------------------------
	
	private InputStream getEmbeddedImageStream(final String fileName) throws NotesException, IOException{
		if(null != document && null != fieldName && null != fileName){
			final DominoRichTextItem drti = document.getRichTextItem(fieldName);
			if(null != drti){
				final PersistedContent pc = drti.getPersistedContent(FacesContext.getCurrentInstance(), fieldName, fileName);
				if(null != pc){
					return pc.getInputStream();
				}
			}
		}
		return null;
	}
	
	//-------------------------------------------------------------------------

	public String getHTML(){
		StringBuffer html = new StringBuffer();
		html.append(getBannerHTML());
		html.append(getBodyHTML());
		html.append(getFooterHTML());
		return html.toString();
	}
	
	//-------------------------------------------------------------------------

	public String getBannerHTML(){
		return this.bannerHTML;
	}

	public void setBannerHTML(final String bannerHTML){
		this.bannerHTML = bannerHTML;
	}
	
	//-------------------------------------------------------------------------

	public String getBodyHTML(){
		if(null != document && null != fieldName){
			if(this.isDebugMode()){
				System.out.println("Started getBodyHTML()");
			}
			final DominoRichTextItem drti = document.getRichTextItem(fieldName);
			if(null != drti){
				try {
					String html = drti.getHTML();
					if(null != html){
						final List<FileRowData> fileRowDataList = document.getEmbeddedImagesList(fieldName);
						if(null != fileRowDataList){
					    	final Matcher matcher = imgRegExp.matcher(html);
					        while(matcher.find()){
					            String src = matcher.group();
					            final String srcToken = "src=\"";
					            final int x = src.indexOf(srcToken);
					            final int y = src.indexOf("\"", x + srcToken.length());
					            final String srcText = src.substring(x + srcToken.length(), y);
					    		for(FileRowData fileRowData : fileRowDataList) {
					    			final String srcImage = fileRowData.getHref();
					    			final String cidImage = ((AttachmentValueHolder)fileRowData).getCID();
					    			if(srcText.endsWith(srcImage)){
						    			final String newSrc = src.replace(srcText, "cid:" + cidImage);
										html = html.replace(src, newSrc);
										if(this.isDebugMode()){
											System.out.println("CID referenced image: " + srcText + " with CID:" + cidImage);
										}
					    			}
					   			}
					        }
						}
					}
					if(this.isDebugMode()){
						System.out.println("Completed getBodyHTML() : " + html);
					}
			        return html;
				} catch (Exception e) {
					if(this.isDebugMode()){
						System.out.println("Failed getBodyHTML() : " + e.getMessage());
					}
				}
			}
		}
		return null;
	}
	
	public void setBodyHTML(final String bodyHTML) throws NotImplementedException{
		if(this.isDebugMode()){
			System.out.println("Method setBodyHTML(string) is not permitted");
		}
		throw new NotImplementedException();
	}
	
	//-------------------------------------------------------------------------

	public String getFooterHTML(){
		return this.footerHTML;
	}
	
	public void setFooterHTML(final String footerHTML){
		this.footerHTML = footerHTML;
	}
	
	//-------------------------------------------------------------------------
	
} // end EmailBean



Code 2 - faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
	<managed-bean>
		<managed-bean-name>emailBean</managed-bean-name>
		<managed-bean-class>com.ibm.xsp.utils.EmailBean</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
		<managed-property>
			<property-name>debugMode</property-name>
			<value>true</value>
		</managed-property>
	</managed-bean>
</faces-config>



Code 3 - emailBeanTest.xsp

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.ibm.com/xsp/core xsdxp://localhost/xsp~core.xsd">
	<xp:this.data>
		<xp:dominoDocument var="document1" formName="frmEmail">
			<xp:this.postSaveDocument>
				<![CDATA[#{javascript:
					try{
						var sendTo = document1.getItemValueString("SendTo");
						var subject = document1.getItemValueString("Subject");
						
						var senderEmail = "samantha/renovations";
						var senderName = "Samantha at Renovations";
						
						emailBean.setSendTo(sendTo);
						emailBean.setSubject(subject);
						emailBean.setSenderEmail(senderEmail);
						emailBean.setSenderName(senderName);
						emailBean.setDocument(document1);
						emailBean.setFieldName("Body");
						emailBean.setBannerHTML("<p>Hi " + sendTo + ",</p>");
						emailBean.setFooterHTML("<p>Kind regards,<br/>" + senderName + "<br/>0044 1234 5678</p>");
						
						emailBean.send();
					}catch(e){
						print(e.getMessage());
					}
				}]]>
			</xp:this.postSaveDocument>
		</xp:dominoDocument>
	</xp:this.data>
	<xp:table style="padding:20px">
		<xp:tr>
			<xp:td>
				<xp:label value="SendTo:" id="to_Label1" for="to"></xp:label>
			</xp:td>
			<xp:td>
				<xp:inputText value="#{document1.SendTo}" id="to"></xp:inputText>
			</xp:td>
		</xp:tr>
		<xp:tr>
			<xp:td>
				<xp:label value="Subject:" id="subject_Label1" for="subject">
				</xp:label>
			</xp:td>
			<xp:td>
				<xp:inputText value="#{document1.Subject}" id="subject">
				</xp:inputText>
			</xp:td>
		</xp:tr>
		<xp:tr>
			<xp:td valign="top">
				<xp:label value="Body:" id="body_2_Label1" for="body">
				</xp:label>
			</xp:td>
			<xp:td>
				<xp:inputRichText value="#{document1.Body}" id="body">
				</xp:inputRichText>
			</xp:td>
		</xp:tr>
		<xp:tr>
			<xp:td valign="top">
				<xp:label value="Attachments:" id="label12" for="fileUpload1">
				</xp:label>
			</xp:td>
			<xp:td>
				<xp:fileUpload id="fileUpload1" value="#{document1.Body}">
				</xp:fileUpload>
				<xp:br></xp:br>
				<xp:br></xp:br>
				<xp:fileDownload rows="30" id="fileDownload1"
					displayLastModified="false" allowDelete="true" value="#{document1.Body}"></xp:fileDownload>
			</xp:td>
		</xp:tr>
		<xp:tr>
			<xp:td></xp:td>
			<xp:td>
				<xp:button id="button1" value="Save and Email">
					<xp:eventHandler event="onclick" submit="true"
						refreshMode="complete">
						<xp:this.action>
							<xp:saveDocument var="document1"></xp:saveDocument>
						</xp:this.action>
					</xp:eventHandler>
				</xp:button>
			</xp:td>
		</xp:tr>
	</xp:table>
</xp:view>
All code submitted to OpenNTF XSnippets, whether submitted as a "Snippet" or in the body of a Comment, is provided under the Apache License Version 2.0. See Terms of Use for full details.
9 comment(s)Login first to comment...
Richard Schumann
(at 12:24 on 13.09.2020)
Ulrich,
While trying to get this example to work, i'm getting a 'Can't instantiate class: 'com.ibm.xsp.utils.EmailBean'..null' error during the onClick event of the 'Save and Email' button found on the 'emailTestBean' XPage.
The page loads without issue, however, when I click the 'Save and Email' button, it's throwing a runtime error. I'm rather new at working with JAVA. I'm assuming my root cause is the non-presence of this class file, but that's just a guess on my part.
If I comment-out the <xp:saveDocument> action, it appears to execute without further error, but the email is not sent.
Brian M Moore
(at 20:53 on 31.07.2018)
Gmail and some other services may reject if you do not add the "InetFrom" header. I put it right after setting the "Sender" header:

emailHeader = emailRoot.createHeader("Sender");
emailHeader.setHeaderVal(fromSender);

// this is needed to send it to GMail.
emailHeader = emailRoot.createHeader("InetFrom");
emailHeader.setHeaderVal(fromSender);
Alice Smith
(at 06:03 on 04.11.2017)
Use CKEditor bound to the data source to compose the email content that can also include embedded images.
Steven Darcy
(at 02:23 on 21.07.2016)
Thanks All ! This is a big help however I have issues though when I use this within a loop on a document save where I pass variables into the code to send multiple emails and I hope someone might be able to assist with why.
Basically I think it's because the string values passed are not cleared and therefore if they are not overwritten then they appear on the next email, also when passing to a list, the new value adds to the previous email's passed value.

Examples:
1st Email:
emailBean.setSendTo("John")
Result: Sends email to John

2nd Email (2nd loop)
emailBean.setSendTo("Mary")
Result: Sends email to John and Mary


1st Email
emailBean.addHTML("test here")
Result: test here (within body)

2nd Email (2nd loop)
Has no addHTML
Result: test here (within body)

Any ideas?
Andrew Magerman
(at 10:51 on 20.04.2015)
just noticed that Grégory posted exactly the same thing. Aaah!
Andrew Magerman
(at 10:50 on 20.04.2015)
Bug for special characters in the subject line; fix:

emailHeader = emailRoot.createHeader("Subject");
// emailHeader.setHeaderVal(this.getSubject());
emailHeader.addValText(this.getSubject(), "UTF-8");

Per Henrik Lausten
(at 01:52 on 07.09.2014)
I had issues with encoding of special characters too and found out that I needed to both MIME encode the strings and use addValText() but without encoding as UTF-8.
See my answer on Stack Overflow: http://stackoverflow.com/a/25707583/785061
Grégory DEVISE
(at 09:53 on 28.04.2014)
Thank you very much Tony and Ulrich. Very useful code!

I meet problems with accented characters (in the subject, sender etc ...).

The solution that seems to work is to use the method :
emailHeader.addValText(xxx,"UTF-8")
instead of
emailHeader.setHeaderVal(xxx)

(I'm in a french environment / R8.53)
Ulrich Krause
(at 01:47 on 25.05.2012)
I have slightly modified the code. You can now use the bean to send mails from the backend without passing a document

There is also a new addHTML() method, that let you add HTML line by line to the mail.



import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.faces.context.FacesContext;

import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.EmbeddedObject;
import lotus.domino.MIMEEntity;
import lotus.domino.MIMEHeader;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.Stream;

import com.ibm.commons.util.NotImplementedException;
import com.ibm.domino.xsp.module.nsf.NotesContext;
import com.ibm.xsp.model.FileRowData;
import com.ibm.xsp.model.domino.wrapped.DominoDocument;
import com.ibm.xsp.model.domino.wrapped.DominoRichTextItem;
import com.ibm.xsp.model.domino.wrapped.DominoDocument.AttachmentValueHolder;
import com.ibm.xsp.persistence.PersistedContent;

public class EMail {

private ArrayList<String> sendTo;
private ArrayList<String> ccList;
private ArrayList<String> bccList;
//UK: 25.04.2012 added contentList
private StringBuilder contentList;
private String senderEmail;
private String senderName;
private String subject;

private DominoDocument document;
private String fieldName;
//UK: 25.04.2012 modified, set default value to an empty string
//otherwise, if bannerHTML and footerHTML are not set, NULL is added to the mail document
private String bannerHTML = "";
private String footerHTML = "";

private boolean debugMode = false;

private static final Pattern imgRegExp = Pattern.compile("<img[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>");

//UK: 25.04.2012 added. The bean can be called from within another java class then
public static final String BEAN_NAME = "email"; // name of the bean
public static EMail get() {
FacesContext context = FacesContext.getCurrentInstance();
EMail bean = (EMail) context.getApplication().getVariableResolver().resolveVariable(context, BEAN_NAME);
return bean;
}

// -------------------------------------------------------------------------

public EMail() {
this.subject = "";
this.sendTo = new ArrayList<String>();
this.ccList = new ArrayList<String>();
this.bccList = new ArrayList<String>();
//UK: 25.04.2012 added
this.contentList = new StringBuilder();
}

// -------------------------------------------------------------------------

public String getSendTo() {
if (this.isDebugMode()) {
System.out.println("getSendTo() : " + this.sendTo.toString());
}
return this.sendTo.toString().replace("[", "").replace("]", "");
}

public void setSendTo(final String sendTo) {
this.sendTo.add(sendTo);
}

// -------------------------------------------------------------------------

public String getCcList() {
if (this.isDebugMode()) {
System.out.println("getCcList() : " + this.ccList.toString());
}
return this.ccList.toString().replace("[", "").replace("]", "");
}

public void setCcList(final String ccList) {
this.ccList.add(ccList);
}

// -------------------------------------------------------------------------

public String getBccList() {
if (this.isDebugMode()) {
System.out.println("getBccList() : " + this.bccList.toString());
}
return this.bccList.toString().replace("[", "").replace("]", "");
}

public void setBccList(final String bccList) {
this.bccList.add(bccList);
}

// -------------------------------------------------------------------------

public String getSenderEmail() {
return this.senderEmail;
}

public void setSenderEmail(final String senderEmail) {
this.senderEmail = senderEmail;
}

// -------------------------------------------------------------------------

public String getSenderName() {
return this.senderName;
}

public void setSenderName(final String senderName) {
this.senderName = senderName;
}

// -------------------------------------------------------------------------

public String getSubject() {
return this.subject;
}

public void setSubject(final String subject) {
this.subject = subject;
}

// -------------------------------------------------------------------------

public boolean isDebugMode() {
return this.debugMode;
}

public void setDebugMode(final boolean debugMode) {
this.debugMode = debugMode;
}

// -------------------------------------------------------------------------

private Session getCurrentSession() {
NotesContext nc = NotesContext.getCurrentUnchecked();
return (null != nc) ? nc.getCurrentSession() : null;
}

// -------------------------------------------------------------------------

private Database getCurrentDatabase() {
NotesContext nc = NotesContext.getCurrentUnchecked();
return (null != nc) ? nc.getCurrentDatabase() : null;
}

// -------------------------------------------------------------------------

public void send() throws NotesException, IOException, Exception {
Session session = getCurrentSession();
Database database = getCurrentDatabase();
if (this.isDebugMode()) {
System.out.println("Started send()");
}
if (null != session && null != database && null != this.sendTo && null != this.subject
&& null != this.senderEmail) {
try {

session.setConvertMime(false);
Document emailDocument = database.createDocument();

MIMEEntity emailRoot = emailDocument.createMIMEEntity("Body");

if (null != emailRoot) {
MIMEHeader emailHeader = emailRoot.createHeader("Reply-To");
emailHeader.setHeaderVal(this.getSenderEmail());

emailHeader = emailRoot.createHeader("Return-Path");
emailHeader.setHeaderVal(this.getSenderEmail());

final String fromSender = (null == this.getSenderName()) ? this.getSenderEmail() : "\""
+ this.getSenderName() + "\" <" + this.getSenderEmail() + ">";

emailHeader = emailRoot.createHeader("From");
emailHeader.setHeaderVal(fromSender);

emailHeader = emailRoot.createHeader("Sender");
emailHeader.setHeaderVal(fromSender);

emailHeader = emailRoot.createHeader("To");
emailHeader.setHeaderVal(this.getSendTo());

if (!this.ccList.isEmpty()) {
emailHeader = emailRoot.createHeader("CC");
emailHeader.setHeaderVal(this.getCcList());
}

if (!this.bccList.isEmpty()) {
emailHeader = emailRoot.createHeader("BCC");
emailHeader.setHeaderVal(this.getBccList());
}

emailHeader = emailRoot.createHeader("Subject");
emailHeader.setHeaderVal(this.getSubject());

MIMEEntity emailRootChild = emailRoot.createChildEntity();
if (null != emailRootChild) { //UK: 25.04.2012 modified
String boundary = System.currentTimeMillis() + "- CV2" + System.currentTimeMillis();
if (null != this.document) {
boundary = System.currentTimeMillis() + "-" + this.document.getDocumentId();
}
emailHeader = emailRootChild.createHeader("Content-Type");
emailHeader.setHeaderVal("multipart/alternative; boundary=\"" + boundary + "\"");

MIMEEntity emailChild = emailRootChild.createChildEntity();
if (null != emailChild) {
String contentAsText = "";
if (null != this.document) {
contentAsText = this.document.getRichTextItem(this.fieldName).getContentAsText();
}
Stream stream = session.createStream();
stream.writeText(contentAsText);
emailChild.setContentFromText(stream, "text/plain; charset=\"UTF-8\"", MIMEEntity.ENC_NONE);
stream.close();

emailChild = emailRootChild.createChildEntity();
stream = session.createStream();
stream.writeText(this.getHTML());
emailChild.setContentFromText(stream, "text/html; charset=\"UTF-8\"", MIMEEntity.ENC_NONE);
stream.close();
stream.recycle();
stream = null;
}

// add embedded images....
final List<FileRowData> embeddedImages = this.getEmbeddedImagesList();
if (null != embeddedImages && !embeddedImages.isEmpty()) {
if (this.isDebugMode()) {
System.out.println("Adding Embedded Images...");
}
for (FileRowData embeddedImage : embeddedImages) {
emailRootChild = emailRoot.createChildEntity();
if (null != emailRootChild && embeddedImage instanceof AttachmentValueHolder) {
InputStream is = null;
try {
String persistentName = ((AttachmentValueHolder) embeddedImage)
.getPersistentName();
String cid = ((AttachmentValueHolder) embeddedImage).getCID();
emailHeader = emailRootChild.createHeader("Content-Disposition");
emailHeader.setHeaderVal("inline; filename=\"" + persistentName + "\"");
emailHeader = emailRootChild.createHeader("Content-ID");
emailHeader.setHeaderVal("<" + cid + ">");
is = this.getEmbeddedImageStream(persistentName);
Stream stream = session.createStream();
stream.setContents(is);
emailRootChild.setContentFromBytes(stream, embeddedImage.getType(),
MIMEEntity.ENC_IDENTITY_BINARY);
if (this.isDebugMode()) {
System.out.println("Added Embedded Image : " + persistentName);
}
} catch (IOException e) {
if (this.isDebugMode()) {
System.out.println("Adding Embedded Image failed : " + e.getMessage());
}
throw e;
} finally {
if (null != is) {
is.close();
is = null;
}
}
}
}
if (this.isDebugMode()) {
System.out.println("Completed Adding Embedded Images");
}
}

if (null != this.document) { //UK: 25.04.2012 added
// add attachments....
final List<FileRowData> attachments = this.getDocument().getAttachmentList(
this.getFieldName());
if (null != attachments && !attachments.isEmpty()) {
if (this.isDebugMode()) {
System.out.println("Adding Attachments...");
}
for (FileRowData attachment : attachments) {
emailRootChild = emailRoot.createChildEntity();
if (null != emailRootChild && attachment instanceof AttachmentValueHolder) {
InputStream is = null;
try {
String persistentName = ((AttachmentValueHolder) attachment)
.getPersistentName();
String cid = ((AttachmentValueHolder) attachment).getCID();
EmbeddedObject eo = this.getDocument().getDocument().getAttachment(
persistentName);
if (null != eo) {
emailHeader = emailRootChild.createHeader("Content-Disposition");
emailHeader.setHeaderVal("attachment; filename=\"" + persistentName
+ "\"");
emailHeader = emailRootChild.createHeader("Content-ID");
emailHeader.setHeaderVal("<" + cid + ">");
is = eo.getInputStream();
Stream stream = session.createStream();
stream.setContents(is);
emailRootChild.setContentFromBytes(stream, attachment.getType(),
MIMEEntity.ENC_IDENTITY_BINARY);
if (this.isDebugMode()) {
System.out.println("Added Attachment : " + persistentName);
}
}
} catch (Exception e) {
if (this.isDebugMode()) {
System.out.println("Adding Attachment failed : " + e.getMessage());
}
throw e;
} finally {
if (null != is) {
is.close();
is = null;
}
}
}
}
if (this.isDebugMode()) {
System.out.println("Completed Adding Attachments");
}
}
}
}
}

emailDocument.send();
session.setConvertMime(true);
if (this.isDebugMode()) {
System.out.println("Completed send()");
}
} catch (NotesException e) {
if (this.isDebugMode()) {
System.out.println("Failed send() with NotesException" + e.getMessage());
}
throw e;
} catch (IOException e) {
if (this.isDebugMode()) {
System.out.println("Failed send() with IOException" + e.getMessage());
}
throw e;
} catch (Exception e) {
if (this.isDebugMode()) {
System.out.println("Failed send() with Exception" + e.getMessage());
}
throw e;
}
}
}

// -------------------------------------------------------------------------

public DominoDocument getDocument() {
return this.document;
}

public void setDocument(final DominoDocument document) {
this.document = document;
}

// -------------------------------------------------------------------------

public String getFieldName() {
return this.fieldName;
}

public void setFieldName(final String fieldName) {
this.fieldName = fieldName;
}

// -------------------------------------------------------------------------

public List<FileRowData> getEmbeddedImagesList() throws NotesException {
if (null != document && null != fieldName) {
return document.getEmbeddedImagesList(fieldName);
}
return null;
}

// -------------------------------------------------------------------------

private InputStream getEmbeddedImageStream(final String fileName) throws NotesException, IOException {
if (null != document && null != fieldName && null != fileName) {
final DominoRichTextItem drti = document.getRichTextItem(fieldName);
if (null != drti) {
final PersistedContent pc = drti.getPersistedContent(FacesContext.getCurrentInstance(), fieldName,
fileName);
if (null != pc) {
return pc.getInputStream();
}
}
}
return null;
}

// -------------------------------------------------------------------------

public String getHTML() {
StringBuffer html = new StringBuffer();
html.append(getBannerHTML());
//UK: 25.04.2012 modified
if (null != getBodyHTML()) {
html.append(getBodyHTML());
}
//UK: 25.04.2012 added
html.append(getContentHTML());
html.append(getFooterHTML());
return html.toString();
}

// -------------------------------------------------------------------------

public String getBannerHTML() {
return this.bannerHTML;
}

public void setBannerHTML(final String bannerHTML) {
this.bannerHTML = bannerHTML;
}

// -------------------------------------------------------------------------

//UK: 25.04.2012 modified
public String getContentHTML() {
if (this.isDebugMode()) {
System.out.println("Started getContentHTML()");
System.out.println(this.contentList.toString());
}
return this.contentList.toString();
}
//UK: 25.04.2012 modified
public void setContentHTML(final String contentHTML) {
this.contentList.append(contentHTML);
}

// -------------------------------------------------------------------------
//UK: 25.04.2012 added
public void addHTML(final String contentHTML) {
this.contentList.append(contentHTML);
}

// -------------------------------------------------------------------------

public String getBodyHTML() {
if (null != document && null != fieldName) {
if (this.isDebugMode()) {
System.out.println("Started getBodyHTML()");
}
final DominoRichTextItem drti = document.getRichTextItem(fieldName);
if (null != drti) {
try {
String html = drti.getHTML();
if (null != html) {
final List<FileRowData> fileRowDataList = document.getEmbeddedImagesList(fieldName);
if (null != fileRowDataList) {
final Matcher matcher = imgRegExp.matcher(html);
while (matcher.find()) {
String src = matcher.group();
final String srcToken = "src=\"";
final int x = src.indexOf(srcToken);
final int y = src.indexOf("\"", x + srcToken.length());
final String srcText = src.substring(x + srcToken.length(), y);
for (FileRowData fileRowData : fileRowDataList) {
final String srcImage = fileRowData.getHref();
final String cidImage = ((AttachmentValueHolder) fileRowData).getCID();
if (srcText.endsWith(srcImage)) {
final String newSrc = src.replace(srcText, "cid:" + cidImage);
html = html.replace(src, newSrc);
if (this.isDebugMode()) {
System.out.println("CID referenced image: " + srcText + " with CID:"
+ cidImage);
}
}
}
}
}
}
if (this.isDebugMode()) {
System.out.println("Completed getBodyHTML() : " + html);
}
return html;
} catch (Exception e) {
if (this.isDebugMode()) {
System.out.println("Failed getBodyHTML() : " + e.getMessage());
}
}
}
}
return "";
}

@Deprecated
public void setBodyHTML(final String bodyHTML) throws NotImplementedException {
if (this.isDebugMode()) {
System.out.println("Method setBodyHTML(string) is not permitted");
}
throw new NotImplementedException();
}

// -------------------------------------------------------------------------

public String getFooterHTML() {
return this.footerHTML;
}

public void setFooterHTML(final String footerHTML) {
this.footerHTML = footerHTML;
}

// -------------------------------------------------------------------------

} // end EmailBean