|
|
|
@ -7,9 +7,16 @@ use rocket::serde::json::Json;
|
|
|
|
|
use rocket::http::Status;
|
|
|
|
|
use rocket::Request;
|
|
|
|
|
use mail_builder::MessageBuilder;
|
|
|
|
|
use serde::Serialize;
|
|
|
|
|
|
|
|
|
|
pub struct ClientIp(Option<IpAddr>);
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize)]
|
|
|
|
|
pub struct Response {
|
|
|
|
|
status: &'static str,
|
|
|
|
|
message: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[rocket::async_trait]
|
|
|
|
|
impl<'r> FromRequest<'r> for ClientIp {
|
|
|
|
|
type Error = Infallible;
|
|
|
|
@ -20,12 +27,15 @@ impl<'r> FromRequest<'r> for ClientIp {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[post("/api/contact/<slug>", data = "<fields>")]
|
|
|
|
|
pub async fn handler(state: &rocket::State<crate::State>, client_ip: ClientIp, slug: &str, fields: Json<HashMap<&str, &str>>) -> Result<String, (Status, String)> {
|
|
|
|
|
pub async fn handler(state: &rocket::State<crate::State>, client_ip: ClientIp, slug: &str, fields: Json<HashMap<&str, &str>>) -> Result<Json<Response>, (Status, Json<Response>)> {
|
|
|
|
|
{
|
|
|
|
|
let rate_limit = &state.rate_limit;
|
|
|
|
|
|
|
|
|
|
if client_ip.0.is_none() {
|
|
|
|
|
return Err((Status::InternalServerError, "Could not identify client IP".to_string()))
|
|
|
|
|
return Err((Status::InternalServerError, Json(Response {
|
|
|
|
|
status: "error",
|
|
|
|
|
message: Some("Could not identify client IP".to_string())
|
|
|
|
|
})))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let client_ip = client_ip.0.unwrap();
|
|
|
|
@ -33,7 +43,10 @@ pub async fn handler(state: &rocket::State<crate::State>, client_ip: ClientIp, s
|
|
|
|
|
let rate_limit_outcome = rate_limit.check_key(&client_ip);
|
|
|
|
|
|
|
|
|
|
if let Err(_not_until) = rate_limit_outcome {
|
|
|
|
|
return Err((Status::TooManyRequests, "Rate limit error".to_string()));
|
|
|
|
|
return Err((Status::TooManyRequests, Json(Response {
|
|
|
|
|
status: "ratelimit",
|
|
|
|
|
message: Some("Too many messages, play nice friend".to_string()),
|
|
|
|
|
})));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
println!("Passed rate limit");
|
|
|
|
@ -47,7 +60,10 @@ pub async fn handler(state: &rocket::State<crate::State>, client_ip: ClientIp, s
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if form_conf.is_none() {
|
|
|
|
|
return Err((Status::NotFound, "Not found".to_string()));
|
|
|
|
|
return Err((Status::NotFound, Json(Response {
|
|
|
|
|
status: "notfound",
|
|
|
|
|
message: Some(format!("Form ID {} not found", slug))
|
|
|
|
|
})));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let form_conf = form_conf.unwrap();
|
|
|
|
@ -62,7 +78,10 @@ Form fields:", form_conf.name);
|
|
|
|
|
let required = field.required;
|
|
|
|
|
|
|
|
|
|
if value_opt.is_none() && required {
|
|
|
|
|
return Err((Status::BadRequest, format!("Missing field: {}", field.name)))
|
|
|
|
|
return Err((Status::BadRequest, Json(Response {
|
|
|
|
|
status: "error",
|
|
|
|
|
message: Some(format!("Missing field: {}", field.name))
|
|
|
|
|
})))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
message_text.push_str(&format!(" - {}: {}\n", field.name, value_opt.unwrap_or(&"[empty]")));
|
|
|
|
@ -81,7 +100,10 @@ Form fields:", form_conf.name);
|
|
|
|
|
if let Err(err) = connection_result {
|
|
|
|
|
println!("Error connecting to server: {}", err.to_string());
|
|
|
|
|
|
|
|
|
|
return Err((Status::InternalServerError, "Could not send message".to_string()));
|
|
|
|
|
return Err((Status::InternalServerError, Json(Response {
|
|
|
|
|
status: "error",
|
|
|
|
|
message: Some("Could not send message".to_string())
|
|
|
|
|
})));
|
|
|
|
|
} else {
|
|
|
|
|
let mut connection = connection_result.unwrap();
|
|
|
|
|
println!("Connected to mail server");
|
|
|
|
@ -89,11 +111,17 @@ Form fields:", form_conf.name);
|
|
|
|
|
if let Err(err) = connection.send(message).await {
|
|
|
|
|
println!("Error sending email: {}", err.to_string());
|
|
|
|
|
|
|
|
|
|
return Err((Status::InternalServerError, "Could not send message".to_string()));
|
|
|
|
|
return Err((Status::InternalServerError, Json(Response {
|
|
|
|
|
status: "error",
|
|
|
|
|
message: Some("Could not send message".to_string())
|
|
|
|
|
})));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
println!("Message sent");
|
|
|
|
|
return Ok("Message sent".to_string());
|
|
|
|
|
return Ok(Json(Response {
|
|
|
|
|
status: "Message sent",
|
|
|
|
|
message: None
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|