choonkeat/elm-aws/8.0.0

NOTE: the latest version is 9.0.0

AWS.SES

= RawEmail
{ from : String
, destinations : List String
, rawMessage : String
}
| Email
{ from : String
, to : List String
, replyTo : List String
, subject : String
, textBody : String
, htmlBody : String
}
= Error
{ type_ : String
, code : String
, message : String
}
| Success
{ messageId : String
, requestId : String
}
unsignedRequest : OutgoingMail -> Result String (UnsignedRequest 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 = "[email protected]"
            , to = [ "[email protected]" ]
            , replyTo = [ "[email protected]" ]
            , 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
= SESBounce Mail Bounce
| SESComplaint Mail Complaint
| SESDelivery Mail Delivery

Inner types and decoders

type alias Mail =
{ timestamp : Posix
, messageId : String
, source : String
, sourceArn : String
, sourceIp : String
, sendingAccountId : String
, destination : List String
, headersTruncated : Bool
, headers : List NamedValue
, commonHeaders : CommonMailHeaders
}
type alias CommonMailHeaders =
{ from : List String
, date : Maybe Posix
, to : List String
, messageId : Maybe String
, subject : Maybe String
}
type alias Bounce =
{ bounceType : BounceType
, bouncedRecipients : List BounceRecipient
, timestamp : Posix
, feedbackId : String
, remoteMtaIp : Maybe String
, reportingMTA : Maybe String
}
type alias BounceRecipient =
{ emailAddress : String
, action : Maybe String
, status : Maybe String
, diagnosticCode : Maybe String
}
= BounceUndetermined
| BouncePermanent
| BouncePermanentGeneral
| BouncePermanentNoEmail
| BouncePermanentSuppressed
| BouncePermanentOnAccountSuppressionList
| BounceTransient
| BounceTransientGeneral
| BounceTransientMailboxFull
| BounceTransientMessageTooLarge
| BounceTransientContentRejected
| BounceTransientAttachmentRejected
type alias Complaint =
{ userAgent : Maybe String
, complaintFeedbackType : Maybe ComplaintFeedbackType
, arrivalDate : Maybe Posix
, complainedRecipients : List ComplainedRecipient
, timestamp : Posix
, feedbackId : String
, complaintSubType : Maybe ComplaintSubType
}
= ComplaintFeedbackAbuse
| ComplaintFeedbackAuthFailure
| ComplaintFeedbackFraud
| ComplaintFeedbackNotSpam
| ComplaintFeedbackVirus
| ComplaintFeedbackOther
| ComplaintFeedbackUnknown String
type alias Delivery =
{ timestamp : Posix
, processingTimeMillis : Int
, recipients : List String
}
type alias NamedValue =
{ name : String
, value : String
}

Mail headers like

  {
     "name":"From",
     "value":"\"Sender Name\" <[email protected]>"
  }
decodeNamedValue : Decoder NamedValue

decoder for Mail headers

Tested internals

paramsForMail : OutgoingMail -> Result String (List ( String, String ))
givenRawMessage : String
givenRawMessage =
    -- NOTE: the leading space of this string will be removed
    "\n\nFrom:[email protected]\nSubject: Test\n\nMessage sent using SendRawEmail.\n\n"


expectedRawParams : List (String, String)
expectedRawParams =
    [ ("Action", "SendRawEmail")
    , ( "Source", "[email protected]" )
    , ("Destinations.member.1", "[email protected]")
    , ("Destinations.member.2", "[email protected]")
    , ("RawMessage.Data", "RnJvbTp1c2VyQGV4YW1wbGUuY29tClN1YmplY3Q6IFRlc3QKCk1lc3NhZ2Ugc2VudCB1c2luZyBTZW5kUmF3RW1haWwuCgo=")
    ]




paramsForMail
    (RawEmail
        { from = "[email protected]"
        , destinations = ["[email protected]", "[email protected]"]
        , rawMessage = givenRawMessage
        }
    )
--> Ok expectedRawParams


givenEmailDetail : { from : String, to : List String, replyTo : List String, subject : String, textBody : String, htmlBody : String}
givenEmailDetail =
    { from = "[email protected]"
    , to = [ "[email protected]" ]
    , replyTo = [ "[email protected]" ]
    , subject = "Test"
    , textBody = "Message sent using SendEmail"
    , htmlBody = "<p>Message sent using SendEmail</p>"
    }


expectedEmailParams : List (String, String)
expectedEmailParams =
    [ ( "Action", "SendEmail" )
    , ( "Source", "[email protected]" )
    , ( "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", "[email protected]" )
    , ( "ReplyToAddresses.member.1", "[email protected]" )
    ]


paramsForMail (Email givenEmailDetail)
--> Ok expectedEmailParams
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" })