We're using SES for sending emails, and have followed the advice to use an SNS Topic -> SQS Queue flow to capture events such as Bounce, Delivery and so on:
I'm now looking into implementing the "Processor" side, where we'll poll the SQS queue for new messages, parse the relevant bits and act accordingly (e.g. update something on the database).
I'm writing this in Kotlin, making use of the Java SDKs provided by AWS. So far, I've been able to unwrap the SNS outer bit of JSON using something like the following:
class SnsEmailNotificationHandler : DefaultSnsMessageHandler() {
override fun handle(message: SnsNotification?) {
val messageStr = message?.message
println(messageStr)
}
}
...
val messages = sqs.receiveMessage(queueUrl).messages
val snsMessageHandler = SnsEmailNotificationHandler()
messages.forEach {
SnsMessageManager().handleMessage(it.body.byteInputStream(), snsMessageHandler)
}
Running this against an example queue with some SES notifications in, the String that's printed to the console is the unwrapped SES notification, which follows the spec here. I'm happy with this so far, because I've been able to use built-in Amazon SDK stuff rather than having to duplicate their message structure in order to parse the JSON.
However, now I'm stuck. Looking at the example code here, it would seem that I'm now expected to create my own classes to represent the AWS message structures for bounces, complaints, deliveries and so on. I can totally go ahead and do that, with some lightweight data classes and something like Jackson, but I'm reluctant to unless I absolutely have to because:
- It is boilerplate code that I would rather not maintain
- It's brittle if amazon ever change their API
Instead, what I'm hoping exists are some ready-made data objects somewhere in the Amazon SDKs like the SnsNotification I made use of earlier. Who knows, perhaps even an AmazonEmailEvent.parse(...) method, which would return me a class which I can instance-check to figure out if it's a bounce or a delivery and go from there.
I haven't found them quickly, though, so I'm starting to believe they don't exist... which would really suck. Anyone found a good way of doing this?
