-
-
Save WaltRiceJr/f43811b0f94603e34fd2 to your computer and use it in GitHub Desktop.
Fixed MIME closing boundary for multipart/alternative section
This file contains hidden or 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
<cfparam name="attributes.type" default=""> | |
<!--- Original from http://cflove.org/2013/02/using-amazon-ses-api-sendrawemail-with-coldfusion.cfm ---> | |
<!--- Modified by [email protected] ---> | |
<cfswitch expression="#thisTag.ExecutionMode#"> | |
<cfcase value="start"> | |
</cfcase> | |
<cfdefaultcase> | |
<!--- *************************************************** ---> | |
<!--- Basic Errors ---> | |
<!--- *************************************************** ---> | |
<cfif not StructKeyExists(attributes,'from')> | |
<cfthrow message="From attribute is required"> | |
</cfif> | |
<cfif not StructKeyExists(attributes,'to')> | |
<cfthrow message="TO attribute is required"> | |
</cfif> | |
<cfif not StructKeyExists(attributes,'Key')> | |
<cfthrow message="Key attribute is required." detail="Please provide AWS Access Key ID"> | |
</cfif> | |
<cfif not StructKeyExists(attributes,'SecretKey')> | |
<cfthrow message="SecretKey attribute is required." detail="Please provide AWS Secret Access Key"> | |
</cfif> | |
<cfset attributes.multipart = false> | |
<cfset attributes.alternative = false> | |
<cfset attributes.boundary = "_#CreateUUID()#_"> | |
<cfset attributes.boundary2 = "_#CreateUUID()#_"> | |
<cfset attributes.mail = ArrayNew(1)> | |
<!--- *************************************************** ---> | |
<!--- Create Header Values ---> | |
<!--- *************************************************** ---> | |
<cfset this.header = ArrayNew(1)> | |
<cfset ArrayAppend(this.header,"From: #trim(attributes.from)#")> | |
<cfset ArrayAppend(this.header,"To: #trim(ListChangeDelims(attributes.to,',',',;'))#")> | |
<cfset attributes.deliverto = attributes.to> | |
<cfif StructKeyExists(attributes,'cc')> | |
<cfset ArrayAppend(this.header,"CC: #trim(ListChangeDelims(attributes.cc,',',',;'))#")> | |
<cfset attributes.deliverto = ListAppend(attributes.deliverto,attributes.cc)> | |
</cfif> | |
<cfif StructKeyExists(attributes,'bcc')> | |
<cfset ArrayAppend(this.header,"BCC: #trim(ListChangeDelims(attributes.bcc,',',',;'))#")> | |
<cfset attributes.deliverto = ListAppend(attributes.deliverto,attributes.bcc)> | |
</cfif> | |
<cfif StructKeyExists(attributes,'replyto')> | |
<cfset ArrayAppend(this.header,"Reply-To: #trim(attributes.replyto)#")> | |
</cfif> | |
<cfif StructKeyExists(attributes,'priority') and val(attributes.priority)> | |
<cfset ArrayAppend(this.header,"Priority: #attributes.priority#")> | |
</cfif> | |
<cfif StructKeyExists(attributes,'returnpath')> | |
<cfset ArrayAppend(this.header,"Return-Path: #attributes.returnpath#")> | |
</cfif> | |
<!--- *************************************************** ---> | |
<!--- Add Custom Header Values ---> | |
<!--- *************************************************** ---> | |
<cfif IsDefined('thisTag.AssocAttribs')> | |
<cfloop from="1" to="#ArrayLen(thisTag.AssocAttribs)#" index="i"> | |
<cfset this.attr = thisTag.AssocAttribs[i]> | |
<cfif StructKeyExists(this.attr,'name')> | |
<cfparam name="this.attr.value" default=""> | |
<cfset ArrayAppend(this.header,"#this.attr.name#: #trim(this.attr.value)#")> | |
</cfif> | |
<!--- if we come across an attachment or multipart/alternative content ---> | |
<cfif StructKeyExists(this.attr,'alternative') or StructKeyExists(this.attr,'attachment')> | |
<!--- this will be a multipart/mixed message ---> | |
<cfset attributes.multipart = true> | |
</cfif> | |
</cfloop> | |
</cfif> | |
<cfset ArrayAppend(this.header,"Subject: #trim(attributes.subject)#")> | |
<cfset ArrayAppend(this.header,"MIME-Version: 1.0")> | |
<cfswitch expression="#attributes.type#"> | |
<cfcase value="html"> | |
<cfset attributes.type = "text/html"> | |
</cfcase> | |
<cfdefaultcase> | |
<cfset attributes.type = "text/plain"> | |
</cfdefaultcase> | |
</cfswitch> | |
<!--- set multipart or non-multipart content type headers ---> | |
<cfif attributes.multipart EQ true> | |
<cfset ArrayAppend(this.header,"Content-Type: multipart/mixed; boundary=#attributes.boundary##chr(10)#")> | |
<cfelse> | |
<cfset ArrayAppend(this.header,"Content-Type: #attributes.type#; charset=UTF-8")> | |
<cfset ArrayAppend(this.header,"Content-Transfer-Encoding: 7bit#chr(10)#")> | |
</cfif> | |
<cfset ArrayAppend(attributes.mail, ArrayToList(this.header,chr(10)) )> | |
<cfset StructDelete(this,'header')> | |
<cfif attributes.multipart EQ true> | |
<cfset ArrayAppend(attributes.mail, '#chr(10)#Your email client does not support MultiPart messages.#chr(10)#' )> | |
</cfif> | |
<!--- *************************************************** ---> | |
<!--- multipart/alternative ---> | |
<!--- *************************************************** ---> | |
<cfif attributes.multipart EQ true> | |
<cfloop from="1" to="#ArrayLen(thisTag.AssocAttribs)#" index="i"> | |
<cfset this.attr = thisTag.AssocAttribs[i]> | |
<cfif StructKeyExists(this.attr,'alternative')> | |
<cfif attributes.alternative EQ false> | |
<cfset attributes.alternative = true> | |
<cfset ArrayAppend(attributes.mail, '#chr(10)#--#attributes.boundary#' )> | |
<cfset ArrayAppend(attributes.mail, "Content-Type: multipart/alternative; boundary=#attributes.boundary2#")> | |
</cfif> | |
<cfset ArrayAppend(attributes.mail, '#chr(10)#--#attributes.boundary2#' )> | |
<cfset ArrayAppend(attributes.mail, ArrayToList(this.attr.alternative,chr(10)) )> | |
</cfif> | |
</cfloop> | |
<cfif attributes.alternative EQ true> | |
<cfset ArrayAppend(attributes.mail,'#chr(10)#--#attributes.boundary2#--' )> | |
</cfif> | |
</cfif> | |
<!--- *************************************************** ---> | |
<!--- add text content ---> | |
<!--- *************************************************** ---> | |
<cfif attributes.alternative EQ false AND len(trim(thisTag.GeneratedContent))> | |
<cfif attributes.multipart EQ true> | |
<cfset ArrayAppend(attributes.mail,'#chr(10)#--#attributes.boundary#' )> | |
<cfset ArrayAppend(attributes.mail,'Content-Type: #attributes.type##chr(10)#')> | |
</cfif> | |
<cfset ArrayAppend(attributes.mail,trim(thisTag.GeneratedContent))> | |
</cfif> | |
<!--- *************************************************** ---> | |
<!--- add attachments and final boundary ---> | |
<!--- *************************************************** ---> | |
<cfif attributes.multipart EQ true> | |
<cfloop from="1" to="#ArrayLen(thisTag.AssocAttribs)#" index="i"> | |
<cfset this.attr = thisTag.AssocAttribs[i]> | |
<cfif StructKeyExists(this.attr,'attachment')> | |
<cfset ArrayAppend(attributes.mail,'#chr(10)#--#attributes.boundary#' )> | |
<cfset ArrayAppend(attributes.mail, ArrayToList(this.attr.attachment,chr(10)) )> | |
</cfif> | |
</cfloop> | |
<cfset ArrayAppend(attributes.mail,'#chr(10)#--#attributes.boundary#--' )> | |
</cfif> | |
<!--- *************************************************** ---> | |
<!--- Remove duplicate email address ---> | |
<!--- *************************************************** ---> | |
<cfset this.deliverto = StructNew()> | |
<cfloop list="#attributes.deliverto#" index="i" delimiters=",;"> | |
<cfset this.deliverto[trim(i)] = ''> | |
</cfloop> | |
<cfset attributes.deliverto = StructKeyList(this.deliverto)> | |
<!--- *************************************************** ---> | |
<!--- Calling AWS ---> | |
<!--- *************************************************** ---> | |
<cfset this.date = DateAdd('s',GetTimeZoneInfo().UTCTotalOffset,now()) /> | |
<cfset this.date = "#DateFormat(this.date, 'ddd, dd mmm yyyy')# #timeFormat(this.date,'HH:mm:ss')# GMT" /> | |
<cfset this.Signature = toBase64(HMAC_SHA256(this.date,attributes.SecretKey)) /> | |
<cfset this.Authoriz = "AWS3-HTTPS AWSAccessKeyId=#attributes.Key#, Algorithm=HmacSHA256, Signature=#this.Signature#" /> | |
<cfhttp url="https://email.us-east-1.amazonaws.com/" method="post" result="result"> | |
<cfhttpparam type="header" name="X-Amzn-Authorization" value="#this.Authoriz#" /> | |
<cfhttpparam type="header" name="Date" value="#this.date#" /> | |
<cfhttpparam type="formfield" name="Action" value="SendRawEmail" /> | |
<cfset count = 1> | |
<cfloop list="#attributes.deliverto#" index="i"> | |
<cfhttpparam type="formfield" name="Destinations.members.#count#" value="#i#" /> | |
<cfset count = 1+count> | |
</cfloop> | |
<!--- don't include the source field, so the Return-Path: header is honored for bounces ---> | |
<!--- <cfhttpparam type="formfield" name="Source" value="#trim(attributes.from)#" /> ---> | |
<cfhttpparam type="formfield" name="RawMessage.Data" value="#ToBase64(trim(ArrayToList(attributes.mail,chr(10))))#" /> | |
</cfhttp> | |
<cfset this.MessageId = ""> | |
<cfif StructKeyExists(result,'Filecontent') and IsXML(result.Filecontent)> | |
<cfif listfirst(result.Statuscode,' ') eq '200'> | |
<cfset this.MessageId = XMLParse(result.Filecontent).SendRawEmailResponse.SendRawEmailResult.MessageId.XmlText> | |
<cfelse> | |
<cfset this.MessageId = 'ERROR: '& XMLParse(result.Filecontent).ErrorResponse.Error.Message.XmlText> | |
</cfif> | |
</cfif> | |
<cfset caller.MessageId = trim(this.MessageId)> | |
<!---- ************************************************************ ---> | |
<!---- Helpers ---> | |
<!---- ************************************************************ ---> | |
<cffunction name="HMAC_SHA256" returntype="binary" access="public" output="no"> | |
<cfargument name="signMessage" type="string" required="true" /> | |
<cfargument name="signKey" type="string" required="true" /> | |
<cfset local.jMsg = JavaCast("string",arguments.signMessage).getBytes("iso-8859-1") /> | |
<cfset local.jKey = JavaCast("string",arguments.signKey).getBytes("iso-8859-1") /> | |
<cfset local.key = createObject("java","javax.crypto.spec.SecretKeySpec") /> | |
<cfset local.mac = createObject("java","javax.crypto.Mac") /> | |
<cfset local.key = local.key.init(local.jKey,"HmacSHA256") /> | |
<cfset local.mac = local.mac.getInstance(local.key.getAlgorithm()) /> | |
<cfset local.mac.init(local.key) /> | |
<cfset local.mac.update(local.jMsg) /> | |
<cfreturn local.mac.doFinal() /> | |
</cffunction> | |
<cfset thisTag.GeneratedContent = "" /> | |
</cfdefaultcase> | |
</cfswitch> |
This file contains hidden or 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
<cfparam name="attributes.disposition" default="attachment"> | |
<!--- http://cflove.org/2013/02/using-amazon-ses-api-sendrawemail-with-coldfusion.cfm ---> | |
<cfswitch expression="#thisTag.ExecutionMode#"> | |
<cfcase value="start"> | |
<cfassociate basetag="cf_mail"> | |
<cfif StructKeyExists(attributes,'file')> | |
<!--- *************************************************** ---> | |
<!--- File Attachment ---> | |
<!--- *************************************************** ---> | |
<cfif FileExists(attributes.file)> | |
<cfset attributes.attachment = ArrayNew(1)> | |
<cfset this.info = GetFileInfo(attributes.file)> | |
<cfparam name="attributes.type" default="#getPageContext().getServletContext().getMimeType(attributes.file)#"> | |
<cfset ArrayAppend(attributes.attachment,'Content-Type: #attributes.type#; name="#this.info.name#";')> | |
<cfset ArrayAppend(attributes.attachment,'Content-Disposition: inline; filename="#this.info.name#"; size=#this.info.size#;')> | |
<cfif StructKeyExists(attributes,'contentID')> | |
<cfset ArrayAppend(attributes.attachment,"Content-ID: <#attributes.contentID#>")> | |
</cfif> | |
<cfset ArrayAppend(attributes.attachment,"Content-Transfer-Encoding: base64#chr(10)#")> | |
<cfset ArrayAppend(attributes.attachment,ToBase64( FileReadBinary(attributes.file) ))> | |
</cfif> | |
</cfif> | |
</cfcase> | |
<cfdefaultcase> | |
</cfdefaultcase> | |
</cfswitch> |
This file contains hidden or 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
<cfparam name="attributes.type"> | |
<cfswitch expression="#thisTag.ExecutionMode#"> | |
<cfcase value="start"> | |
</cfcase> | |
<cfdefaultcase> | |
<cfassociate basetag="cf_mail"> | |
<cfswitch expression="#attributes.type#"> | |
<cfcase value="html"> | |
<cfset attributes.type = "text/html"> | |
</cfcase> | |
<cfdefaultcase> | |
<cfset attributes.type = "text/plain"> | |
</cfdefaultcase> | |
</cfswitch> | |
<cfset attributes.alternative = ArrayNew(1)> | |
<cfset ArrayAppend(attributes.alternative, 'Content-Type: #attributes.type#; charset=UTF-8')> | |
<cfset ArrayAppend(attributes.alternative, 'Content-Transfer-Encoding: 7bit#chr(10)#')> | |
<cfset ArrayAppend(attributes.alternative, thisTag.GeneratedContent)> | |
</cfdefaultcase> | |
</cfswitch> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Forked and revised to add multipart/alternative content, and to send a non-multipart message if there are no attachments or alternative content sections.