|
@@ -1,12 +1,14 @@
|
|
|
|
+use std::fs;
|
|
use crate::config::Config;
|
|
use crate::config::Config;
|
|
use crate::indexes::{Indexes, SerializableMessage, SerializableThread};
|
|
use crate::indexes::{Indexes, SerializableMessage, SerializableThread};
|
|
use serde::{Deserialize, Serialize};
|
|
use serde::{Deserialize, Serialize};
|
|
-use std::fs::File;
|
|
|
|
-use std::io::{BufReader};
|
|
|
|
|
|
+use std::fs::{File, metadata};
|
|
|
|
+use std::io::{BufReader, Read};
|
|
use std::net::{IpAddr, SocketAddr};
|
|
use std::net::{IpAddr, SocketAddr};
|
|
use std::str::FromStr;
|
|
use std::str::FromStr;
|
|
use chrono::{DateTime, Utc};
|
|
use chrono::{DateTime, Utc};
|
|
use warp::Filter;
|
|
use warp::Filter;
|
|
|
|
+use warp::fs::file;
|
|
use warp::http::StatusCode;
|
|
use warp::http::StatusCode;
|
|
use crate::{create_folder_lar, delete_folder_lar, rename_folder_lar};
|
|
use crate::{create_folder_lar, delete_folder_lar, rename_folder_lar};
|
|
use crate::models::MailAddress;
|
|
use crate::models::MailAddress;
|
|
@@ -47,6 +49,14 @@ pub async fn run_api() {
|
|
.and(warp::get())
|
|
.and(warp::get())
|
|
.and(warp::query::<GetEmailQuery>())
|
|
.and(warp::query::<GetEmailQuery>())
|
|
.and_then(get_email_handle))
|
|
.and_then(get_email_handle))
|
|
|
|
+ .or(warp::path("get_attachments_info")
|
|
|
|
+ .and(warp::get())
|
|
|
|
+ .and(warp::query::<GetAttachmentsInfoQuery>())
|
|
|
|
+ .and_then(get_attachments_info_handle))
|
|
|
|
+ .or(warp::path("get_attachment")
|
|
|
|
+ .and(warp::get())
|
|
|
|
+ .and(warp::query::<GetAttachmentQuery>())
|
|
|
|
+ .and_then(get_attachment_handle))
|
|
.or(warp::path("search")
|
|
.or(warp::path("search")
|
|
.and(warp::get())
|
|
.and(warp::get())
|
|
.and(warp::query::<SearchQuery>())
|
|
.and(warp::query::<SearchQuery>())
|
|
@@ -70,6 +80,64 @@ pub async fn run_api() {
|
|
warp::serve(routes).run(addr).await;
|
|
warp::serve(routes).run(addr).await;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// functions
|
|
|
|
+pub async fn get_attachment(folder: String, id: String, name: String) -> GetAttachmentResponse{
|
|
|
|
+ let attachment_path = Config::global().out_dir.clone()
|
|
|
|
+ .join(folder.clone())
|
|
|
|
+ .join(".attachments")
|
|
|
|
+ .join(id)
|
|
|
|
+ .join(name.clone());
|
|
|
|
+ let file_result = File::open(attachment_path);
|
|
|
|
+ let mut file = match file_result {
|
|
|
|
+ Ok(f) => f,
|
|
|
|
+ Err(_) => {return GetAttachmentResponse{ name, data: vec![] }}
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ let mut buffer = Vec::new();
|
|
|
|
+ let read_result = file.read_to_end(&mut buffer);
|
|
|
|
+ match read_result {
|
|
|
|
+ Ok(_) => GetAttachmentResponse{ name, data: buffer },
|
|
|
|
+ Err(e) => GetAttachmentResponse{ name, data: vec![] },
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+pub async fn get_attachments_info(folder: String, id: String) -> String{
|
|
|
|
+ let mut attachments_info: Vec<AttachmentInfo> = Vec::new();
|
|
|
|
+ let attachments_path = Config::global().out_dir.clone()
|
|
|
|
+ .join(folder.clone())
|
|
|
|
+ .join(".attachments")
|
|
|
|
+ .join(id);
|
|
|
|
+
|
|
|
|
+ let entries = fs::read_dir(attachments_path);
|
|
|
|
+ match entries {
|
|
|
|
+ Ok(entries) => {
|
|
|
|
+ for entry in entries {
|
|
|
|
+ match entry {
|
|
|
|
+ Ok(entry) => {
|
|
|
|
+ let path = entry.path();
|
|
|
|
+ if path.is_file() {
|
|
|
|
+ match metadata(&path) {
|
|
|
|
+ Ok(meta) => {
|
|
|
|
+ let file_size = meta.len();
|
|
|
|
+ attachments_info.push(AttachmentInfo{
|
|
|
|
+ name: entry.file_name().to_str().unwrap().to_string(),
|
|
|
|
+ size: file_size,
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ Err(_) => {}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ Err(_) => {}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ Err(_) => {}
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ serde_json::to_string(&attachments_info).unwrap()
|
|
|
|
+}
|
|
|
|
+
|
|
pub async fn get_folders() -> String {
|
|
pub async fn get_folders() -> String {
|
|
let mut folders: Vec<String> = Vec::new();
|
|
let mut folders: Vec<String> = Vec::new();
|
|
for entry in std::fs::read_dir(Config::global().out_dir.clone())
|
|
for entry in std::fs::read_dir(Config::global().out_dir.clone())
|
|
@@ -89,7 +157,7 @@ pub async fn get_folders() -> String {
|
|
serde_json::to_string(&folders).unwrap()
|
|
serde_json::to_string(&folders).unwrap()
|
|
}
|
|
}
|
|
|
|
|
|
-pub async fn get_email(id: String) -> String {
|
|
|
|
|
|
+pub async fn get_email(id: String) -> String { // TODO replace with Indexes::get_messages()
|
|
let messages_path = Config::global()
|
|
let messages_path = Config::global()
|
|
.out_dir
|
|
.out_dir
|
|
.clone()
|
|
.clone()
|
|
@@ -196,6 +264,37 @@ pub async fn get_sorted_threads_by_date(folder: String) -> String {
|
|
}
|
|
}
|
|
|
|
|
|
// Handlers
|
|
// Handlers
|
|
|
|
+#[derive(Deserialize)]
|
|
|
|
+struct GetAttachmentQuery {
|
|
|
|
+ folder: String,
|
|
|
|
+ id: String,
|
|
|
|
+ name: String
|
|
|
|
+}
|
|
|
|
+#[derive(Deserialize, Serialize)]
|
|
|
|
+struct GetAttachmentResponse{
|
|
|
|
+ pub name: String,
|
|
|
|
+ pub data: Vec<u8>
|
|
|
|
+}
|
|
|
|
+async fn get_attachment_handle(query: GetAttachmentQuery) -> Result<impl warp::Reply, warp::Rejection>{
|
|
|
|
+ let result: GetAttachmentResponse = get_attachment(query.folder, query.id, query.name).await;
|
|
|
|
+ Ok(warp::reply::json(&result))
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#[derive(Deserialize)]
|
|
|
|
+struct GetAttachmentsInfoQuery {
|
|
|
|
+ folder: String,
|
|
|
|
+ id: String
|
|
|
|
+}
|
|
|
|
+#[derive(Deserialize, Serialize)]
|
|
|
|
+struct AttachmentInfo{
|
|
|
|
+ pub name: String,
|
|
|
|
+ pub size: u64
|
|
|
|
+}
|
|
|
|
+async fn get_attachments_info_handle(query: GetAttachmentsInfoQuery) -> Result<impl warp::Reply, warp::Rejection>{
|
|
|
|
+ let result: Vec<AttachmentInfo> = serde_json::from_str(&*get_attachments_info(query.folder, query.id).await).unwrap();
|
|
|
|
+ Ok(warp::reply::json(&result))
|
|
|
|
+}
|
|
|
|
+
|
|
#[derive(Deserialize, Serialize)]
|
|
#[derive(Deserialize, Serialize)]
|
|
struct ErrorResponse {
|
|
struct ErrorResponse {
|
|
error: String,
|
|
error: String,
|
|
@@ -230,7 +329,6 @@ async fn get_email_handle(query: GetEmailQuery) -> Result<impl warp::Reply, warp
|
|
struct GetThreadQuery {
|
|
struct GetThreadQuery {
|
|
id: u32,
|
|
id: u32,
|
|
}
|
|
}
|
|
-
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
#[derive(Serialize, Deserialize)]
|
|
struct GetThreadResponse{
|
|
struct GetThreadResponse{
|
|
pub id: u32,
|
|
pub id: u32,
|
|
@@ -254,7 +352,6 @@ impl GetThreadResponse{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
async fn get_thread_handle(query: GetThreadQuery) -> Result<impl warp::Reply, warp::Rejection> {
|
|
async fn get_thread_handle(query: GetThreadQuery) -> Result<impl warp::Reply, warp::Rejection> {
|
|
let result: GetThreadResponse = serde_json::from_str(&*get_thread(query.id).await).unwrap();
|
|
let result: GetThreadResponse = serde_json::from_str(&*get_thread(query.id).await).unwrap();
|
|
Ok(warp::reply::json(&result))
|
|
Ok(warp::reply::json(&result))
|