make smtp service lazy with instance()

This commit is contained in:
Clément DOUIN 2021-09-14 22:27:49 +02:00
parent 979c6ef1c9
commit 07833c2fc7
No known key found for this signature in database
GPG key ID: 69C9B9CFFDEE2DEF
6 changed files with 86 additions and 71 deletions

68
src/domain/smtp.rs Normal file
View file

@ -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<SmtpTransport>,
}
impl<'a> SmtpService<'a> {
pub fn new(account: &'a Account) -> Result<Self> {
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(())
}
}

View file

@ -1,3 +0,0 @@
//! Modules related to SMTP.
pub mod service;

View file

@ -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<Self> {
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(())
}
}

View file

@ -43,4 +43,5 @@ pub mod msg;
pub mod output;
pub mod domain;
pub mod infra;
pub mod ui;

View file

@ -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);

View file

@ -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<clap::App<'a, 'a>> {
]
}
pub fn matches<SMTP: smtp::service::SMTPServiceInterface>(
pub fn matches<SmtpService: SmtpServiceInterface>(
ctx: &Ctx,
account: &Account,
smtp: SMTP,
smtp: SmtpService,
) -> Result<bool> {
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<SmtpService: SmtpServiceInterface>(
ctx: &Ctx,
account: &Account,
matches: &clap::ArgMatches,
smtp: SMTP,
smtp: SmtpService,
) -> Result<bool> {
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<SmtpService: SmtpServiceInterface>(
ctx: &Ctx,
account: &Account,
matches: &clap::ArgMatches,
smtp: SMTP,
smtp: SmtpService,
) -> Result<bool> {
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<SmtpService: SmtpServiceInterface>(
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<SmtpService: SmtpServiceInterface>(
ctx: &Ctx,
account: &Account,
matches: &clap::ArgMatches,
smtp: SMTP,
smtp: SmtpService,
) -> Result<bool> {
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<SmtpService: SmtpServiceInterface>(
ctx: &Ctx,
account: &Account,
matches: &clap::ArgMatches,
smtp: SMTP,
mut smtp: SmtpService,
) -> Result<bool> {
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<SMTP: smtp::service::SMTPServiceInterface>(
fn msg_interaction<SmtpService: SmtpServiceInterface>(
ctx: &Ctx,
msg: &mut Msg,
imap_conn: &mut ImapConnector,
smtp: SMTP,
mut smtp: SmtpService,
) -> Result<bool> {
// let the user change the body a little bit first, before opening the prompt
msg.edit_body()?;