From c2d001b060b4a8953a09abf344aab63eb19255b4 Mon Sep 17 00:00:00 2001 From: ryan Date: Wed, 4 Sep 2024 22:36:22 -0400 Subject: [PATCH] bugfix parsing empty string and sending singlepart plaintext emails --- crates/web-form/src/main.rs | 40 +++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/crates/web-form/src/main.rs b/crates/web-form/src/main.rs index 371bada..8338a41 100644 --- a/crates/web-form/src/main.rs +++ b/crates/web-form/src/main.rs @@ -5,37 +5,62 @@ use axum::{ Extension, Form, Router, }; -use lettre::message::Mailbox; +use lettre::message::{header::ContentType, Mailbox, SinglePart}; use lettre::transport::smtp::AsyncSmtpTransport; use lettre::{AsyncTransport, Message, Tokio1Executor}; -use serde::Deserialize; +use serde::{Deserialize, Deserializer}; use std::error::Error; use std::net::SocketAddr; use std::sync::Arc; +fn deserialize_empty_string_as_none<'de, D, T>(de: D) -> Result, D::Error> +where + D: Deserializer<'de>, + T: std::str::FromStr + std::fmt::Debug, + T::Err: std::fmt::Display + std::fmt::Debug, +{ + let opt: Option = Option::deserialize(de)?; + match opt.as_deref() { + None | Some("") => Ok(None), + Some(s) => std::str::FromStr::from_str(s) + .map_err(serde::de::Error::custom) + .map(Some), + } +} + #[derive(Deserialize)] #[serde(rename_all = "kebab-case")] struct FormData { + #[serde(default, deserialize_with = "deserialize_empty_string_as_none")] name: Option, email: String, + #[serde(default, deserialize_with = "deserialize_empty_string_as_none")] company_name: Option, service: String, help: String, + #[serde(default, deserialize_with = "deserialize_empty_string_as_none")] hear_about: Option, + #[serde(default, deserialize_with = "deserialize_empty_string_as_none")] other_source: Option, } struct State { username: String, password: String, + target_address: String, } #[tokio::main] async fn main() -> Result<(), Box> { let username = std::env::var("WEBMAIL_USERNAME")?; let password = std::env::var("WEBMAIL_PASSWORD")?; + let target_address = std::env::var("WEBMAIL_TARGET")?; - let state = State { username, password }; + let state = State { + username, + password, + target_address, + }; let app = Router::new() .route("/submit-email", post(handle_form)) @@ -105,10 +130,13 @@ async fn send_email(form_data: FormData, state: &State) -> Result<(), Box