diff --git a/src/domain/smtp.rs b/src/domain/smtp.rs new file mode 100644 index 0000000..c5b969f --- /dev/null +++ b/src/domain/smtp.rs @@ -0,0 +1,68 @@ +use anyhow::Result; +use lettre::{ + self, + transport::smtp::{ + client::{Tls, TlsParameters}, + SmtpTransport, + }, + Transport, +}; + +use crate::domain::account::entity::Account; + +pub trait SmtpServiceInterface { + fn send(&mut self, msg: &lettre::Message) -> Result<()>; +} + +pub struct SmtpService<'a> { + account: &'a Account, + transport: Option, +} + +impl<'a> SmtpService<'a> { + pub fn new(account: &'a Account) -> Result { + Ok(Self { + account, + transport: None, + }) + } + + fn transport(&mut self) -> Result<&SmtpTransport> { + if let Some(ref transport) = self.transport { + Ok(transport) + } else { + let builder = if self.account.smtp_starttls { + SmtpTransport::starttls_relay(&self.account.smtp_host) + } else { + SmtpTransport::relay(&self.account.smtp_host) + }?; + + let tls = TlsParameters::builder(self.account.smtp_host.to_owned()) + .dangerous_accept_invalid_hostnames(self.account.smtp_insecure) + .dangerous_accept_invalid_certs(self.account.smtp_insecure) + .build()?; + let tls = if self.account.smtp_starttls { + Tls::Required(tls) + } else { + Tls::Wrapper(tls) + }; + + self.transport = Some( + builder + .tls(tls) + .port(self.account.smtp_port) + .credentials(self.account.smtp_creds()?) + .build(), + ); + + Ok(self.transport.as_ref().unwrap()) + } + } +} + +impl<'a> SmtpServiceInterface for SmtpService<'a> { + fn send(&mut self, msg: &lettre::Message) -> Result<()> { + self.transport()?.send(msg)?; + Ok(()) + } +} diff --git a/src/domain/smtp/mod.rs b/src/domain/smtp/mod.rs deleted file mode 100644 index 81d6738..0000000 --- a/src/domain/smtp/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! Modules related to SMTP. - -pub mod service; diff --git a/src/domain/smtp/service.rs b/src/domain/smtp/service.rs deleted file mode 100644 index 286e71a..0000000 --- a/src/domain/smtp/service.rs +++ /dev/null @@ -1,51 +0,0 @@ -use anyhow::Result; -use lettre::{ - self, - transport::{smtp::client::Tls, smtp::client::TlsParameters, smtp::SmtpTransport}, - Transport, -}; - -use crate::domain::account::entity::Account; - -pub trait SMTPServiceInterface { - fn send(&self, msg: &lettre::Message) -> Result<()>; -} - -pub struct SMTPService<'a> { - account: &'a Account, -} - -impl<'a> SMTPService<'a> { - pub fn new(account: &'a Account) -> Result { - Ok(Self { account }) - } -} - -impl<'a> SMTPServiceInterface for SMTPService<'a> { - fn send(&self, msg: &lettre::Message) -> Result<()> { - let smtp_relay = if self.account.smtp_starttls { - SmtpTransport::starttls_relay - } else { - SmtpTransport::relay - }; - - let tls = TlsParameters::builder(self.account.smtp_host.to_string()) - .dangerous_accept_invalid_hostnames(self.account.smtp_insecure) - .dangerous_accept_invalid_certs(self.account.smtp_insecure) - .build()?; - let tls = if self.account.smtp_starttls { - Tls::Required(tls) - } else { - Tls::Wrapper(tls) - }; - - smtp_relay(&self.account.smtp_host)? - .port(self.account.smtp_port) - .tls(tls) - .credentials(self.account.smtp_creds()?) - .build() - .send(msg)?; - - Ok(()) - } -} diff --git a/src/lib.rs b/src/lib.rs index 61a963a..a6ae5ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,4 +43,5 @@ pub mod msg; pub mod output; pub mod domain; +pub mod infra; pub mod ui; diff --git a/src/main.rs b/src/main.rs index bd03c07..b030cb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ use himalaya::{ comp, config::cli::config_args, ctx::Ctx, - domain::{account::entity::Account, config::entity::Config, smtp::service::SMTPService}, + domain::{account::entity::Account, config::entity::Config, smtp::SmtpService}, flag, imap, mbox, msg, output::{cli::output_args, model::Output}, }; @@ -73,7 +73,7 @@ fn main() -> Result<()> { let account_name = arg_matches.value_of("account"); let account = Account::try_from((&config, account_name))?; - let smtp_service = SMTPService::new(&account)?; + let smtp_service = SmtpService::new(&account)?; debug!("account name: {}", account_name.unwrap_or("default")); trace!("account: {:?}", account); diff --git a/src/msg/cli.rs b/src/msg/cli.rs index 937da98..81606b8 100644 --- a/src/msg/cli.rs +++ b/src/msg/cli.rs @@ -20,7 +20,7 @@ use super::{ }; use crate::{ ctx::Ctx, - domain::{account::entity::Account, smtp}, + domain::{account::entity::Account, smtp::*}, flag::model::Flags, imap::model::ImapConnector, input, @@ -127,10 +127,10 @@ pub fn subcmds<'a>() -> Vec> { ] } -pub fn matches( +pub fn matches( ctx: &Ctx, account: &Account, - smtp: SMTP, + smtp: SmtpService, ) -> Result { match ctx.arg_matches.subcommand() { ("attachments", Some(matches)) => msg_matches_attachments(&ctx, &account, &matches), @@ -399,11 +399,11 @@ fn msg_matches_attachments( Ok(true) } -fn msg_matches_write<'a, SMTP: smtp::service::SMTPServiceInterface>( +fn msg_matches_write( ctx: &Ctx, account: &Account, matches: &clap::ArgMatches, - smtp: SMTP, + smtp: SmtpService, ) -> Result { debug!("write command matched"); @@ -438,11 +438,11 @@ fn msg_matches_write<'a, SMTP: smtp::service::SMTPServiceInterface>( Ok(true) } -fn msg_matches_reply<'a, SMTP: smtp::service::SMTPServiceInterface>( +fn msg_matches_reply( ctx: &Ctx, account: &Account, matches: &clap::ArgMatches, - smtp: SMTP, + smtp: SmtpService, ) -> Result { debug!("reply command matched"); @@ -473,11 +473,11 @@ fn msg_matches_reply<'a, SMTP: smtp::service::SMTPServiceInterface>( Ok(true) } -pub fn msg_matches_mailto<'a, SMTP: smtp::service::SMTPServiceInterface>( +pub fn msg_matches_mailto( ctx: &Ctx, account: &Account, url: &Url, - smtp: SMTP, + smtp: SmtpService, ) -> Result<()> { debug!("mailto command matched"); @@ -525,11 +525,11 @@ pub fn msg_matches_mailto<'a, SMTP: smtp::service::SMTPServiceInterface>( Ok(()) } -fn msg_matches_forward<'a, SMTP: smtp::service::SMTPServiceInterface>( +fn msg_matches_forward( ctx: &Ctx, account: &Account, matches: &clap::ArgMatches, - smtp: SMTP, + smtp: SmtpService, ) -> Result { debug!("forward command matched"); @@ -639,11 +639,11 @@ fn msg_matches_delete(ctx: &Ctx, account: &Account, matches: &clap::ArgMatches) Ok(true) } -fn msg_matches_send<'a, SMTP: smtp::service::SMTPServiceInterface>( +fn msg_matches_send( ctx: &Ctx, account: &Account, matches: &clap::ArgMatches, - smtp: SMTP, + mut smtp: SmtpService, ) -> Result { debug!("send command matched"); @@ -849,11 +849,11 @@ fn tpl_matches_forward(ctx: &Ctx, account: &Account, matches: &clap::ArgMatches) /// This function opens the prompt to do some actions to the msg like sending, editing it again and /// so on. -fn msg_interaction( +fn msg_interaction( ctx: &Ctx, msg: &mut Msg, imap_conn: &mut ImapConnector, - smtp: SMTP, + mut smtp: SmtpService, ) -> Result { // let the user change the body a little bit first, before opening the prompt msg.edit_body()?;