this repo has no description
1use crate::api::error::{ApiError, AtpJson};
2use crate::auth::BearerAuthAdmin;
3use crate::state::AppState;
4use crate::types::Did;
5use axum::{
6 Json,
7 extract::State,
8 http::StatusCode,
9 response::{IntoResponse, Response},
10};
11use serde::{Deserialize, Serialize};
12use tracing::{error, warn};
13
14#[derive(Deserialize)]
15#[serde(rename_all = "camelCase")]
16pub struct SendEmailInput {
17 pub recipient_did: Did,
18 pub sender_did: Did,
19 pub content: String,
20 pub subject: Option<String>,
21 pub comment: Option<String>,
22}
23
24#[derive(Serialize)]
25pub struct SendEmailOutput {
26 pub sent: bool,
27}
28
29pub async fn send_email(
30 State(state): State<AppState>,
31 _auth: BearerAuthAdmin,
32 AtpJson(input): AtpJson<SendEmailInput>,
33) -> Response {
34 let content = input.content.trim();
35 if content.is_empty() {
36 return ApiError::InvalidRequest("content is required".into()).into_response();
37 }
38 let user = sqlx::query!(
39 "SELECT id, email, handle FROM users WHERE did = $1",
40 input.recipient_did.as_str()
41 )
42 .fetch_optional(&state.db)
43 .await;
44 let (user_id, email, handle) = match user {
45 Ok(Some(row)) => {
46 let email = match row.email {
47 Some(e) => e,
48 None => {
49 return ApiError::NoEmail.into_response();
50 }
51 };
52 (row.id, email, row.handle)
53 }
54 Ok(None) => {
55 return ApiError::AccountNotFound.into_response();
56 }
57 Err(e) => {
58 error!("DB error in send_email: {:?}", e);
59 return ApiError::InternalError(None).into_response();
60 }
61 };
62 let hostname = std::env::var("PDS_HOSTNAME").unwrap_or_else(|_| "localhost".to_string());
63 let subject = input
64 .subject
65 .clone()
66 .unwrap_or_else(|| format!("Message from {}", hostname));
67 let item = crate::comms::NewComms::email(
68 user_id,
69 crate::comms::CommsType::AdminEmail,
70 email,
71 subject,
72 content.to_string(),
73 );
74 let result = crate::comms::enqueue_comms(&state.db, item).await;
75 match result {
76 Ok(_) => {
77 tracing::info!(
78 "Admin email queued for {} ({})",
79 handle,
80 input.recipient_did
81 );
82 (StatusCode::OK, Json(SendEmailOutput { sent: true })).into_response()
83 }
84 Err(e) => {
85 warn!("Failed to enqueue admin email: {:?}", e);
86 (StatusCode::OK, Json(SendEmailOutput { sent: false })).into_response()
87 }
88 }
89}