Working Version of EmailService

This commit is contained in:
2024-02-25 03:57:42 -03:00
parent 0dcb35e718
commit 0801fd5f7c
5 changed files with 83 additions and 28 deletions

View File

@@ -5,6 +5,8 @@ use std::env;
pub struct ConfigEmail { pub struct ConfigEmail {
pub smtp_server: String, pub smtp_server: String,
pub smtp_port: u16, pub smtp_port: u16,
pub smtp_name: String,
pub smtp_email: String,
pub smtp_username: String, pub smtp_username: String,
pub smtp_password: String, pub smtp_password: String,
} }
@@ -16,9 +18,14 @@ pub fn get_config_email() -> ConfigEmail {
let username = env::var("SMTP_USERNAME").expect("SMTP_USERNAME must be set"); let username = env::var("SMTP_USERNAME").expect("SMTP_USERNAME must be set");
let password = env::var("SMTP_PASSWORD").expect("SMTP_PASSWORD must be set"); let password = env::var("SMTP_PASSWORD").expect("SMTP_PASSWORD must be set");
let name = env::var("SMTP_NAME").expect("SMTP_NAME must be set");
let email = env::var("SMTP_EMAIL").unwrap_or(username.clone());
ConfigEmail { ConfigEmail {
smtp_server: server, smtp_server: server,
smtp_port: port.parse::<u16>().unwrap(), smtp_port: port.parse::<u16>().unwrap(),
smtp_name: name,
smtp_email: email,
smtp_username: username, smtp_username: username,
smtp_password: password, smtp_password: password,
} }

View File

@@ -1,3 +1,3 @@
pub mod config_auth; pub mod config_auth;
pub mod config_server;
pub mod config_email; pub mod config_email;
pub mod config_server;

View File

@@ -1,13 +1,35 @@
use crate::model::generic_response::GenericResponse;
use crate::model::send_message::{MessageAuthor, SendMessage}; use crate::model::send_message::{MessageAuthor, SendMessage};
use axum::extract::State; use crate::service::email_service::EmailService;
use axum::{http::StatusCode, response::IntoResponse, Extension, Json}; use axum::{http::StatusCode, response::IntoResponse, Extension, Json};
pub async fn send_message( pub async fn send_message(
Extension(auther): Extension<MessageAuthor>, Extension(email_service): Extension<EmailService>,
Extension(author): Extension<MessageAuthor>,
Json(payload): Json<SendMessage>, Json(payload): Json<SendMessage>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let mut response = payload.clone(); let mut package = payload.clone();
response.author = Some(auther).clone(); package.author = Some(author).clone();
(StatusCode::OK, Json(response)) match email_service.send_email_smtp(package).await {
Ok(_) => {},
Err(e) => {
return (
StatusCode::INTERNAL_SERVER_ERROR,
Json(GenericResponse {
status: StatusCode::INTERNAL_SERVER_ERROR.to_string(),
message: e.to_string(),
}),
)
},
};
return (
StatusCode::OK,
Json(GenericResponse {
status: StatusCode::OK.to_string(),
message: "Message sent".to_string(),
}),
);
} }

View File

@@ -16,7 +16,9 @@ fn configure_message_endpoint(router: Router) -> Router {
.route("/message", post(send_message)) .route("/message", post(send_message))
.layer(middleware::from_fn(auth_middleware)) .layer(middleware::from_fn(auth_middleware))
.layer(Extension(AuthService::new(config_auth::get_config_auth()))) .layer(Extension(AuthService::new(config_auth::get_config_auth())))
.layer(Extension(EmailService::new(config_email::get_config_email()))) .layer(Extension(EmailService::new(
config_email::get_config_email(),
)))
} }
fn configure_health_endpoint(router: Router) -> Router { fn configure_health_endpoint(router: Router) -> Router {

View File

@@ -1,41 +1,65 @@
use lettre::{
transport::smtp::authentication::Credentials, AsyncSmtpTransport, AsyncTransport, Message,
Tokio1Executor,
};
use crate::config::config_email::ConfigEmail; use crate::config::config_email::ConfigEmail;
use crate::model::send_message::{MessageAuthor, SendMessage};
use lettre::{transport::smtp::authentication::Credentials, AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor, Address};
use lettre::message::Mailbox;
#[derive(Clone)] #[derive(Clone)]
pub struct EmailService { pub struct EmailService {
mailer: AsyncSmtpTransport<Tokio1Executor> name: String,
email: String,
mailer: AsyncSmtpTransport<Tokio1Executor>,
} }
impl EmailService { impl EmailService {
pub fn new(config_email: ConfigEmail) -> Self { pub fn new(config_email: ConfigEmail) -> Self {
EmailService { EmailService {
mailer: AsyncSmtpTransport::<Tokio1Executor>::relay(&config_email.smtp_server) name: config_email.smtp_name.clone(),
email: config_email.smtp_email.clone(),
mailer: AsyncSmtpTransport::<Tokio1Executor>::starttls_relay(&config_email.smtp_server)
.unwrap() .unwrap()
.credentials(Credentials::new(config_email.smtp_username, config_email.smtp_password)) .credentials(Credentials::new(
config_email.smtp_username,
config_email.smtp_password,
))
.port(config_email.smtp_port) .port(config_email.smtp_port)
.build() .build(),
} }
} }
async fn send_email_smtp( pub async fn send_email_smtp(&self, m: SendMessage) -> Result<(), Box<dyn std::error::Error>> {
&self, let sender = m.author.clone().unwrap();
from: &str, let sender_mailbox = Mailbox::new(
to: &str, Some(sender.name), sender.email.parse::<Address>().unwrap()
subject: &str, );
body: String,
) -> Result<(), Box<dyn std::error::Error>> { let recipient_mailbox = Mailbox::new(
Some(self.name.clone()), self.email.parse::<Address>().unwrap()
);
let body = self.create_email_body(&m);
let email = Message::builder() let email = Message::builder()
.from(from.parse()?) .from(sender_mailbox.clone())
.to(to.parse()?) .to(recipient_mailbox.clone())
.subject(subject) .subject(m.subject)
.body(body.to_string())?; .body(body.to_string())?;
self.mailer.send(email).await?; self.mailer.send(email).await?;
Ok(()) Ok(())
} }
fn create_email_body(&self, m: &SendMessage) -> String {
let sender = m.author.clone().unwrap();
format!(
"From: {} <{}>\nTo: {} <{}>\nSubject: {}\n\n{}",
sender.name,
sender.email,
self.name,
self.email,
m.subject,
m.message
)
}
} }