Last active
October 31, 2015 08:26
-
-
Save katio/95a673a3d14a4147ed0c to your computer and use it in GitHub Desktop.
Class to generate HTML e-mail messages from IBM Domino XPages SSJS by Mark Leusink (Twitter @markleusink). This is a small modification to solve a problem when you use the mime header "To" and the length in characters of a recipient is greater than or equal to 79, as can be the case in a long canonical name. This is solved here using the item "S…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Took from: | |
* http://openntf.org/XSnippets.nsf/snippet.xsp?id=create-html-mails-in-ssjs-using-mime | |
* | |
* Class to generate HTML e-mail messages from SSJS | |
* | |
* Author: Mark Leusink (m.leusink@gmail.com) | |
* | |
* Version: 2012-11-20 | |
* | |
* History: | |
* 2011-12-07 initial version | |
* 2011-12-08 added support for inline images | |
* 2011-12-19 fixed wrong method name in usage samples | |
* 2012-11-20 added code to set JSON contents | |
changed setHeaderVal() to addValText() to set the sender with the correct encoding | |
* 2013-01-08 small bug fix in _addAttachments() function | |
* 2013-11-20 option to set a different reply to address (thanks Ken Behrens!) | |
* 2014-01-02 changed setHeaderVal() to addValText() for better Subject header encoding (thanks Egor Margineanu!) | |
* 2014-03-05 modification to solve a problem when you use the mime header "To" and the length in characters of a recipient is greater than or equal to 79, as can be the case in a long canonical name. This is solved here using the item "SendTo" in the NotesDocument instead of the mime header. @Katio, @Abrupto. | |
* | |
* Usage example (simple): | |
* | |
* var mail = new HTMLMail(); | |
* mail.setTo( "m.leusink@gmail.com") | |
* mail.setSubject("Your notification"); | |
* mail.addHTML("<b>Hello world</b>"); | |
* mail.send(); | |
* | |
* Usage example (extended): | |
* | |
* var mail = new HTMLMail(); | |
* mail.setTo( "m.leusink@gmail.com") | |
* mail.setCC( ["user@domain.com", "anotheruser@domaino.com"] ); | |
* mail.setBCC( "user3@domaino.com"); | |
* mail.setSubject("Your notification"); | |
* mail.addHTML("<h1>Hi!</h1>"); | |
* mail.addHTML("<table><tbody><tr><td>contents in a table here</td></tr></tbody></table>"); | |
* mail.addDocAttachment( "DC9126E84C59093FC1257953003C13E6", "jellyfish.jpg") | |
* mail.addFileAttachment( "c:/temp/report.pdf"); | |
* mail.setSender("m.leusink@gmail.com", "Mark Leusink"); | |
* mail.send(); | |
*/ | |
var HTMLMail = function() { | |
this._to = []; | |
this._cc = []; | |
this._bcc = []; | |
this._fromEmail = null; | |
this._fromName = null; | |
this._reply = []; | |
this._subject = ""; | |
this._contentsHTML = []; | |
this._contentsText = []; | |
this._contentsJSON = null; | |
this._attachments = []; | |
/* | |
* set "to", "CC" and/ or "BCC" addresses | |
* to = string or array of strings containing either e-mail addresses or Notes names | |
*/ | |
this.setTo = function( to:String ) { | |
//if (typeof to === "string") { to = [to] }; | |
if (typeof to === "string") { to = to.split(",") }; | |
this._to = to; | |
}; | |
this.setCC = function( to:String ) { | |
//if (typeof to === "string") { to = [to] }; | |
if (typeof to === "string") { to = to.split(",") }; | |
this._cc = to; | |
} | |
this.setBCC = function( to:String ) { | |
//if (typeof to === "string") { to = [to] }; | |
if (typeof to === "string") { to = to.split(",") }; | |
this._bcc = to; | |
} | |
this.setReply = function( to:String ) { | |
if (typeof to === "string") { to = [to] }; | |
this._reply = to; | |
} | |
//set the subject of the message | |
this.setSubject = function( subject:String ) { | |
this._subject = subject; | |
} | |
this.addHTML = function( content:String ) { | |
this._contentsHTML.push(content); | |
//create a plain text representation of the HTML contents: | |
//remove all HTML tags and add a line break | |
var plainText = content.replace( /<[a-zA-Z\/][^>]*>/g, ""); | |
this._contentsText.push( plainText + "\n" ); | |
} | |
this.addText = function( content:String ) { | |
this._contentsText.push( content ); | |
//add html part by replacing all line breaks with a <br /> tag | |
var htmlText = @ReplaceSubstring(content, @Char(13), "<br />"); | |
this._contentsHTML.push(htmlText); | |
} | |
this.setJSON = function( content:String ) { | |
this._contentsJSON = content; | |
} | |
//set the sender of the message | |
//fromEmail is required, fromName is optional | |
this.setSender = function( fromEmail:String, fromName:String ) { | |
if ( fromEmail.length > 0 ) { | |
this._fromEmail = fromEmail; | |
this._fromName = fromName; | |
} | |
} | |
/* | |
* add an attachment on a document to the mail message | |
* | |
* unid (string) = unid of the document in the current database that contains the file to be send | |
* fileName (string) = well... guess... | |
* inlineImage (boolean, defaults to false): if set to true, this image is marked as "inline" (used in the content) | |
*/ | |
this.addDocAttachment = function( unid:String , fileName:String, inlineImage:boolean) { | |
var contentId = @Unique().toLowerCase(); | |
if (typeof inlineImage=="undefined") { inlineImage = false; } | |
this._attachments.push( { type : "document", unid: unid, fileName : fileName, contentId : contentId, inline : inlineImage } ); | |
return "cid:" + contentId; | |
} | |
/* | |
* add an OS file to the mail message | |
* | |
* path (string): path of the file on the server | |
* fileName (string): fileName of the file | |
* inlineImage (boolean, defaults to false): if set to true, this image is marked as "inline" (used in the content) | |
*/ | |
this.addFileAttachment = function( path:String, fileName:String, inlineImage:boolean ) { | |
var contentId = @Unique().toLowerCase(); | |
if (typeof inlineImage=="undefined") { inlineImage = false; } | |
this._attachments.push( { type : "file", path : path, fileName : fileName, contentId : contentId, inline : inlineImage } ); | |
return "cid:" + contentId; | |
} | |
this.send = function() { | |
session.setConvertMime(false); | |
var doc:NotesDocument = database.createDocument(); | |
doc.replaceItemValue("RecNoOutOfOffice", "1"); //no replies from out of office agents | |
var mimeRoot:NotesMIMEEntity = doc.createMIMEEntity("Body"); | |
var mimeHeader:NotesMIMEHeader; | |
/* Not TO, CC, & BCC as mime header anymore. | |
if (this._to.length>0) { | |
mimeHeader = mimeRoot.createHeader("To"); | |
mimeHeader.setHeaderVal( this._to.join(",")); | |
} | |
if (this._cc.length>0) { | |
mimeHeader = mimeRoot.createHeader("CC"); | |
mimeHeader.setHeaderVal( this._cc.join(",")); | |
} | |
if (this._bcc.length>0) { | |
mimeHeader = mimeRoot.createHeader("BCC"); | |
mimeHeader.setHeaderVal( this._bcc.join(",")); | |
}*/ | |
//set subject | |
mimeHeader = mimeRoot.createHeader("Subject"); | |
mimeHeader.addValText(this._subject, "UTF-8"); | |
var mimeBoundary = doc.getUniversalID().toLowerCase(); | |
var stream:NotesStream; | |
var mimeEntity:NotesMIMEEntity; | |
//create text/alternative directive: text/plain and text/html part will be childs of this entity | |
var mimeRootChild = mimeRoot.createChildEntity(); | |
mimeHeader = mimeRootChild.createHeader("Content-Type"); | |
mimeHeader.setHeaderVal( "multipart/alternative; boundary=\"" + mimeBoundary + "\"" ); | |
//create plain text part | |
if (this._contentsText.length>0) { | |
mimeEntity = mimeRootChild.createChildEntity(); | |
stream = session.createStream(); | |
stream.writeText(this._contentsText.join("")); | |
mimeEntity.setContentFromText(stream, "text/plain; charset=\"UTF-8\"", NotesMIMEEntity.ENC_NONE); | |
stream.close(); | |
} | |
//create HTML part | |
if (this._contentsHTML.length>0) { | |
mimeEntity = mimeRootChild.createChildEntity(); | |
stream = session.createStream(); | |
stream.writeText(this._contentsHTML.join("\n")); | |
mimeEntity.setContentFromText(stream, "text/html; charset=\"UTF-8\"", NotesMIMEEntity.ENC_NONE); | |
stream.close(); | |
} | |
//create embedded JSON part | |
if (this._contentsJSON) { | |
mimeEntity = mimeRootChild.createChildEntity(); | |
stream = session.createStream(); | |
var json = "{\"url\" : \"" + this._contentsJSON + "\"}\n"; | |
stream.writeText(json); | |
mimeEntity.setContentFromText(stream, "application/embed+json; charset=\"UTF-8\"", NotesMIMEEntity.ENC_NONE); | |
stream.close(); | |
} | |
//add attachments | |
this._addAttachments(mimeRoot); | |
//set the sender | |
this._setSender(mimeRoot); | |
//send the e-mail | |
doc.replaceItemValue("SendTo", this._to) | |
doc.replaceItemValue("CopyTo", this._cc) | |
doc.replaceItemValue("BlindCopyTo", this._bcc) | |
doc.send(); | |
session.setConvertMime(true); | |
}; | |
//retrieve a file from a document that should be added to the message | |
this._addAttachments = function( mimeRoot:NotesMIMEEntity ) { | |
var streamFile:NotesStream = null; | |
//process document attachments | |
for (var i=0; i<this._attachments.length; i++) { | |
var att = this._attachments[i]; | |
is = null; | |
//get content type for file | |
var contentType = "application/octet-stream"; | |
var extension = @LowerCase(@RightBack( att.fileName, ".")); | |
if (extension=="gif") { | |
contentType = "image/gif"; | |
} else if (extension=="jpg" || extension=="jpeg") { | |
contentType = "image/jpeg"; | |
} else if (extension=="png") { | |
contentType = "image/png"; | |
} | |
contentType += "; name=\"" + att.fileName + "\""; | |
var eo:NotesEmbeddedObject = null; | |
var is = null; | |
try { | |
if ( att.type.equals("document")) { | |
//retrieve the document containing the attachment to send from the current database | |
var docFile:NotesDocument = database.getDocumentByUNID( att.unid ); | |
if (null != docFile) { | |
eo = docFile.getAttachment(att.fileName); | |
is = eo.getInputStream(); | |
} | |
} else { | |
is = new java.io.FileInputStream( att.path + att.fileName ); | |
} | |
if (is != null) { | |
var mimeChild = mimeRoot.createChildEntity(); | |
var mimeHeader = mimeChild.createHeader("Content-Disposition"); | |
if (att.inline) { | |
mimeHeader.setHeaderVal("inline; filename=\"" + att.fileName + "\""); | |
} else { | |
mimeHeader.setHeaderVal("attachment; filename=\"" + att.fileName + "\""); | |
} | |
mimeHeader = mimeChild.createHeader("Content-ID"); | |
mimeHeader.setHeaderVal( "<" + att.contentId + ">" ); | |
streamFile = session.createStream(); | |
streamFile.setContents(is); | |
mimeChild.setContentFromBytes(streamFile, contentType, NotesMIMEEntity.ENC_IDENTITY_BINARY); | |
} | |
} catch (e) { | |
print("error while adding attachment: " + e.toString()); | |
} finally { | |
if (is != null) { is.close(); } | |
if (eo != null) { eo.recycle(); } | |
} | |
} | |
} | |
//change the sender of an e-mail | |
this._setSender = function( mimeRoot:NotesMIMEEntity ) { | |
if (this._fromEmail==null) { | |
return; | |
} | |
var mimeHeader:NotesMIMEHeader = null; | |
//set reply address | |
if (this._reply.length>0) { | |
mimeHeader = mimeRoot.createHeader("Reply-To"); | |
mimeHeader.setHeaderVal( this._reply.join(",")); | |
} else { | |
mimeHeader = mimeRoot.createHeader("Reply-To"); | |
mimeHeader.setHeaderVal(this._fromEmail); | |
} | |
mimeHeader = mimeRoot.createHeader("Return-Path"); | |
mimeHeader.setHeaderVal(this._fromEmail); | |
if (this._fromName==null) { | |
mimeHeader = mimeRoot.createHeader("From"); | |
mimeHeader.setHeaderVal(this._fromEmail); | |
mimeHeader = mimeRoot.createHeader("Sender"); | |
mimeHeader.setHeaderVal(this._fromEmail); | |
} else { | |
mimeHeader = mimeRoot.createHeader("From"); | |
mimeHeader.addValText( "\"" + this._fromName + "\" <" + this._fromEmail + ">", "UTF-8" ); | |
mimeHeader = mimeRoot.createHeader("Sender"); | |
mimeHeader.addValText( "\"" + this._fromName + "\" <" + this._fromEmail + ">", "UTF-8" ); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment