Implementation of https://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-ses-api-requests.html
Response from SES API
See https://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-ses-api-responses.html
unsignedRequest : OutgoingMail -> Result String (AWS.Types.UnsignedRequest Http.Error Response)
Construct an UnsignedRequest
for SES, e.g.
import Http
import AWS.Types
unsignedResult : Result String (AWS.Types.UnsignedRequest Http.Error Response)
unsignedResult =
unsignedRequest
(Email
{ from = "alice@example.com"
, to = [ "bob@example.com" ]
, replyTo = [ "donotreply@example.com" ]
, subject = "Test"
, textBody = "Message sent using SendEmail"
, htmlBody = "<p>Message sent using SendEmail</p>"
}
)
Result.map .method unsignedResult
--> Ok "POST"
Result.map .headers unsignedResult
--> Ok [("Content-Type","application/x-www-form-urlencoded")]
Result.map .stringBody unsignedResult
--> Ok "Action=SendEmail&Source=alice%40example.com&Message.Subject.Data=Test&Message.Body.Text.Data=Message%20sent%20using%20SendEmail&Message.Body.Html.Data=%3Cp%3EMessage%20sent%20using%20SendEmail%3C%2Fp%3E&Destination.ToAddresses.member.1=bob%40example.com&ReplyToAddresses.member.1=donotreply%40example.com"
Result.map .service unsignedResult
--> Ok AWS.Types.ServiceSES
usage config now unsignedResult =
unsignedResult
|> Result.andThen (AWS.signRequest config now)
|> Result.map Http.task
The top-level JSON object in an Amazon SES notification https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#top-level-json-object
decodeNotification : Json.Decode.Decoder Notification
decoder of an Amazon SES notification according to https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html
{ timestamp : Time.Posix
, messageId : String
, source : String
, sourceArn : String
, sourceIp : String
, sendingAccountId : String
, destination : List String
, headersTruncated : Basics.Bool
, headers : List NamedValue
, commonHeaders : CommonMailHeaders
}
mail
in top-level JSON object
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#mail-object
decodeMail : Json.Decode.Decoder Mail
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#mail-object
{ from : List String
, date : Maybe Time.Posix
, to : List String
, messageId : Maybe String
, subject : Maybe String
}
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#mail-object
decodeCommonMailHeaders : Json.Decode.Decoder CommonMailHeaders
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#mail-object
{ bounceType : BounceType
, bouncedRecipients : List BounceRecipient
, timestamp : Time.Posix
, feedbackId : String
, remoteMtaIp : Maybe String
, reportingMTA : Maybe String
}
bounce
in top-level JSON object
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#bounce-object
{ emailAddress : String
, action : Maybe String
, status : Maybe String
, diagnosticCode : Maybe String
}
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#bounced-recipients
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#bounce-types
{ emailAddress : String }
{ userAgent : Maybe String
, complaintFeedbackType : Maybe ComplaintFeedbackType
, arrivalDate : Maybe Time.Posix
, complainedRecipients : List ComplainedRecipient
, timestamp : Time.Posix
, feedbackId : String
, complaintSubType : Maybe ComplaintSubType
}
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#complaint-object
complaint
in top-level JSON object
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#complaint-object
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#complaint-object
{ timestamp : Time.Posix
, processingTimeMillis : Basics.Int
, recipients : List String
}
delivery
in top-level JSON object
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#delivery-object
{ name : String
, value : String
}
Mail headers like
{
"name":"From",
"value":"\"Sender Name\" <sender@example.com>"
}
decodeBounce : Json.Decode.Decoder Bounce
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#bounce-object
decodeBounceRecipient : Json.Decode.Decoder BounceRecipient
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#bounced-recipients
decodeBounceType : Json.Decode.Decoder BounceType
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#bounce-types
decodeComplainedRecipient : Json.Decode.Decoder ComplainedRecipient
decodeComplaint : Json.Decode.Decoder Complaint
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#complaint-object
decodeComplaintFeedbackType : Json.Decode.Decoder ComplaintFeedbackType
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#complaint-object
decodeComplaintSubType : Json.Decode.Decoder ComplaintSubType
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#complaint-object
decodeDelivery : Json.Decode.Decoder Delivery
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html#delivery-object
decodeNamedValue : Json.Decode.Decoder NamedValue
decoder for Mail headers
paramsForMail : OutgoingMail -> Result String (List ( String, String ))
givenRawMessage : String
givenRawMessage =
-- NOTE: the leading space of this string will be removed
"\n\nFrom:user@example.com\nSubject: Test\n\nMessage sent using SendRawEmail.\n\n"
expectedRawParams : List (String, String)
expectedRawParams =
[ ("Action", "SendRawEmail")
, ( "Source", "charlie@example.com" )
, ("Destinations.member.1", "alice@example.com")
, ("Destinations.member.2", "bob@example.com")
, ("RawMessage.Data", "RnJvbTp1c2VyQGV4YW1wbGUuY29tClN1YmplY3Q6IFRlc3QKCk1lc3NhZ2Ugc2VudCB1c2luZyBTZW5kUmF3RW1haWwuCgo=")
]
paramsForMail
(RawEmail
{ from = "charlie@example.com"
, destinations = ["alice@example.com", "bob@example.com"]
, rawMessage = givenRawMessage
}
)
--> Ok expectedRawParams
givenEmailDetail : { from : String, to : List String, replyTo : List String, subject : String, textBody : String, htmlBody : String}
givenEmailDetail =
{ from = "alice@example.com"
, to = [ "bob@example.com" ]
, replyTo = [ "donotreply@example.com" ]
, subject = "Test"
, textBody = "Message sent using SendEmail"
, htmlBody = "<p>Message sent using SendEmail</p>"
}
expectedEmailParams : List (String, String)
expectedEmailParams =
[ ( "Action", "SendEmail" )
, ( "Source", "alice@example.com" )
, ( "Message.Subject.Data", "Test" )
, ( "Message.Body.Text.Data", "Message sent using SendEmail" )
, ( "Message.Body.Html.Data", "<p>Message sent using SendEmail</p>" )
, ( "Destination.ToAddresses.member.1", "bob@example.com" )
, ( "ReplyToAddresses.member.1", "donotreply@example.com" )
]
paramsForMail (Email givenEmailDetail)
--> Ok expectedEmailParams
decodeResponse : Xml.Decode.Decoder Response
import Xml.Decode
--
-- Success scenario
"""
<SendEmailResponse xmlns="https://email.amazonaws.com/doc/2010-03-31/">
<SendEmailResult>
<MessageId>000001271b15238a-fd3ae762-2563-11df-8cd4-6d4e828a9ae8-000000</MessageId>
</SendEmailResult>
<ResponseMetadata>
<RequestId>fd3ae762-2563-11df-8cd4-6d4e828a9ae8</RequestId>
</ResponseMetadata>
</SendEmailResponse>
"""
|> Xml.Decode.run decodeResponse
--> Ok (Success { messageId = "000001271b15238a-fd3ae762-2563-11df-8cd4-6d4e828a9ae8-000000", requestId = "fd3ae762-2563-11df-8cd4-6d4e828a9ae8" })
--
-- Error scenario
"""
<ErrorResponse>
<Error>
<Type>
Sender
</Type>
<Code>
ValidationError
</Code>
<Message>
Value null at 'message.subject' failed to satisfy constraint: Member must not be null
</Message>
</Error>
<RequestId>
42d59b56-7407-4c4a-be0f-4c88daeea257
</RequestId>
</ErrorResponse>
"""
|> Xml.Decode.run decodeResponse
--> Ok (Error { type_ = "Sender", code = "ValidationError", message = "Value null at 'message.subject' failed to satisfy constraint: Member must not be null" })