diff --git a/serverless-haskell.cabal b/serverless-haskell.cabal
--- a/serverless-haskell.cabal
+++ b/serverless-haskell.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: f3d35ad6736c054bc1bebffa93ddf0f4d556eca6a0743b1a17f9dc2e7d898c4d
+-- hash: 40b2acd2d0bc1eddea721bde88ddc17eb101d926cc891b5dcddd6083254be037
 
 name:           serverless-haskell
-version:        0.12.0
+version:        0.12.1
 synopsis:       Deploying Haskell code onto AWS Lambda using Serverless
 description:    Utilities to help process the events from AWS Lambda when deployed with the serverless-haskell plugin.
 category:       AWS, Cloud, Network
@@ -101,6 +101,7 @@
     , serverless-haskell
     , text
     , time
+    , transformers
     , unix
     , unordered-containers
   default-language: Haskell2010
diff --git a/src/AWSLambda/Events.hs b/src/AWSLambda/Events.hs
--- a/src/AWSLambda/Events.hs
+++ b/src/AWSLambda/Events.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DeriveGeneric   #-}
 {-# LANGUAGE TemplateHaskell #-}
 
 module AWSLambda.Events
@@ -9,13 +9,15 @@
   , module AWSLambda.Events.S3Event
   , module AWSLambda.Events.SNSEvent
   , module AWSLambda.Events.SQSEvent
+  , traverseSnsInSqs
   , snsInSqsMain
+  , traverseS3InSnsInSqs
   , s3InSnsInSqsMain
   ) where
 
-import           Control.Exception.Safe (MonadCatch)
+import           Control.Exception.Safe            (MonadCatch)
 import           Control.Monad.IO.Class
-import           Data.Aeson (FromJSON(..))
+import           Data.Aeson                        (FromJSON (..))
 
 import           AWSLambda.Events.APIGateway
 import           AWSLambda.Events.KinesisEvent
@@ -24,14 +26,24 @@
 import           AWSLambda.Events.S3Event
 import           AWSLambda.Events.SNSEvent
 import           AWSLambda.Events.SQSEvent
+import           AWSLambda.Handler                 (lambdaMain)
+import           Data.Aeson.Embedded               (Embedded)
 
+-- | Traverse all the SNS messages embedded in an SQS event
+traverseSnsInSqs :: (FromJSON a, Applicative m) => (a -> m ()) -> SQSEvent (Embedded (SNSMessage (Embedded a))) -> m ()
+traverseSnsInSqs = traverseSqs . traverseSnsMessage
+
 -- | A specialised version of the 'lambdaMain' entry-point
--- for handling individual SNS messages embedded in SQS messages
+-- for handling individual SNS messages embedded in an SQS event
 snsInSqsMain :: (FromJSON a, MonadCatch m, MonadIO m) => (a -> m ()) -> m ()
-snsInSqsMain = sqsMain . traverseSns
+snsInSqsMain = lambdaMain . traverseSnsInSqs
 
+-- | Traverse S3 events embedded within SNS messages within an SQS event
+traverseS3InSnsInSqs :: (Applicative m) => (S3EventNotification -> m ()) -> SQSEvent (Embedded (SNSMessage (Embedded S3Event))) -> m ()
+traverseS3InSnsInSqs = traverseSnsInSqs . traverseRecords
+
 -- | A specialised version of the 'lambdaMain' entry-point
 -- for handling individual S3 event notifications embedded in
--- SNS messages embedded in SQS messages
+-- SNS messages embedded in an SQS event
 s3InSnsInSqsMain :: (MonadCatch m, MonadIO m) => (S3EventNotification -> m ()) -> m ()
-s3InSnsInSqsMain = snsInSqsMain . traverseRecords
+s3InSnsInSqsMain = lambdaMain . traverseS3InSnsInSqs
diff --git a/src/AWSLambda/Events/SNSEvent.hs b/src/AWSLambda/Events/SNSEvent.hs
--- a/src/AWSLambda/Events/SNSEvent.hs
+++ b/src/AWSLambda/Events/SNSEvent.hs
@@ -104,6 +104,11 @@
 binary :: Traversal' (SNSEvent Base64) ByteString
 binary = messages . _Base64
 
+-- | Traverse an SNS message
+traverseSnsMessage :: (FromJSON a, Applicative m) => (a -> m ()) -> SNSMessage (Embedded a) -> m ()
+traverseSnsMessage act message =
+    act $ message ^. smMessage . unTextValue . unEmbed
+
 -- | Traverse all the messages in an SNS event
 traverseSns :: (FromJSON a, Applicative m) => (a -> m ()) -> SNSEvent (Embedded a) -> m ()
 traverseSns act = traverseRecords $ \record ->
diff --git a/test/AWSLambda/Events/SQSEventSpec.hs b/test/AWSLambda/Events/SQSEventSpec.hs
--- a/test/AWSLambda/Events/SQSEventSpec.hs
+++ b/test/AWSLambda/Events/SQSEventSpec.hs
@@ -1,23 +1,20 @@
-{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedLists   #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes       #-}
 
 module AWSLambda.Events.SQSEventSpec where
 
-import           AWSLambda.Events.MessageAttribute
-import           AWSLambda.Events.Records
-import           AWSLambda.Events.S3Event
-import           AWSLambda.Events.SNSEvent
-import           AWSLambda.Events.SQSEvent
+import           AWSLambda.Events
 
+import           Control.Monad.Trans.Writer
 import           Data.Aeson
 import           Data.Aeson.Embedded
 import           Data.Aeson.TextValue
-import           Data.ByteString.Lazy      (ByteString)
-import           Data.Text                 (Text)
+import           Data.ByteString.Lazy              (ByteString)
+import           Data.Text                         (Text)
 import           Data.Time.Calendar
 import           Data.Time.Clock
-import           Network.AWS.S3            as S3
+import           Network.AWS.S3                    as S3
 
 import           Text.RawString.QQ
 
@@ -29,6 +26,10 @@
     decode sampleSQSJSON `shouldBe` Just sampleSQSEvent
   it "parses sample embedded S3 -> SNS -> SQS event" $
     eitherDecode sampleS3SNSSQSJSON `shouldBe` Right sampleS3SNSSQSEvent
+  it "traverses sample embedded S3 -> SNS -> SQS event" $
+    (execWriter $
+      traverseS3InSnsInSqs (tell . (: []) . _sbeName . _seBucket . _senS3) sampleS3SNSSQSEvent)
+      `shouldBe` ["my-bucket"]
 
 sampleSQSJSON :: ByteString
 sampleSQSJSON = [r|
