use async_smtp::{EmailAddress, Envelope, SendableEmail};
use super::Smtp;
use crate::config::Config;
use crate::context::Context;
use crate::events::EventType;
use crate::tools;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Envelope error: {}", _0)]
Envelope(anyhow::Error),
#[error("Send error: {}", _0)]
SmtpSend(async_smtp::error::Error),
#[error("SMTP has no transport")]
NoTransport,
#[error("{}", _0)]
Other(#[from] anyhow::Error),
}
impl Smtp {
pub async fn send(
&mut self,
context: &Context,
recipients: &[EmailAddress],
message: &[u8],
) -> Result<()> {
if !context.get_config_bool(Config::Bot).await? {
context.ratelimit.write().await.send();
}
let message_len_bytes = message.len();
let recipients_display = recipients
.iter()
.map(|x| x.as_ref())
.collect::<Vec<&str>>()
.join(",");
let envelope =
Envelope::new(self.from.clone(), recipients.to_vec()).map_err(Error::Envelope)?;
let mail = SendableEmail::new(envelope, message);
if let Some(ref mut transport) = self.transport {
transport.send(mail).await.map_err(Error::SmtpSend)?;
let info_msg =
format!("Message len={message_len_bytes} was SMTP-sent to {recipients_display}");
info!(context, "{info_msg}.");
context.emit_event(EventType::SmtpMessageSent(info_msg));
self.last_success = Some(tools::Time::now());
} else {
warn!(
context,
"uh? SMTP has no transport, failed to send to {}", recipients_display
);
return Err(Error::NoTransport);
}
Ok(())
}
}