2025-10-06 20:06:43 -03:00
|
|
|
use actix_web::{post, web, HttpResponse, Result};
|
|
|
|
|
use lettre::{
|
|
|
|
|
message::header::ContentType,
|
|
|
|
|
transport::smtp::authentication::Credentials,
|
|
|
|
|
Message,
|
|
|
|
|
SmtpTransport,
|
|
|
|
|
Transport
|
|
|
|
|
};
|
2025-10-06 10:30:17 -03:00
|
|
|
use log::info;
|
2025-10-06 20:06:43 -03:00
|
|
|
use serde::{Deserialize, Serialize};
|
2025-10-06 10:30:17 -03:00
|
|
|
|
2025-10-06 20:06:43 -03:00
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
|
pub struct EmailRequest {
|
|
|
|
|
pub to: String,
|
2025-10-06 10:30:17 -03:00
|
|
|
pub subject: String,
|
2025-10-06 20:06:43 -03:00
|
|
|
pub body: String,
|
2025-10-06 10:30:17 -03:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:06:43 -03:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct EmailConfig {
|
|
|
|
|
pub from: String,
|
|
|
|
|
pub server: String,
|
|
|
|
|
pub port: u16,
|
|
|
|
|
pub username: String,
|
|
|
|
|
pub password: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn send_email_impl(
|
|
|
|
|
config: &EmailConfig,
|
|
|
|
|
to: &str,
|
|
|
|
|
subject: &str,
|
|
|
|
|
body: &str,
|
|
|
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
2025-10-06 10:30:17 -03:00
|
|
|
let email = Message::builder()
|
2025-10-06 20:06:43 -03:00
|
|
|
.from(config.from.parse()?)
|
|
|
|
|
.to(to.parse()?)
|
2025-10-06 10:30:17 -03:00
|
|
|
.subject(subject)
|
2025-10-06 20:06:43 -03:00
|
|
|
.header(ContentType::TEXT_PLAIN)
|
|
|
|
|
.body(body.to_string())?;
|
2025-10-06 10:30:17 -03:00
|
|
|
|
|
|
|
|
let creds = Credentials::new(config.username.clone(), config.password.clone());
|
|
|
|
|
|
2025-10-06 20:06:43 -03:00
|
|
|
let mailer = SmtpTransport::relay(&config.server)?
|
2025-10-06 10:30:17 -03:00
|
|
|
.port(config.port)
|
|
|
|
|
.credentials(creds)
|
2025-10-06 20:06:43 -03:00
|
|
|
.build();
|
2025-10-06 10:30:17 -03:00
|
|
|
|
2025-10-06 20:06:43 -03:00
|
|
|
match mailer.send(&email) {
|
|
|
|
|
Ok(_) => {
|
|
|
|
|
info!("Email sent to {}", to);
|
|
|
|
|
Ok(())
|
2025-10-06 10:30:17 -03:00
|
|
|
}
|
|
|
|
|
Err(e) => {
|
2025-10-06 20:06:43 -03:00
|
|
|
log::error!("Failed to send email: {}", e);
|
|
|
|
|
Err(Box::new(e))
|
2025-10-06 10:30:17 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:06:43 -03:00
|
|
|
#[post("/email/send")]
|
2025-10-06 10:30:17 -03:00
|
|
|
pub async fn send_email(
|
2025-10-06 20:06:43 -03:00
|
|
|
config: web::Data<crate::config::AppConfig>,
|
|
|
|
|
payload: web::Json<EmailRequest>,
|
|
|
|
|
) -> Result<HttpResponse> {
|
|
|
|
|
let email_request = payload.into_inner();
|
|
|
|
|
|
|
|
|
|
match send_email_impl(&config.email, &email_request.to, &email_request.subject, &email_request.body).await {
|
|
|
|
|
Ok(_) => Ok(HttpResponse::Ok().json(serde_json::json!({"status": "sent"}))),
|
|
|
|
|
Err(e) => Ok(HttpResponse::InternalServerError().json(serde_json::json!({"error": e.to_string()})))
|
|
|
|
|
}
|
2025-10-06 10:30:17 -03:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:06:43 -03:00
|
|
|
#[post("/email/test")]
|
|
|
|
|
pub async fn test_email(
|
|
|
|
|
config: web::Data<crate::config::AppConfig>,
|
|
|
|
|
) -> Result<HttpResponse> {
|
|
|
|
|
match send_email_impl(&config.email, &config.email.from, "Test Email", "This is a test email from BotServer").await {
|
|
|
|
|
Ok(_) => Ok(HttpResponse::Ok().json(serde_json::json!({"status": "test_sent"}))),
|
|
|
|
|
Err(e) => Ok(HttpResponse::InternalServerError().json(serde_json::json!({"error": e.to_string()})))
|
|
|
|
|
}
|
2025-10-06 10:30:17 -03:00
|
|
|
}
|