Skip to content

Commit

Permalink
feat: add mailgun client to axum state
Browse files Browse the repository at this point in the history
  • Loading branch information
jooakar committed Aug 11, 2024
1 parent cfd22df commit 74a432a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 22 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ time = { version = "0.3.36", optional = true }
fontdb = { version = "0.17.0", optional = true }
typst-assets = { version = "0.11.1", features = ["fonts"], optional = true }
tempdir = { version = "0.3.7", optional = true }
tokio-rayon = "2.1.0"
reqwest = { version = "0.12.5", features = ["multipart"] }

[dev-dependencies]
Expand Down
34 changes: 13 additions & 21 deletions src/api/invoices.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::database::DatabaseConnection;
use crate::database::{DatabaseConnection, MailgunClient};
use crate::error::Error;
use crate::models::{Address, Attachment, Invoice, InvoiceRow};
use axum::{async_trait, body::Bytes, http::StatusCode, Json};
Expand Down Expand Up @@ -197,21 +197,15 @@ pub async fn list_all(mut conn: DatabaseConnection) -> Result<Json<Vec<Populated
}

#[allow(dead_code)]
pub async fn send_mail(invoice: &PopulatedInvoice) -> Result<(), Error> {
let client = reqwest::Client::new();
pub async fn send_mail(
mailgun_client: MailgunClient,
invoice: &PopulatedInvoice,
) -> Result<(), Error> {
let invoice_recipient = format!("{} <{}>", invoice.recipient_name, invoice.recipient_email);
let form = reqwest::multipart::Form::new()
.text(
"from",
std::env::var("MAILGUN_FROM").unwrap_or(String::from("")),
)
.text(
"to",
format!("{} <{}>", invoice.recipient_name, invoice.recipient_email),
)
.text(
"to",
std::env::var("MAILGUN_TO").unwrap_or(String::from("")),
)
.text("from", mailgun_client.from)
.text("to", mailgun_client.default_to)
.text("cc", invoice_recipient)
.text("subject", format!("Uusi lasku #{}", invoice.id))
.text("html", format!("Uusi lasku #{}", invoice.id));

Expand All @@ -228,12 +222,10 @@ pub async fn send_mail(invoice: &PopulatedInvoice) -> Result<(), Error> {
))
})?;

let response = client
.post(std::env::var("MAILGUN_URL").unwrap_or(String::from("")))
.basic_auth(
std::env::var("MAILGUN_USER").unwrap_or(String::from("")),
Some(std::env::var("MAILGUN_PASSWORD").unwrap_or(String::from(""))),
)
let response = mailgun_client
.client
.post(mailgun_client.url)
.basic_auth(mailgun_client.api_user, Some(mailgun_client.api_key))
.multipart(form)
.send()
.await?;
Expand Down
35 changes: 35 additions & 0 deletions src/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod invoices;
#[derive(FromRef, Clone)]
pub struct State {
pool: bb8::Pool<AsyncDieselConnectionManager<AsyncPgConnection>>,
mailgun_client: MailgunClient,
for_garde: (),
}

Expand All @@ -21,6 +22,15 @@ pub async fn new() -> State {
let db_url = std::env::var("DATABASE_URL").expect("No DATABASE_URL in env");
let config = AsyncDieselConnectionManager::<diesel_async::AsyncPgConnection>::new(db_url);

let mailgun_client = MailgunClient {
client: reqwest::Client::new(),
url: std::env::var("MAILGUN_URL").expect("No MAILGUN_URL in env"),
api_user: std::env::var("MAILGUN_USER").expect("No MAILGUN_USER in env"),
api_key: std::env::var("MAILGUN_PASSWORD").expect("No MAILGUN_PASSWORD in env"),
default_to: std::env::var("MAILGUN_TO").unwrap_or(String::from("")),
from: std::env::var("MAILGUN_FROM").unwrap_or(String::from("")),
};

State {
pool: if cfg!(test) {
let pool = bb8::Pool::builder()
Expand All @@ -40,6 +50,7 @@ pub async fn new() -> State {
.await
.expect("Failed to build database pool")
},
mailgun_client,
for_garde: (),
}
}
Expand All @@ -48,6 +59,30 @@ pub struct DatabaseConnection(
pub bb8::PooledConnection<'static, AsyncDieselConnectionManager<AsyncPgConnection>>,
);

#[derive(Clone)]
pub struct MailgunClient {
pub client: reqwest::Client,
pub url: String,
pub api_user: String,
pub api_key: String,
pub default_to: String,
pub from: String,
}

#[async_trait]
impl<S> FromRequestParts<S> for MailgunClient
where
S: Send + Sync,
State: FromRef<S>,
{
type Rejection = crate::error::Error;

async fn from_request_parts(_parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let state = State::from_ref(state);
Ok(state.mailgun_client)
}
}

#[async_trait]
impl<S> FromRequestParts<S> for DatabaseConnection
where
Expand Down

0 comments on commit 74a432a

Please sign in to comment.