use crate::prelude2::*;
use crate::core::http_clients::EmailClient;
use crate::core::remail::{do_send_email, SendEmailBuilder};
use crate::services::newsletter_service::SubscribeFormData;
use crate::services::newsletter_service::SubscriberEmail;
use crate::services::newsletter_service::insert_subscriber;
use crate::services::newsletter_service::store_token;
#[derive(serde::Deserialize)]
pub struct SendEmailParams {
pub subject: String,
pub receiver: String,
pub email_body: String,
}
pub async fn send_confirmation_email(
_receiver: SubscriberEmail,
_email_client: &EmailClient,
_confirmation_link: &str,
) -> Result<()> {
let html_body = format!(
"Welcome to our newsletter!<br />\
Click <a href=\"{}\">here</a> to confirm your subscription.",
_confirmation_link
);
_email_client
.send_email(&_receiver, "Welcome!", &html_body)
.await?;
Ok(())
}
pub async fn subscribe(
_form: web::Form<SubscribeFormData>,
app_state: web::Data<AppContext>,
) -> Result<HttpResponse> {
let subscription_token = crate::commons::random_token();
let confirmation_link = format!(
"https://my-api.com/subscriptions/confirm?subscription_token={}",
subscription_token
);
let new_subscriber = _form
.0
.try_into()
.map_err(|e| Error::invalid_request(format!("参数有误: error={:}", e)))?;
let mut transaction = app_state
.mysql()
.begin()
.await
.context("Failed to acquire a Postgres connection from the pool")
.map_err(Error::UnexpectedError)?;
let subscriber_id = insert_subscriber(&mut transaction, &new_subscriber)
.await
.context("Failed to insert new subscriber in the database.")
.map_err(Error::UnexpectedError)?;
store_token(&mut transaction, subscriber_id, &subscription_token)
.await
.context("Failed to store the confirmation token for a new subscriber.")
.map_err(Error::UnexpectedError)?;
transaction
.commit()
.await
.context("Failed to commit SQL transaction to store a new subscriber.")
.map_err(Error::UnexpectedError)?;
send_confirmation_email(
new_subscriber.email,
&app_state.email_client,
&confirmation_link,
)
.await
.context("Failed to send a confirmation email.")
.map_err(Error::UnexpectedError)?;
Ok(HttpResponse::Ok().body(confirmation_link.to_string()))
}
pub async fn send_email(
_form: web::Form<SendEmailParams>,
_app_state: web::Data<crate::server::AppContext>,
) -> impl Responder {
let receiver = match SubscriberEmail::parse(_form.0.receiver) {
Ok(email) => email,
Err(e) => {
return format!("Validation failed: {:?}", e);
}
};
match _app_state
.email_client
.send_email(
&receiver,
_form.0.subject.as_ref(),
_form.0.email_body.as_ref(),
)
.await
{
Ok(()) => {
log::info!("New email send successful");
"Ok".to_string()
}
Err(e) => {
format!("Failed to SendEmail: {:?}", e)
}
}
}
pub async fn send_emails() -> impl Responder {
match do_send_email(&SendEmailBuilder {
from: "asdasdf@126.com",
passwd: "asdfasdf",
smtp: "smtp.gmail.com",
receiver: "asdfsadf@qq.com",
_type: "text",
title: "激活账号",
content: "激活账号sad",
file_path: None,
})
.await
{
Ok(_) => {}
Err(e) => {
log::error!("Failed to send email: {:?}", e);
}
}
"Ok".to_string()
}