diff --git a/Cargo.toml b/Cargo.toml index 0b30ce9..e7132ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ env_logger = "^0.7" glob = "^0.3" criterion = "^0.3" async-attributes = "1.1.1" +structopt = "0.3.17" [[bench]] name = "transport_smtp" diff --git a/examples/smtp.rs b/examples/smtp.rs index 39e64e3..6bec97e 100644 --- a/examples/smtp.rs +++ b/examples/smtp.rs @@ -1,32 +1,57 @@ +use async_smtp::smtp::response::Response; use async_smtp::{EmailAddress, Envelope, SendableEmail, SmtpClient}; +use async_std::{io, io::Read, io::ReadExt, task}; +use structopt::StructOpt; + +pub type Error = Box; +pub type Result = std::result::Result; fn main() { env_logger::init(); - async_std::task::block_on(async move { - let email = SendableEmail::new( - Envelope::new( - Some(EmailAddress::new("user@localhost".to_string()).unwrap()), - vec![EmailAddress::new("root@localhost".to_string()).unwrap()], - ) - .unwrap(), - "id".to_string(), - "Hello ß☺ example".to_string().into_bytes(), - ); - - // Open a local connection on port 25 - let mut mailer = SmtpClient::new_unencrypted_localhost() - .await - .unwrap() - .into_transport(); - // Send the email - let result = mailer.connect_and_send(email).await; - - if result.is_ok() { - println!("Email sent"); - } else { - println!("Could not send email: {:?}", result); - } - - assert!(result.is_ok()); - }); + + // Collect all inputs + let opt = Opt::from_args(); + let id = "some_random_id"; + println!("Type your mail and finish with Ctrl+D:"); + + // Send mail + let result = task::block_on(send_mail(opt, id, io::stdin())); + + if let Ok(response) = result { + println!("Email sent. Response: {:?}", response); + } else { + println!("Could not send email: {:?}", result); + } +} + +async fn send_mail(opt: Opt, id: &str, mut mail: impl Read + Unpin) -> Result { + let mut body = vec![]; + mail.read_to_end(&mut body).await?; + + // Compose a mail + let email = SendableEmail::new(Envelope::new(Some(opt.from), opt.to)?, id.to_string(), body); + + // Open an SMTP connection to given address + let mut mailer = SmtpClient::unencrypted(opt.server).await?.into_transport(); + + // Send the email + let response = mailer.connect_and_send(email).await?; + + Ok(response) +} + +#[derive(StructOpt, Debug)] +#[structopt(name = "smtp")] +struct Opt { + /// Mail from + #[structopt(short = "f", name = "sender address")] + from: EmailAddress, + + /// Rcpt to, can be repeated multiple times + #[structopt(short = "t", name = "recipient address", min_values = 1)] + to: Vec, + + /// SMTP server address:port to talk to + #[structopt(short = "s", name = "smtp server", default_value = "localhost:25")] + server: String, } diff --git a/src/smtp/smtp_client.rs b/src/smtp/smtp_client.rs index c3ded97..ae24324 100644 --- a/src/smtp/smtp_client.rs +++ b/src/smtp/smtp_client.rs @@ -117,6 +117,20 @@ impl SmtpClient { } } + /// Creates a new unencrypted SMTP client + /// + /// Defaults are: + /// + /// * No connection reuse + /// * No authentication + /// * No SMTPUTF8 support + /// * A 60 seconds timeout for smtp commands + /// + /// Consider using [`SmtpClient::new_simple`] instead, if possible. + pub async fn unencrypted(addr: A) -> Result { + SmtpClient::with_security(addr, ClientSecurity::None).await + } + /// Simple and secure transport, should be used when possible. /// Creates an encrypted transport over submissions port, using the provided domain /// to validate TLS certificates.