diff --git a/web/src/main.rs b/web/src/main.rs index 6e2db15e..268cd981 100644 --- a/web/src/main.rs +++ b/web/src/main.rs @@ -35,9 +35,9 @@ async fn main() -> anyhow::Result<()> { let args = parse_args()?; let pool = PgPool::connect(&config.database_url).await?; - let mailer = utils::email::get_mailer()?; + let mailer = utils::email::get_mailer(&config)?; - handle_command(args.command, &pool).await?; + handle_command(args.command, &pool, &mailer).await?; let address = config.server_address; let port = config.server_port; diff --git a/web/src/utils/email.rs b/web/src/utils/email.rs index 0a7ede00..de4a16ca 100644 --- a/web/src/utils/email.rs +++ b/web/src/utils/email.rs @@ -1,5 +1,6 @@ use std::env; +use brass_config::{Config, SmtpTlsType}; use lettre::{ message::{header::ContentType, Mailbox, MultiPart, SinglePart}, transport::smtp::{authentication::Credentials, extension::ClientId}, @@ -10,30 +11,19 @@ use crate::models::User; use super::ApplicationError; -pub fn get_mailer() -> anyhow::Result { - let server = &env::var("SMTP_SERVER")?; - let port = &env::var("SMTP_PORT")?.parse()?; - let login = &env::var("SMTP_LOGIN") - .and_then(|x| Ok(Some(x))) - .unwrap_or(None); - let password = &env::var("SMTP_PASSWORD") - .and_then(|x| Ok(Some(x))) - .unwrap_or(None); - let tls_type = &env::var("SMTP_TLSTYPE")?; - let hostname = &env::var("HOSTNAME")?; - - let mut builder = match tls_type.as_str() { - "starttls" => SmtpTransport::starttls_relay(server)?.port(*port), - "tls" => SmtpTransport::relay(server)?.port(*port), - _ => SmtpTransport::builder_dangerous(server).port(*port), +pub fn get_mailer(config: &Config) -> anyhow::Result { + let mut builder = match config.smtp_tlstype { + SmtpTlsType::StartTLS => SmtpTransport::starttls_relay(&config.smtp_server)?.port(config.smtp_port), + SmtpTlsType::TLS => SmtpTransport::relay(&config.smtp_server)?.port(config.smtp_port), + SmtpTlsType::NoTLS => SmtpTransport::builder_dangerous(&config.smtp_server).port(config.smtp_port), }; - if let (Some(login), Some(password)) = (login, password) { + if let (Some(login), Some(password)) = (config.smtp_login.as_ref(), config.smtp_password.as_ref()) { builder = builder.credentials(Credentials::new(login.to_string(), password.to_string())); } let mailer = builder - .hello_name(ClientId::Domain(hostname.to_string())) + .hello_name(ClientId::Domain(config.hostname.clone())) .build(); Ok(mailer) diff --git a/web/src/utils/manage_commands.rs b/web/src/utils/manage_commands.rs index 8489e564..4ce55e87 100644 --- a/web/src/utils/manage_commands.rs +++ b/web/src/utils/manage_commands.rs @@ -1,8 +1,13 @@ use std::{ + error::Error, io::{stdin, stdout, Write}, process::exit, }; +use lettre::{ + message::{header::ContentType, SinglePart}, + Message, SmtpTransport, Transport, +}; use sqlx::{Pool, Postgres}; use crate::{ @@ -13,6 +18,7 @@ use crate::{ pub enum Command { Migrate, CreateAdmin, + TestMail(String), } pub struct Args { @@ -23,6 +29,7 @@ pub fn parse_args() -> Result { let mut pargs = pico_args::Arguments::from_env(); let command = pargs.free_from_str::(); + let argument = pargs.opt_free_from_str::()?; let mut args = Args { command: None }; @@ -30,6 +37,14 @@ pub fn parse_args() -> Result { match parsed.trim() { "migrate" => args.command = Some(Command::Migrate), "createadmin" => args.command = Some(Command::CreateAdmin), + "testmail" => { + if let Some(to) = argument { + args.command = Some(Command::TestMail(to)) + } else { + eprintln!("Testmail command requires an email. Use it like this 'brass testmail abc@example.com'"); + exit(1) + } + } _ => (), } } @@ -47,7 +62,11 @@ fn prompt(prompt: &str) -> anyhow::Result { Ok(input.trim().to_string()) } -pub async fn handle_command(command: Option, pool: &Pool) -> anyhow::Result<()> { +pub async fn handle_command( + command: Option, + pool: &Pool, + mailer: &SmtpTransport, +) -> anyhow::Result<()> { match command { Some(Command::Migrate) => { sqlx::migrate!("../migrations").run(pool).await?; @@ -81,6 +100,32 @@ pub async fn handle_command(command: Option, pool: &Pool) -> exit(0); } + Some(Command::TestMail(to)) => { + let message = Message::builder() + .from("noreply ".parse().unwrap()) + .reply_to("noreply ".parse().unwrap()) + .to(to.parse().unwrap()) + .subject("Brass: Test E-Mail") + .singlepart( + SinglePart::builder() + .header(ContentType::TEXT_HTML) + .body("Testmail von Brass. E-Mail Versand funktioniert!".to_string()), + ) + .unwrap(); + + match mailer.send(&message) { + Ok(_) => println!("Successfully sent mail to {to}."), + Err(e) => { + if let Some(source) = e.source() { + eprintln!("Error sending mail with error source: {source}"); + } else { + eprintln!("Error sending mail with unkown error source."); + } + } + } + + exit(0); + } None => (), };