module Aws.Ses.Core
( SesError(..)
, SesMetadata(..)
, SesConfiguration(..)
, sesEuWest1
, sesUsEast
, sesUsEast1
, sesUsWest2
, sesHttpsGet
, sesHttpsPost
, sesSignQuery
, sesResponseConsumer
, RawMessage(..)
, Destination(..)
, EmailAddress
, Sender(..)
, sesAsQuery
) where
import Aws.Core
import qualified Blaze.ByteString.Builder as Blaze
import qualified Blaze.ByteString.Builder.Char8 as Blaze8
import qualified Control.Exception as C
import Control.Monad (mplus)
import Control.Monad.Trans.Resource (throwM)
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64 as B64
import Data.ByteString.Char8 ()
import Data.IORef
import Data.Maybe
import Data.Monoid
import qualified Data.Semigroup as Sem
import Data.Text (Text)
import qualified Data.Text.Encoding as TE
import Data.Typeable
import Prelude
import qualified Network.HTTP.Conduit as HTTP
import qualified Network.HTTP.Types as HTTP
import Text.XML.Cursor (($/), ($//))
import qualified Text.XML.Cursor as Cu
data SesError
= SesError {
SesError -> Status
sesStatusCode :: HTTP.Status
, SesError -> Text
sesErrorCode :: Text
, SesError -> Text
sesErrorMessage :: Text
}
deriving (Int -> SesError -> ShowS
[SesError] -> ShowS
SesError -> String
(Int -> SesError -> ShowS)
-> (SesError -> String) -> ([SesError] -> ShowS) -> Show SesError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SesError -> ShowS
showsPrec :: Int -> SesError -> ShowS
$cshow :: SesError -> String
show :: SesError -> String
$cshowList :: [SesError] -> ShowS
showList :: [SesError] -> ShowS
Show, Typeable)
instance C.Exception SesError
data SesMetadata
= SesMetadata {
SesMetadata -> Maybe Text
requestId :: Maybe Text
}
deriving (Int -> SesMetadata -> ShowS
[SesMetadata] -> ShowS
SesMetadata -> String
(Int -> SesMetadata -> ShowS)
-> (SesMetadata -> String)
-> ([SesMetadata] -> ShowS)
-> Show SesMetadata
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SesMetadata -> ShowS
showsPrec :: Int -> SesMetadata -> ShowS
$cshow :: SesMetadata -> String
show :: SesMetadata -> String
$cshowList :: [SesMetadata] -> ShowS
showList :: [SesMetadata] -> ShowS
Show, Typeable)
instance Loggable SesMetadata where
toLogText :: SesMetadata -> Text
toLogText (SesMetadata Maybe Text
rid) = Text
"SES: request ID=" Text -> Text -> Text
forall a. Monoid a => a -> a -> a
`mappend` Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"<none>" Maybe Text
rid
instance Sem.Semigroup SesMetadata where
SesMetadata Maybe Text
r1 <> :: SesMetadata -> SesMetadata -> SesMetadata
<> SesMetadata Maybe Text
r2 = Maybe Text -> SesMetadata
SesMetadata (Maybe Text
r1 Maybe Text -> Maybe Text -> Maybe Text
forall a. Maybe a -> Maybe a -> Maybe a
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` Maybe Text
r2)
instance Monoid SesMetadata where
mempty :: SesMetadata
mempty = Maybe Text -> SesMetadata
SesMetadata Maybe Text
forall a. Maybe a
Nothing
mappend :: SesMetadata -> SesMetadata -> SesMetadata
mappend = SesMetadata -> SesMetadata -> SesMetadata
forall a. Semigroup a => a -> a -> a
(Sem.<>)
data SesConfiguration qt
= SesConfiguration {
forall qt. SesConfiguration qt -> Method
sesiHttpMethod :: Method
, forall qt. SesConfiguration qt -> ByteString
sesiHost :: B.ByteString
}
deriving (Int -> SesConfiguration qt -> ShowS
[SesConfiguration qt] -> ShowS
SesConfiguration qt -> String
(Int -> SesConfiguration qt -> ShowS)
-> (SesConfiguration qt -> String)
-> ([SesConfiguration qt] -> ShowS)
-> Show (SesConfiguration qt)
forall qt. Int -> SesConfiguration qt -> ShowS
forall qt. [SesConfiguration qt] -> ShowS
forall qt. SesConfiguration qt -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall qt. Int -> SesConfiguration qt -> ShowS
showsPrec :: Int -> SesConfiguration qt -> ShowS
$cshow :: forall qt. SesConfiguration qt -> String
show :: SesConfiguration qt -> String
$cshowList :: forall qt. [SesConfiguration qt] -> ShowS
showList :: [SesConfiguration qt] -> ShowS
Show)
instance DefaultServiceConfiguration (SesConfiguration NormalQuery) where
defServiceConfig :: SesConfiguration NormalQuery
defServiceConfig = ByteString -> SesConfiguration NormalQuery
sesHttpsPost ByteString
sesUsEast1
instance DefaultServiceConfiguration (SesConfiguration UriOnlyQuery) where
defServiceConfig :: SesConfiguration UriOnlyQuery
defServiceConfig = ByteString -> SesConfiguration UriOnlyQuery
forall qt. ByteString -> SesConfiguration qt
sesHttpsGet ByteString
sesUsEast1
sesEuWest1 :: B.ByteString
sesEuWest1 :: ByteString
sesEuWest1 = ByteString
"email.eu-west-1.amazonaws.com"
sesUsEast :: B.ByteString
sesUsEast :: ByteString
sesUsEast = ByteString
sesUsEast1
sesUsEast1 :: B.ByteString
sesUsEast1 :: ByteString
sesUsEast1 = ByteString
"email.us-east-1.amazonaws.com"
sesUsWest2 :: B.ByteString
sesUsWest2 :: ByteString
sesUsWest2 = ByteString
"email.us-west-2.amazonaws.com"
sesHttpsGet :: B.ByteString -> SesConfiguration qt
sesHttpsGet :: forall qt. ByteString -> SesConfiguration qt
sesHttpsGet ByteString
endpoint = Method -> ByteString -> SesConfiguration qt
forall qt. Method -> ByteString -> SesConfiguration qt
SesConfiguration Method
Get ByteString
endpoint
sesHttpsPost :: B.ByteString -> SesConfiguration NormalQuery
sesHttpsPost :: ByteString -> SesConfiguration NormalQuery
sesHttpsPost ByteString
endpoint = Method -> ByteString -> SesConfiguration NormalQuery
forall qt. Method -> ByteString -> SesConfiguration qt
SesConfiguration Method
PostQuery ByteString
endpoint
sesSignQuery :: [(B.ByteString, B.ByteString)] -> SesConfiguration qt -> SignatureData -> SignedQuery
sesSignQuery :: forall qt.
[(ByteString, ByteString)]
-> SesConfiguration qt -> SignatureData -> SignedQuery
sesSignQuery [(ByteString, ByteString)]
query SesConfiguration qt
si SignatureData
sd
= SignedQuery {
sqMethod :: Method
sqMethod = SesConfiguration qt -> Method
forall qt. SesConfiguration qt -> Method
sesiHttpMethod SesConfiguration qt
si
, sqProtocol :: Protocol
sqProtocol = Protocol
HTTPS
, sqHost :: ByteString
sqHost = SesConfiguration qt -> ByteString
forall qt. SesConfiguration qt -> ByteString
sesiHost SesConfiguration qt
si
, sqPort :: Int
sqPort = Protocol -> Int
defaultPort Protocol
HTTPS
, sqPath :: ByteString
sqPath = ByteString
"/"
, sqQuery :: Query
sqQuery = [(ByteString, ByteString)] -> Query
HTTP.simpleQueryToQuery [(ByteString, ByteString)]
query'
, sqDate :: Maybe UTCTime
sqDate = UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just (UTCTime -> Maybe UTCTime) -> UTCTime -> Maybe UTCTime
forall a b. (a -> b) -> a -> b
$ SignatureData -> UTCTime
signatureTime SignatureData
sd
, sqAuthorization :: Maybe (IO ByteString)
sqAuthorization = Maybe (IO ByteString)
forall a. Maybe a
Nothing
, sqContentType :: Maybe ByteString
sqContentType = Maybe ByteString
forall a. Maybe a
Nothing
, sqContentMd5 :: Maybe (Digest MD5)
sqContentMd5 = Maybe (Digest MD5)
forall a. Maybe a
Nothing
, sqAmzHeaders :: RequestHeaders
sqAmzHeaders = RequestHeaders
amzHeaders
, sqOtherHeaders :: RequestHeaders
sqOtherHeaders = []
, sqBody :: Maybe RequestBody
sqBody = Maybe RequestBody
forall a. Maybe a
Nothing
, sqStringToSign :: ByteString
sqStringToSign = ByteString
stringToSign
}
where
stringToSign :: ByteString
stringToSign = UTCTime -> ByteString
fmtRfc822Time (SignatureData -> UTCTime
signatureTime SignatureData
sd)
credentials :: Credentials
credentials = SignatureData -> Credentials
signatureCredentials SignatureData
sd
accessKeyId :: ByteString
accessKeyId = Credentials -> ByteString
accessKeyID Credentials
credentials
amzHeaders :: RequestHeaders
amzHeaders = [Maybe (HeaderName, ByteString)] -> RequestHeaders
forall a. [Maybe a] -> [a]
catMaybes
[ (HeaderName, ByteString) -> Maybe (HeaderName, ByteString)
forall a. a -> Maybe a
Just (HeaderName
"X-Amzn-Authorization", ByteString
authorization)
, (HeaderName
"x-amz-security-token",) (ByteString -> (HeaderName, ByteString))
-> Maybe ByteString -> Maybe (HeaderName, ByteString)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Credentials -> Maybe ByteString
iamToken Credentials
credentials
]
authorization :: ByteString
authorization = [ByteString] -> ByteString
B.concat
[ ByteString
"AWS3-HTTPS AWSAccessKeyId="
, ByteString
accessKeyId
, ByteString
", Algorithm=HmacSHA256, Signature="
, Credentials -> AuthorizationHash -> ByteString -> ByteString
signature Credentials
credentials AuthorizationHash
HmacSHA256 ByteString
stringToSign
]
query' :: [(ByteString, ByteString)]
query' = (ByteString
"AWSAccessKeyId", ByteString
accessKeyId) (ByteString, ByteString)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> [a] -> [a]
: [(ByteString, ByteString)]
query
sesResponseConsumer :: (Cu.Cursor -> Response SesMetadata a)
-> IORef SesMetadata
-> HTTPResponseConsumer a
sesResponseConsumer :: forall a.
(Cursor -> Response SesMetadata a)
-> IORef SesMetadata -> HTTPResponseConsumer a
sesResponseConsumer Cursor -> Response SesMetadata a
inner IORef SesMetadata
metadataRef Response (ConduitM () ByteString (ResourceT IO) ())
resp = (Cursor -> Response SesMetadata a)
-> IORef SesMetadata -> HTTPResponseConsumer a
forall m a.
Monoid m =>
(Cursor -> Response m a) -> IORef m -> HTTPResponseConsumer a
xmlCursorConsumer Cursor -> Response SesMetadata a
parse IORef SesMetadata
metadataRef Response (ConduitM () ByteString (ResourceT IO) ())
resp
where
parse :: Cursor -> Response SesMetadata a
parse Cursor
cursor = do
let requestId' :: Maybe Text
requestId' = [Text] -> Maybe Text
forall a. [a] -> Maybe a
listToMaybe ([Text] -> Maybe Text) -> [Text] -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Cursor
cursor Cursor -> (Cursor -> [Text]) -> [Text]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
"RequestID"
SesMetadata -> Response SesMetadata ()
forall m. m -> Response m ()
tellMetadata (SesMetadata -> Response SesMetadata ())
-> SesMetadata -> Response SesMetadata ()
forall a b. (a -> b) -> a -> b
$ Maybe Text -> SesMetadata
SesMetadata Maybe Text
requestId'
case Cursor
cursor Cursor -> (Cursor -> [Cursor]) -> [Cursor]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$/ Text -> Cursor -> [Cursor]
Cu.laxElement Text
"Error" of
[] -> Cursor -> Response SesMetadata a
inner Cursor
cursor
(Cursor
err:[Cursor]
_) -> Cursor -> Response SesMetadata a
fromError Cursor
err
fromError :: Cursor -> Response SesMetadata a
fromError Cursor
cursor = do
Text
errCode <- String -> [Text] -> Response SesMetadata Text
forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force String
"Missing Error Code" ([Text] -> Response SesMetadata Text)
-> [Text] -> Response SesMetadata Text
forall a b. (a -> b) -> a -> b
$ Cursor
cursor Cursor -> (Cursor -> [Text]) -> [Text]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
"Code"
Text
errMessage <- String -> [Text] -> Response SesMetadata Text
forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force String
"Missing Error Message" ([Text] -> Response SesMetadata Text)
-> [Text] -> Response SesMetadata Text
forall a b. (a -> b) -> a -> b
$ Cursor
cursor Cursor -> (Cursor -> [Text]) -> [Text]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
"Message"
SesError -> Response SesMetadata a
forall e a.
(HasCallStack, Exception e) =>
e -> Response SesMetadata a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
throwM (SesError -> Response SesMetadata a)
-> SesError -> Response SesMetadata a
forall a b. (a -> b) -> a -> b
$ Status -> Text -> Text -> SesError
SesError (Response (ConduitM () ByteString (ResourceT IO) ()) -> Status
forall body. Response body -> Status
HTTP.responseStatus Response (ConduitM () ByteString (ResourceT IO) ())
resp) Text
errCode Text
errMessage
class SesAsQuery a where
sesAsQuery :: a -> [(B.ByteString, B.ByteString)]
instance SesAsQuery a => SesAsQuery (Maybe a) where
sesAsQuery :: Maybe a -> [(ByteString, ByteString)]
sesAsQuery = [(ByteString, ByteString)]
-> (a -> [(ByteString, ByteString)])
-> Maybe a
-> [(ByteString, ByteString)]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] a -> [(ByteString, ByteString)]
forall a. SesAsQuery a => a -> [(ByteString, ByteString)]
sesAsQuery
data RawMessage = RawMessage { RawMessage -> ByteString
rawMessageData :: B.ByteString }
deriving (RawMessage -> RawMessage -> Bool
(RawMessage -> RawMessage -> Bool)
-> (RawMessage -> RawMessage -> Bool) -> Eq RawMessage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RawMessage -> RawMessage -> Bool
== :: RawMessage -> RawMessage -> Bool
$c/= :: RawMessage -> RawMessage -> Bool
/= :: RawMessage -> RawMessage -> Bool
Eq, Eq RawMessage
Eq RawMessage =>
(RawMessage -> RawMessage -> Ordering)
-> (RawMessage -> RawMessage -> Bool)
-> (RawMessage -> RawMessage -> Bool)
-> (RawMessage -> RawMessage -> Bool)
-> (RawMessage -> RawMessage -> Bool)
-> (RawMessage -> RawMessage -> RawMessage)
-> (RawMessage -> RawMessage -> RawMessage)
-> Ord RawMessage
RawMessage -> RawMessage -> Bool
RawMessage -> RawMessage -> Ordering
RawMessage -> RawMessage -> RawMessage
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: RawMessage -> RawMessage -> Ordering
compare :: RawMessage -> RawMessage -> Ordering
$c< :: RawMessage -> RawMessage -> Bool
< :: RawMessage -> RawMessage -> Bool
$c<= :: RawMessage -> RawMessage -> Bool
<= :: RawMessage -> RawMessage -> Bool
$c> :: RawMessage -> RawMessage -> Bool
> :: RawMessage -> RawMessage -> Bool
$c>= :: RawMessage -> RawMessage -> Bool
>= :: RawMessage -> RawMessage -> Bool
$cmax :: RawMessage -> RawMessage -> RawMessage
max :: RawMessage -> RawMessage -> RawMessage
$cmin :: RawMessage -> RawMessage -> RawMessage
min :: RawMessage -> RawMessage -> RawMessage
Ord, Int -> RawMessage -> ShowS
[RawMessage] -> ShowS
RawMessage -> String
(Int -> RawMessage -> ShowS)
-> (RawMessage -> String)
-> ([RawMessage] -> ShowS)
-> Show RawMessage
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RawMessage -> ShowS
showsPrec :: Int -> RawMessage -> ShowS
$cshow :: RawMessage -> String
show :: RawMessage -> String
$cshowList :: [RawMessage] -> ShowS
showList :: [RawMessage] -> ShowS
Show, Typeable)
instance SesAsQuery RawMessage where
sesAsQuery :: RawMessage -> [(ByteString, ByteString)]
sesAsQuery = ((ByteString, ByteString)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> [a] -> [a]
:[]) ((ByteString, ByteString) -> [(ByteString, ByteString)])
-> (RawMessage -> (ByteString, ByteString))
-> RawMessage
-> [(ByteString, ByteString)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,) ByteString
"RawMessage.Data" (ByteString -> (ByteString, ByteString))
-> (RawMessage -> ByteString)
-> RawMessage
-> (ByteString, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
B64.encode (ByteString -> ByteString)
-> (RawMessage -> ByteString) -> RawMessage -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RawMessage -> ByteString
rawMessageData
data Destination =
Destination
{ Destination -> [Text]
destinationBccAddresses :: [EmailAddress]
, Destination -> [Text]
destinationCcAddresses :: [EmailAddress]
, Destination -> [Text]
destinationToAddresses :: [EmailAddress]
} deriving (Destination -> Destination -> Bool
(Destination -> Destination -> Bool)
-> (Destination -> Destination -> Bool) -> Eq Destination
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Destination -> Destination -> Bool
== :: Destination -> Destination -> Bool
$c/= :: Destination -> Destination -> Bool
/= :: Destination -> Destination -> Bool
Eq, Eq Destination
Eq Destination =>
(Destination -> Destination -> Ordering)
-> (Destination -> Destination -> Bool)
-> (Destination -> Destination -> Bool)
-> (Destination -> Destination -> Bool)
-> (Destination -> Destination -> Bool)
-> (Destination -> Destination -> Destination)
-> (Destination -> Destination -> Destination)
-> Ord Destination
Destination -> Destination -> Bool
Destination -> Destination -> Ordering
Destination -> Destination -> Destination
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Destination -> Destination -> Ordering
compare :: Destination -> Destination -> Ordering
$c< :: Destination -> Destination -> Bool
< :: Destination -> Destination -> Bool
$c<= :: Destination -> Destination -> Bool
<= :: Destination -> Destination -> Bool
$c> :: Destination -> Destination -> Bool
> :: Destination -> Destination -> Bool
$c>= :: Destination -> Destination -> Bool
>= :: Destination -> Destination -> Bool
$cmax :: Destination -> Destination -> Destination
max :: Destination -> Destination -> Destination
$cmin :: Destination -> Destination -> Destination
min :: Destination -> Destination -> Destination
Ord, Int -> Destination -> ShowS
[Destination] -> ShowS
Destination -> String
(Int -> Destination -> ShowS)
-> (Destination -> String)
-> ([Destination] -> ShowS)
-> Show Destination
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Destination -> ShowS
showsPrec :: Int -> Destination -> ShowS
$cshow :: Destination -> String
show :: Destination -> String
$cshowList :: [Destination] -> ShowS
showList :: [Destination] -> ShowS
Show, Typeable)
instance SesAsQuery Destination where
sesAsQuery :: Destination -> [(ByteString, ByteString)]
sesAsQuery (Destination [Text]
bcc [Text]
cc [Text]
to) = [[(ByteString, ByteString)]] -> [(ByteString, ByteString)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ Builder -> [Text] -> [(ByteString, ByteString)]
go (ByteString -> Builder
s ByteString
"Bcc") [Text]
bcc
, Builder -> [Text] -> [(ByteString, ByteString)]
go (ByteString -> Builder
s ByteString
"Cc") [Text]
cc
, Builder -> [Text] -> [(ByteString, ByteString)]
go (ByteString -> Builder
s ByteString
"To") [Text]
to ]
where
go :: Builder -> [Text] -> [(ByteString, ByteString)]
go Builder
kind = (Builder -> Text -> (ByteString, ByteString))
-> [Builder] -> [Text] -> [(ByteString, ByteString)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Builder -> Text -> (ByteString, ByteString)
f ((Int -> Builder) -> [Int] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Builder
forall a. Show a => a -> Builder
Blaze8.fromShow [Int
one..])
where txt :: Builder
txt = Builder
kind Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` ByteString -> Builder
s ByteString
"Addresses.member."
f :: Builder -> Text -> (ByteString, ByteString)
f Builder
n Text
v = ( Builder -> ByteString
Blaze.toByteString (Builder
txt Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` Builder
n)
, Text -> ByteString
TE.encodeUtf8 Text
v )
s :: ByteString -> Builder
s = ByteString -> Builder
Blaze.fromByteString
one :: Int
one = Int
1 :: Int
instance Sem.Semigroup Destination where
(Destination [Text]
a1 [Text]
a2 [Text]
a3) <> :: Destination -> Destination -> Destination
<> (Destination [Text]
b1 [Text]
b2 [Text]
b3) =
[Text] -> [Text] -> [Text] -> Destination
Destination ([Text]
a1 [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text]
b1) ([Text]
a2 [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text]
b2) ([Text]
a3 [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text]
b3)
instance Monoid Destination where
mempty :: Destination
mempty = [Text] -> [Text] -> [Text] -> Destination
Destination [] [] []
mappend :: Destination -> Destination -> Destination
mappend = Destination -> Destination -> Destination
forall a. Semigroup a => a -> a -> a
(Sem.<>)
type EmailAddress = Text
data Sender = Sender { Sender -> Text
senderAddress :: EmailAddress }
deriving (Sender -> Sender -> Bool
(Sender -> Sender -> Bool)
-> (Sender -> Sender -> Bool) -> Eq Sender
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Sender -> Sender -> Bool
== :: Sender -> Sender -> Bool
$c/= :: Sender -> Sender -> Bool
/= :: Sender -> Sender -> Bool
Eq, Eq Sender
Eq Sender =>
(Sender -> Sender -> Ordering)
-> (Sender -> Sender -> Bool)
-> (Sender -> Sender -> Bool)
-> (Sender -> Sender -> Bool)
-> (Sender -> Sender -> Bool)
-> (Sender -> Sender -> Sender)
-> (Sender -> Sender -> Sender)
-> Ord Sender
Sender -> Sender -> Bool
Sender -> Sender -> Ordering
Sender -> Sender -> Sender
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Sender -> Sender -> Ordering
compare :: Sender -> Sender -> Ordering
$c< :: Sender -> Sender -> Bool
< :: Sender -> Sender -> Bool
$c<= :: Sender -> Sender -> Bool
<= :: Sender -> Sender -> Bool
$c> :: Sender -> Sender -> Bool
> :: Sender -> Sender -> Bool
$c>= :: Sender -> Sender -> Bool
>= :: Sender -> Sender -> Bool
$cmax :: Sender -> Sender -> Sender
max :: Sender -> Sender -> Sender
$cmin :: Sender -> Sender -> Sender
min :: Sender -> Sender -> Sender
Ord, Int -> Sender -> ShowS
[Sender] -> ShowS
Sender -> String
(Int -> Sender -> ShowS)
-> (Sender -> String) -> ([Sender] -> ShowS) -> Show Sender
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Sender -> ShowS
showsPrec :: Int -> Sender -> ShowS
$cshow :: Sender -> String
show :: Sender -> String
$cshowList :: [Sender] -> ShowS
showList :: [Sender] -> ShowS
Show, Typeable)
instance SesAsQuery Sender where
sesAsQuery :: Sender -> [(ByteString, ByteString)]
sesAsQuery = ((ByteString, ByteString)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> [a] -> [a]
:[]) ((ByteString, ByteString) -> [(ByteString, ByteString)])
-> (Sender -> (ByteString, ByteString))
-> Sender
-> [(ByteString, ByteString)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,) ByteString
"Source" (ByteString -> (ByteString, ByteString))
-> (Sender -> ByteString) -> Sender -> (ByteString, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
TE.encodeUtf8 (Text -> ByteString) -> (Sender -> Text) -> Sender -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sender -> Text
senderAddress