Skip to content

Instantly share code, notes, and snippets.

@cflove
Last active December 13, 2015 20:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cflove/4967768 to your computer and use it in GitHub Desktop.
Save cflove/4967768 to your computer and use it in GitHub Desktop.
To accept AWS SNS calls originating from SES mail bounces and complains. http://cflove.org/2013/02/track-amazon-aws-ses-email-bounce-and-complains-with-coldfusion.cfm
<cfset sns = getHttpRequestData()>
<!---<cfif YesNoFormat(fromSNS(cgi.REMOTE_ADDR))>--->
<cfset sns = DeserializeJSON(sns.content)>
<!---- ****************************************************************** --->
<!---- if subsribe request, acccept it (remove after first use) --->
<!---- ****************************************************************** --->
<cfif StructKeyExists(sns,'SubscribeURL')>
<cfhttp charset="utf-8" method="get" resolveurl="no" url="#sns.SubscribeURL#">
</cfif>
<!---- ****************************************************************** --->
<!---- Mail Bounce & Complains. sns.type, sns.subtype and sns.Recipients --->
<!---- ****************************************************************** --->
<cfif StructKeyExists(sns,'Message') and IsJSON(sns.Message)>
<cfset sns.Message = DeserializeJSON(sns.Message)>
<cfif StructKeyExists(sns.Message,'complaint')>
<cfset sns.Recipients = sns.Message.complaint.complainedRecipients>
<cfset sns.subtype = sns.Message.complaint.complaintFeedbackType>
<cfset sns.type = "complaint">
</cfif>
<cfif StructKeyExists(sns.Message,'bounce')>
<cfset sns.Recipients = sns.Message.bounce.bouncedRecipients>
<cfset sns.subtype = sns.Message.bounce.bounceSubType>
<cfswitch expression="#sns.Message.bounce.bounceType#">
<cfcase value="Transient">
<cfset sns.type = "Our_Of_Office">
</cfcase>
<cfcase value="Permanent">
<cfset sns.type = "bounce">
</cfcase>
</cfswitch>
</cfif>
<!---- ****************************************************************** --->
<!---- Update The Dateabase --->
<!---- ****************************************************************** --->
<!--- update Mytable ... where messageid = '#sns.Message.mail.messageId#' --->
</cfif>
<!---</cfif> --->
<!---- ****************************************************************** --->
<!---- Helpers --->
<!---- ****************************************************************** --->
<cffunction name="fromSNS" returntype="boolean" output="yes">
<cfargument name="ip" type="string" required="yes">
<cfset local.iplist ="207.171.167.101,207.171.172.6,207.171.167.25,207.171.167.26,72.21.196.64/29,72.21.198.64/29,72.21.198.72,72.21.217.0/24,204.246.160.32/28,204.246.162.32/28,54.240.198.0/24,205.251.233.32/28,205.251.233.48/29,205.251.233.160/28,205.251.233.176/29,205.251.234.32/28,87.238.84.64/29,87.238.80.64/29,54.240.197.0/24,203.83.220.24/29,203.83.220.152/29,54.240.199.0/24,27.0.1.24/29,27.0.1.152/29,54.240.200.0/24,177.72.241.96/28,177.72.241.112/28,177.72.241.160/28,177.72.241.176/28,177.72.242.96/28,177.72.242.112/28,177.72.241.16/29,177.72.242.16/29">
<cfset local.out = "false">
<cfloop list="#local.iplist#" index="local.i">
<cfif find('/',local.i)>
<cfif YesNoFormat(testCidrRange(local.i,arguments.ip))>
<cfset local.out = "true">
<cfbreak>
</cfif>
<cfelse>
<cfif not compare(local.i,arguments.ip)>
<cfset local.out = "true">
<cfbreak>
</cfif>
</cfif>
</cfloop>
<cfreturn local.out>
</cffunction>
<!--- http://tech.groups.yahoo.com/group/fusebox5/message/2089 --->
<cffunction name="testCidrRange" output="false" returntype="boolean">
<cfargument name="CIDR" required="true" type="string">
<cfargument name="TestIP" required="true" type="string">
<cfset var CIDRParts = ListToArray(arguments.CIDR, "/")>
<cfset var CIDRAddress = ListToArray(CIDRParts[1], ".")>
<cfset var CIDRMask = CIDRParts[2]>
<cfset var TestIPAddress = ListToArray(arguments.TestIP, ".")>
<cfset var CIDRRealAddress = 0>
<cfset var CIDRRealMask = 0>
<cfset var TestRealAddress = 0>
<cfset var TestIPA = 0>
<cfset var TestIPB = 0>
<cfset var CidrA = 0>
<cfset var CidrB = 0>
<cfset var MaskA = 0>
<cfset var MaskB = 0>
<cfset var x = "">
<!--- Get the integer the CIDR core address represents --->
<cfset CIDRRealAddress = CIDRAddress[4]>
<cfset CIDRRealAddress = CIDRRealAddress
+ CIDRAddress[3] * 256> <!--- 2^8 --->
<cfset CIDRRealAddress = CIDRRealAddress
+ CIDRAddress[2] * 65536> <!--- 2^16 --->
<cfset CIDRRealAddress = CIDRRealAddress
+ CIDRAddress[1] * 16777216> <!--- 2^24 --->
<!--- Get the integer representation of the test IP address --->
<cfset TestRealAddress = TestIPAddress[4]>
<cfset TestRealAddress = TestRealAddress
+ TestIPAddress[3] * 256> <!--- 2^8 --->
<cfset TestRealAddress = TestRealAddress
+ TestIPAddress[2] * 65536> <!--- 2^16 --->
<cfset TestRealAddress = TestRealAddress
+ TestIPAddress[1] * 16777216> <!--- 2^24 --->
<!--- Get the integer representation of the CIDR mask --->
<cfloop from="1" to="#CIDRMask#" index="x">
<cfset CIDRRealMask = CIDRRealMask + 2^(32-x) >
</cfloop>
<!---
CF's BitAnd() cannot handle 32-bit unsigned integers, we will
break these addresses into numbers denoting their left and right
half bits
--->
<!--- Just the left 16 bits --->
<cfset CidrA = int(CIDRRealAddress / 65536)>
<cfset TestIPA = int(TestRealAddress / 65536)>
<cfset MaskA = int(CIDRRealMask / 65536)>
<!--- Just the right 16 bits --->
<!--- Much more efficient would be to use "mod 65536" but even
this does not support unsigned integers --->
<cfset CidrB = CIDRRealAddress - (CidrA * 65536)>
<cfset TestIPB = TestRealAddress - (TestIPA * 65536)>
<cfset MaskB = CIDRRealMask - (MaskA * 65536)>
<cfif BitAnd(CidrA, MaskA) eq BitAnd(TestIPA, MaskA)
AND BitAnd(CidrB, MaskB) eq BitAnd(TestIPB, MaskB)>
<cfreturn true>
<cfelse>
<cfreturn false>
</cfif>
</cffunction>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment