From f338a9d964bf37af4237057777da2f7cb67087ae Mon Sep 17 00:00:00 2001 From: Ash Svitan Date: Sun, 26 Jul 2026 10:55:59 +0200 Subject: [PATCH] :heavy_plus_sign: Adds mailer library --- backend/Cargo.toml | 1 + .../up.sql | 15 +++++++++++++ backend/src/main.rs | 21 +++++++++++++++++-- backend/src/models/mod.rs | 10 +++++++-- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index f3b9dde..ffc66d9 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -12,3 +12,4 @@ diesel = { version = "2.3.2", features = ["postgres", "uuid", "chrono", "r2d2"] chrono = "0.4.42" log = "0.4.28" fern = "0.7.1" +lettre = "0.11" diff --git a/backend/migrations/2026-07-05-070623-0000_create_actions/up.sql b/backend/migrations/2026-07-05-070623-0000_create_actions/up.sql index 07d9e1f..1172120 100644 --- a/backend/migrations/2026-07-05-070623-0000_create_actions/up.sql +++ b/backend/migrations/2026-07-05-070623-0000_create_actions/up.sql @@ -8,3 +8,18 @@ CREATE TABLE IF NOT EXISTS actions created_at TIMESTAMP NOT NULL DEFAULT now(), updated_at TIMESTAMP NOT NULL DEFAULT now() ); + +CREATE TABLE IF NOT EXISTS timed_emails +( + id UUID PRIMARY KEY NOT NULL UNIQUE DEFAULT gen_random_uuid(), + name TEXT NOT NULL, + recipient TEXT NOT NULL, + subject TEXT NOT NULL, + body TEXT NOT NULL, + interval INT NOT NULL, + heartbeat TIMESTAMP NOT NULL, + expires TIMESTAMP NOT NULL, + fired BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMP NOT NULL DEFAULT now(), + updated_at TIMESTAMP NOT NULL DEFAULT now() +) diff --git a/backend/src/main.rs b/backend/src/main.rs index 8b5500d..af643bb 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -12,8 +12,10 @@ mod sh; use crate::api::action; use auth::CORS; use chrono::Local; -use diesel::r2d2::{ConnectionManager, Pool}; use diesel::PgConnection; +use diesel::r2d2::{ConnectionManager, Pool}; +use lettre::SmtpTransport; +use lettre::transport::smtp::authentication::Credentials; use models::AppState; use rocket::State; use std::env; @@ -63,7 +65,22 @@ fn rocket() -> _ { .build(manager) .expect("Failed to create pool"); - let app_data = AppState::new(pool); + let smtp_server = env::var("SMTP_SERVER").expect("SMTP_SERVER must be set"); + let smtp_port = env::var("SMTP_PORT") + .expect("SMTP_PORT must be set") + .parse::() + .expect("SMTP_PORT must be a number"); + let smtp_username = env::var("SMTP_USERNAME").expect("SMTP_USERNAME must be set"); + let smtp_password = env::var("SMTP_PASSWORD").expect("SMTP_PASSWORD must be set"); + + let creds = Credentials::new(smtp_username, smtp_password); + let mailer = SmtpTransport::relay(smtp_server.as_str()) + .unwrap() + .port(smtp_port) + .credentials(creds) + .build(); + + let app_data = AppState::new(pool, mailer); rocket::build() .manage(app_data) .attach(CORS {}) diff --git a/backend/src/models/mod.rs b/backend/src/models/mod.rs index 105f8e0..b808a14 100644 --- a/backend/src/models/mod.rs +++ b/backend/src/models/mod.rs @@ -1,5 +1,7 @@ use diesel::PgConnection; use diesel::r2d2::{ConnectionManager, Pool}; +use lettre::SmtpTransport; +use std::sync::{Arc, Mutex}; pub const DEFAULT_QUERY_LIMIT: i64 = 100; @@ -7,10 +9,14 @@ pub mod action; pub struct AppState { pub db: Pool>, + pub mailer: Arc>, } impl AppState { - pub fn new(pool: Pool>) -> Self { - Self { db: pool } + pub fn new(pool: Pool>, mailer: SmtpTransport) -> Self { + Self { + db: pool, + mailer: Arc::new(Mutex::new(mailer)), + } } }