1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A representation of a response from
//! the SocketLabs [Injection API](https://www.socketlabs.com/api-reference/injection-api/).

use std::borrow::Cow;

use serde::de::{Deserialize, Deserializer};

/// Representation of the SocketLabs AddressResult.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct AddressResult<'a> {
    /// The recipient address which generated the warning or error.
    pub email_address: Cow<'a, str>,
    /// A true or false value indicating whether or not
    /// the message was deliverable.
    pub accepted: bool,
    /// The reason for message delivery failure when an error
    /// occurs on the address-level.
    #[serde(deserialize_with = "deserialize_addressresult")]
    pub error_code: AddressResultErrorCode,
}

/// Representation of the SocketLabs MessageResult.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct MessageResult<'a> {
    /// The index of the message that this response represents
    /// from the original array posted.
    pub index: u16,
    /// The reason for message delivery failure when an error
    /// occurs on the message-level.
    #[serde(deserialize_with = "deserialize_messageresult")]
    pub error_code: MessageResultErrorCode,
    /// An array of AddressResult objects that contain the status
    /// of each address that failed. If no messages failed this array is empty.
    pub address_result: Option<Vec<AddressResult<'a>>>,
}

/// Representation of the SocketLabs PostResponse.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Response<'a> {
    /// The success or failure details of the overall injection request.
    #[serde(deserialize_with = "deserialize_postmessage")]
    pub error_code: PostMessageErrorCode,
    /// A unique key generated if an unexpected error occurs during
    /// injection that can be used by SocketLabs support to
    /// troubleshoot the issue.
    pub transaction_receipt: Option<Cow<'a, str>>,
    /// An array of message result objects for messages that failed or
    /// have bad recipients. If there were no errors this response is empty.
    pub message_results: Option<Vec<MessageResult<'a>>>,
}

macro_rules! create_error_codes {
    ($(#[$docs:meta] ($enum:ident, $func: ident, ($(($kind:ident, $display:expr)),*) )),+) => ($(
        #[$docs]
        #[derive(Debug, Deserialize, Fail, PartialEq)]
        pub enum $enum {
            $(
                #[fail(display = $display)]
                $kind,
            )*
            #[fail(display = "SocketLabs returned an unknown error code.")]
            #[serde(skip_deserializing)]
            UnknownErrorCode,
        }

        fn $func<'de, D>(
            deserializer: D,
        ) -> Result<$enum, D::Error>
        where
            D: Deserializer<'de>,
        {
            Ok($enum::deserialize(deserializer)
                .unwrap_or($enum::UnknownErrorCode))
        }
    )*);
}

create_error_codes! {
    /// Return codes within the Response object, specifying the status of the injection request.
    (PostMessageErrorCode, deserialize_postmessage,
        ((Success, "Success."),
        (Warning, "There were one or more failed messages and/or recipients."),
        (AccountDisabled, "The account has been disabled."),
        (InternalError, "Internal server error. (Please report to SocketLabs support if encountered.)"),
        (InvalidAuthentication, "The ServerId/ApiKey combination is invalid."),
        (InvalidData, "PostBody parameter does not have a valid structure, or contains invalid or missing data."),
        (NoMessages, "There were no messages to inject included in the request."),
        (EmptyMessage, "One or more messages have insufficient content to process."),
        (OverQuota, "Rate limit exceeded."),
        (TooManyErrors, "Authentication error limit exceeded."),
        (TooManyMessages, "Too many messages in a single request."),
        (TooManyRecipients, "Too many recipients in a single message."),
        (NoValidRecipients, "A merge was attempted, but there were no valid recipients."))
    ),
    /// Return codes within the MessageResult object, specifying the status of a specific message.
    (MessageResultErrorCode, deserialize_messageresult,
        ((Warning, "The message has one or more bad recipients."),
        (InvalidAttachment, "The message has one or more invalid attachments."),
        (MessageTooLarge, "The message was larger than the allowed size."),
        (EmptySubject, "This message contained an empty subject line, which is not allowed."),
        (EmptyToAddress, "This message does not contain a To address."),
        (InvalidFromAddress, "This message does not contain a valid From address."),
        (NoValidBodyParts, "This message does not have a valid text HTML body specified."),
        (NoValidRecipients, "There are no valid addresses specified as message recipients."),
        (InvalidMergeData, "The included merge data does not follow the API specification."),
        (InvalidTemplateId, "The selected API Template does not exist."),
        (MessageBodyConflict, "The Html Body and Text Body cannot be set when also specifying an API Template ID."))
    ),
    /// Return codes within the AddressResult object, specifying the status of a specific recipient.
    (AddressResultErrorCode, deserialize_addressresult,
        ((InvalidAddress, "The address did not meet specification requirements."))
    )
}