Geo
Geo

Reputation: 3200

ColdFusion and AWS SES

I am trying to setup my CF server with Amazon's SES but I guess I am doing something wrong...

This is what I did so far

• Created credentials from my AWS console
• Added the necessary settings (server, port, user/pass) in my CF admin
• Created a test script
• No errors of any sort appeared
• No emails received and based on my AWS SES console nothing was sent out.

Anyone ever used this service before with CF and can point me to the right direction I will appreciate it.

Upvotes: 1

Views: 1407

Answers (1)

Eric Almond
Eric Almond

Reputation: 21

The below code does not use the CFMail tag. It allows for sending raw formatted emails, calendar invites, etc... using a CFHTTP POST to AWS SES without the constraints of the CFMAIL tag. If you want to use the CFMail TAG, see the AWS instructions for configuring an SMTP server.

Grab the following before implementing the below code:

  1. Refer to <cfLove/> Sending emails with Amazon SES API SendRawEmail in ColdFusion to construct raw email message

  2. Reference to Leigh Sv4Util.cfc for AWS v4 Signing

 NOTE: in the V4 Signing cfc -- CF16 returns the AMZDate as +0000
 for zulu. Find AMZDate (2 places) change to LEFT(AMZDate, 15) & "Z" to force
 the to end in Z -- 20200930T222905+0000 -> 0200930T222905Z.
  1. Refer to AWS for Sample SES Post

The sample code below assumes that attributes.mail was formatted from the sample code from CFLove and you are using the Sv4Util.cfc for signing.

<!--- This is sample code for send to AWS SES as Raw Data Send post --->



<!--- Init Signing CFC --->
<cfset LocalVar.s4 = CreateObject('component', 'Sv4Util.cfc').init(
  accessKeyId = attributes.AWSKey
, secretAccessKey = attributes.AWSSecretKey
, defaultRegionName = attributes.AWSRegion
, defaultServiceName = "ses"
)>


<!--- 
  Refer to https://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-ses-api-requests.html 
  AWS Post Example Requirements
   - Action
   - Destinations.members.?
   - Source
   - RawMessage.Data
--->

<cfset PL           = {}>
<cfset PL['Action'] = "SendRawEmail">
   

<!--- List of Email Addresses --->
<cfset count = 1>
<cfloop list="#attributes.deliverto#" index="i">
       <cfset PL["Destinations.members.#count#"] = i>
       <cfset count = count + 1>
</cfloop>

<!--- From --->
<cfset PL["Source"]          = trim(attributes.from)>

<!--- The RAW MESSAGE -- Must be encoded due to BASE64 ending with an = --->
<cfset PL["RawMessage.Data"] = URLEncodedFormat(ToBase64(trim(ArrayToList(attributes.mail,chr(10)))))>


<!--- Build URL format string for posting the above struct (PLS) --->
<cfset PLS = ''>
<cfloop list="#ListSort(structKeyList(PL), 'text', 'asc')#" index="i" >
       <cfset PLS = ListAppend(PLS,  i & "=" & PL[i], "&")>
</cfloop>

<!--- Sign Request --->
<cfset LocalVar.Signing = LocalVar.s4.generateSignatureData(  
                          requestMethod = 'POST' <!--- UPPER CASE --->
                        , hostName = 'email.#attributes.AWSRegion#.amazonaws.com'
                        , requestURI = ''
                        , requestBody = PLS
                        , requestHeaders = {"content-type":"application/x-www-form-urlencoded"}
                        , requestParams = {}
                        )>


<!--- Do POST to AWS --->
<!--- Required in POST 
      - x-amz-content-sha256
      - Authorization
      - x-amz-date
      - content-type
      - body
--->      
<cfhttp url="https://email.#attributes.AWSRegion#.amazonaws.com" method="post" result="result">  
   <cfhttpparam type="header" name="x-amz-content-sha256"    value="#LocalVar.Signing.RequestPayLoad#" />
       <cfhttpparam type="header" name="Authorization"        value="#LocalVar.Signing.authorizationHeader#" />
       <cfhttpparam type="header" name="x-amz-date" value="#LocalVar.Signing.AMZDate#" />
       <cfhttpparam type="header" name="content-type" value="application/x-www-form-urlencoded" />
       <cfhttpparam type="body" value="#PLS#" />        
</cfhttp>

Upvotes: 2

Related Questions