diff --git a/Cargo.toml b/Cargo.toml index a19461f..273f454 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] members = [ "status_cloud", - "time_tracker" + "chrono_track" ] diff --git a/time_tracker/Cargo.toml b/chrono_track/Cargo.toml similarity index 100% rename from time_tracker/Cargo.toml rename to chrono_track/Cargo.toml diff --git a/time_tracker/src/main.rs b/chrono_track/src/main.rs similarity index 82% rename from time_tracker/src/main.rs rename to chrono_track/src/main.rs index 4ea2a49..16ce56f 100644 --- a/time_tracker/src/main.rs +++ b/chrono_track/src/main.rs @@ -2,7 +2,7 @@ use chrono::{DateTime, Datelike, Utc}; use chrono_tz::US::Central; use clap::Parser; use lettre::{ - message::{Message, header::ContentType, Attachment, MultiPart, SinglePart}, + message::{header::ContentType, Attachment, Message, MultiPart, SinglePart}, SendmailTransport, Transport, }; use log::{debug, error}; @@ -196,7 +196,7 @@ fn main() -> Result<(), Box> { if do_email_summary { debug!("Send email selected"); reset_email_checkbox(&cfg); - send_email_summary(&cfg, body_content); + send_email_summary(&cfg, body_content, &args); } Ok(()) @@ -236,6 +236,9 @@ struct CliArgs { #[arg(short, long)] config_file: PathBuf, + #[arg(short, long)] + from_addr: String, + #[arg(short, long)] debug: bool, } @@ -299,14 +302,14 @@ struct SummaryRow { // All calls after depend on the success of the one before, and cannot run // without. So it would be too much work to make an error type to handle an error // that would cause a crash anyways -fn send_email_summary(config: &Config, body_content: Vec) { +fn send_email_summary(config: &Config, body_content: Vec, cliargs: &CliArgs) { let mut wtr = csv::Writer::from_writer(vec![]); for line in body_content { if line.starts_with("### ") { let mut split: Vec<&str> = line.split('|').collect(); if split.len() != 3 { - error!("There was an issue with this line: {line}"); + error!("There was an issue with this line. 3 splits not found: {line}"); continue; } let date: String = match split.pop() { @@ -355,36 +358,70 @@ fn send_email_summary(config: &Config, body_content: Vec) { .to_string() .replace("### ", ""); - wtr.serialize(SummaryRow { date: date.trim().to_string(), total_time: time, task_name }).unwrap(); + match wtr.serialize(SummaryRow { + date: date.trim().to_string(), + total_time: time, + task_name, + }) { + Ok(_) => continue, + Err(e) => { + error!("There was an error serializing the csv, aborting: {e}"); + return; + } + }; } } - let data = String::from_utf8(wtr.into_inner().unwrap()).unwrap(); + let data = match String::from_utf8(wtr.into_inner().unwrap()) { + Ok(val) => val, + Err(e) => { + error!("There was an error converting the csv writer to a string, aborting: {e}"); + return; + } + }; debug!("{:#?}", data); - let attachment = Attachment::new("TimeSummary.csv".to_string()).body(data, ContentType::parse("text/csv").unwrap()); + let attachment = Attachment::new("TimeSummary.csv".to_string()) + // The unwrap is on a constant value + .body(data, ContentType::parse("text/csv").unwrap()); const HTML: &str = r#" - !DOCTYPE html> + - Hello from Lettre! + ChronoTrack Export -
-

Hello from Lettre!

-

A mailer library for Rust

+
+
+ +

Prepared with care, and sent through the horrors of the interwebs, ChronoTrack presents! (see attached)

"#; let email = Message::builder() - .from("NoReply@nickiel.net ".parse().unwrap()) - .to(config.email_addr.parse().unwrap()) - .subject("Testing email") + .from(match cliargs.from_addr.parse() { + Ok(val) => val, + Err(e) => { + error!("The provided from_email address was unparsable:\n{e}"); + std::process::exit(1); + } + }) + .to(match config.email_addr.parse() { + Ok(val) => val, + Err(e) => { + error!( + "The provided destination email in the configuration file was unparsable:\n{e}" + ); + std::process::exit(1); + } + }) + .subject("ChronoTrack Export") .multipart( MultiPart::mixed() .multipart( @@ -392,23 +429,22 @@ fn send_email_summary(config: &Config, body_content: Vec) { .singlepart( SinglePart::builder() .header(ContentType::TEXT_PLAIN) - .body(String::from("Hello world")) + .body(String::from("This is an automated email from ChronoTrack")), ) .singlepart( SinglePart::builder() .header(ContentType::TEXT_HTML) - .body(String::from(HTML)) - ) - ) - .singlepart(attachment) - ).unwrap(); - + .body(String::from(HTML)), + ), + ) + .singlepart(attachment), + ) + .unwrap(); let mailer = SendmailTransport::new(); - + match mailer.send(&email) { Ok(val) => debug!("email sent: {:?}", val), - Err(e) => error!("Couldn't send email {}", e) + Err(e) => error!("Couldn't send email {}", e), }; - }