rss2email_lib/email/
email_provider.rs

1//! An email provider abstraction to allow for multiple backends.
2
3use super::{error::EmailError, resend::Resend, sendgrid::SendGrid};
4use super::{mail_cmd::MailCommand, EnvLoader};
5use enum_dispatch::enum_dispatch;
6
7#[enum_dispatch]
8pub trait EmailProvider {
9  /// Sends an email to and from the specified address.
10  fn send_email(
11    &self,
12    from_address: &str,
13    recipient_addresses: Vec<&str>,
14    subject: &str,
15    contents: &str,
16  ) -> Result<(), EmailError>;
17}
18
19/// An enum containing all Email Provider implementations.
20#[derive(Debug)]
21#[enum_dispatch(EmailProvider)]
22pub enum EmailProviders {
23  SendGrid(SendGrid),
24  Resend(Resend),
25  MailCommand(MailCommand),
26}
27
28/// Abstracts away the email backend.
29///
30/// The email provider is picked by inspecting the
31/// `EMAIL` environment variable.
32///
33/// By default, this will return the `SendGrid` implementation.
34pub fn get_email_provider() -> Result<impl EmailProvider, String> {
35  let env_var = std::env::var("EMAIL")
36    .ok()
37    .unwrap_or_else(|| "SENDGRID".to_owned());
38
39  EmailProviders::try_from(env_var)
40}
41
42impl TryFrom<String> for EmailProviders {
43  type Error = String;
44
45  fn try_from(value: String) -> Result<Self, Self::Error> {
46    let client = value.trim().to_uppercase();
47    let env_vars = EnvLoader::new();
48
49    match client.as_str() {
50      "SENDGRID" => Ok(Self::SendGrid(SendGrid::new(&env_vars))),
51      "RESEND" => Ok(Self::Resend(Resend::new(&env_vars))),
52      "MAIL_COMMAND" => Ok(Self::MailCommand(MailCommand {})),
53      _ => Err("Requested client not found".to_owned()),
54    }
55  }
56}