use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum SesErrorCode {
#[default]
AccountSendingPausedException,
AlreadyExists,
AlreadyExistsException,
CannotDeleteException,
ConfigurationSetAlreadyExistsException,
ConfigurationSetDoesNotExist,
ConfigurationSetDoesNotExistException,
ConfigurationSetSendingPausedException,
EventDestinationAlreadyExistsException,
EventDestinationDoesNotExistException,
InternalError,
InvalidCloudWatchDestinationException,
InvalidConfigurationSetException,
InvalidFirehoseDestinationException,
InvalidLambdaFunctionException,
InvalidParameterValue,
InvalidPolicyException,
InvalidS3ConfigurationException,
InvalidSNSDestinationException,
InvalidSnsTopicException,
InvalidTemplate,
InvalidTemplateException,
LimitExceeded,
LimitExceededException,
MailFromDomainNotVerifiedException,
MessageRejected,
MissingAction,
RuleDoesNotExist,
RuleDoesNotExistException,
RuleSetDoesNotExist,
RuleSetDoesNotExistException,
TemplateDoesNotExist,
TemplateDoesNotExistException,
}
impl SesErrorCode {
#[must_use]
pub fn error_type(&self) -> &'static str {
self.as_str()
}
#[must_use]
pub fn as_str(&self) -> &'static str {
match self {
Self::AccountSendingPausedException => "AccountSendingPausedException",
Self::AlreadyExists => "AlreadyExists",
Self::AlreadyExistsException => "AlreadyExistsException",
Self::CannotDeleteException => "CannotDeleteException",
Self::ConfigurationSetAlreadyExistsException => {
"ConfigurationSetAlreadyExistsException"
}
Self::ConfigurationSetDoesNotExist => "ConfigurationSetDoesNotExist",
Self::ConfigurationSetDoesNotExistException => "ConfigurationSetDoesNotExistException",
Self::ConfigurationSetSendingPausedException => {
"ConfigurationSetSendingPausedException"
}
Self::EventDestinationAlreadyExistsException => {
"EventDestinationAlreadyExistsException"
}
Self::EventDestinationDoesNotExistException => "EventDestinationDoesNotExistException",
Self::InternalError => "InternalError",
Self::InvalidCloudWatchDestinationException => "InvalidCloudWatchDestinationException",
Self::InvalidConfigurationSetException => "InvalidConfigurationSetException",
Self::InvalidFirehoseDestinationException => "InvalidFirehoseDestinationException",
Self::InvalidLambdaFunctionException => "InvalidLambdaFunctionException",
Self::InvalidParameterValue => "InvalidParameterValue",
Self::InvalidPolicyException => "InvalidPolicyException",
Self::InvalidS3ConfigurationException => "InvalidS3ConfigurationException",
Self::InvalidSNSDestinationException => "InvalidSNSDestinationException",
Self::InvalidSnsTopicException => "InvalidSnsTopicException",
Self::InvalidTemplate => "InvalidTemplate",
Self::InvalidTemplateException => "InvalidTemplateException",
Self::LimitExceeded => "LimitExceeded",
Self::LimitExceededException => "LimitExceededException",
Self::MailFromDomainNotVerifiedException => "MailFromDomainNotVerifiedException",
Self::MessageRejected => "MessageRejected",
Self::MissingAction => "MissingAction",
Self::RuleDoesNotExist => "RuleDoesNotExist",
Self::RuleDoesNotExistException => "RuleDoesNotExistException",
Self::RuleSetDoesNotExist => "RuleSetDoesNotExist",
Self::RuleSetDoesNotExistException => "RuleSetDoesNotExistException",
Self::TemplateDoesNotExist => "TemplateDoesNotExist",
Self::TemplateDoesNotExistException => "TemplateDoesNotExistException",
}
}
#[must_use]
pub fn code(&self) -> &'static str {
self.as_str()
}
#[must_use]
pub fn status_code(&self) -> http::StatusCode {
self.default_status_code()
}
#[must_use]
pub fn fault(&self) -> &'static str {
match self {
Self::InternalError => "Receiver",
_ => "Sender",
}
}
#[must_use]
pub fn default_status_code(&self) -> http::StatusCode {
match self {
Self::AccountSendingPausedException
| Self::AlreadyExists
| Self::AlreadyExistsException
| Self::CannotDeleteException
| Self::ConfigurationSetAlreadyExistsException
| Self::ConfigurationSetDoesNotExist
| Self::ConfigurationSetDoesNotExistException
| Self::ConfigurationSetSendingPausedException
| Self::EventDestinationAlreadyExistsException
| Self::EventDestinationDoesNotExistException
| Self::InvalidCloudWatchDestinationException
| Self::InvalidConfigurationSetException
| Self::InvalidFirehoseDestinationException
| Self::InvalidLambdaFunctionException
| Self::InvalidParameterValue
| Self::InvalidPolicyException
| Self::InvalidS3ConfigurationException
| Self::InvalidSNSDestinationException
| Self::InvalidSnsTopicException
| Self::InvalidTemplate
| Self::InvalidTemplateException
| Self::LimitExceeded
| Self::LimitExceededException
| Self::MailFromDomainNotVerifiedException
| Self::MessageRejected
| Self::MissingAction
| Self::RuleDoesNotExist
| Self::RuleDoesNotExistException
| Self::RuleSetDoesNotExist
| Self::RuleSetDoesNotExistException
| Self::TemplateDoesNotExist
| Self::TemplateDoesNotExistException => http::StatusCode::BAD_REQUEST,
Self::InternalError => http::StatusCode::INTERNAL_SERVER_ERROR,
}
}
}
impl fmt::Display for SesErrorCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug)]
pub struct SesError {
pub code: SesErrorCode,
pub message: String,
pub status_code: http::StatusCode,
pub source: Option<Box<dyn std::error::Error + Send + Sync>>,
}
impl fmt::Display for SesError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SesError({}): {}", self.code, self.message)
}
}
impl std::error::Error for SesError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.source
.as_ref()
.map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
}
}
impl SesError {
#[must_use]
pub fn new(code: SesErrorCode) -> Self {
Self {
status_code: code.default_status_code(),
message: code.as_str().to_owned(),
code,
source: None,
}
}
#[must_use]
pub fn with_message(code: SesErrorCode, message: impl Into<String>) -> Self {
Self {
status_code: code.default_status_code(),
message: message.into(),
code,
source: None,
}
}
#[must_use]
pub fn error_type(&self) -> &'static str {
self.code.error_type()
}
#[must_use]
pub fn internal_error(message: impl Into<String>) -> Self {
Self::with_message(SesErrorCode::InternalError, message)
}
#[must_use]
pub fn missing_action() -> Self {
Self::with_message(
SesErrorCode::MissingAction,
"Missing required header: X-Amz-Target",
)
}
#[must_use]
pub fn not_implemented(operation: &str) -> Self {
Self::with_message(
SesErrorCode::InternalError,
format!("Operation {operation} is not yet implemented"),
)
}
#[must_use]
pub fn invalid_parameter_value(message: impl Into<String>) -> Self {
Self::with_message(SesErrorCode::InvalidParameterValue, message)
}
#[must_use]
pub fn invalid_action(action: &str) -> Self {
Self::with_message(
SesErrorCode::InvalidParameterValue,
format!("Unrecognized operation: {action}"),
)
}
#[must_use]
pub fn message_rejected(message: impl Into<String>) -> Self {
Self::with_message(SesErrorCode::MessageRejected, message)
}
#[must_use]
pub fn template_does_not_exist(name: &str) -> Self {
Self::with_message(
SesErrorCode::TemplateDoesNotExist,
format!("Template {name} does not exist"),
)
}
}
#[macro_export]
macro_rules! ses_error {
($code:ident) => {
$crate::error::SesError::new($crate::error::SesErrorCode::$code)
};
($code:ident, $msg:expr) => {
$crate::error::SesError::with_message($crate::error::SesErrorCode::$code, $msg)
};
}