mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
feat: use fjall to store detached emails and attachments
This commit is contained in:
@@ -1,19 +1,17 @@
|
||||
use std::collections::HashSet;
|
||||
use std::{collections::HashSet, io::Cursor};
|
||||
|
||||
use crate::{
|
||||
modules::{
|
||||
envelope::extractor::reattach_eml_content,
|
||||
error::{code::ErrorCode, BichonResult},
|
||||
settings::dir::DATA_DIR_MANAGER,
|
||||
utils::compute_content_hash,
|
||||
},
|
||||
raise_error,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use mail_parser::MessageParser;
|
||||
use poem_openapi::Object;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::fs::File;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize, Object)]
|
||||
pub struct AttachmentMetadata {
|
||||
@@ -34,8 +32,8 @@ pub async fn retrieve_attachment_content(
|
||||
account_id: u64,
|
||||
envelope_id: String,
|
||||
content_hash: &str,
|
||||
) -> BichonResult<File> {
|
||||
let (envelope, eml) = reattach_eml_content(account_id, envelope_id).await?;
|
||||
) -> BichonResult<Cursor<Bytes>> {
|
||||
let (_, eml) = reattach_eml_content(account_id, envelope_id).await?;
|
||||
let message = MessageParser::default().parse(&eml).ok_or_else(|| {
|
||||
raise_error!(
|
||||
"Failed to parse parent EML".into(),
|
||||
@@ -53,20 +51,7 @@ pub async fn retrieve_attachment_content(
|
||||
ErrorCode::ResourceNotFound
|
||||
)
|
||||
})?;
|
||||
let mut path = DATA_DIR_MANAGER.temp_dir.clone();
|
||||
path.push(format!("{}.eml", envelope.content_hash));
|
||||
{
|
||||
let mut file = File::create(&path)
|
||||
.await
|
||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?;
|
||||
file.write_all(attachment_content)
|
||||
.await
|
||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?;
|
||||
}
|
||||
let file = File::open(&path)
|
||||
.await
|
||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?;
|
||||
Ok(file)
|
||||
Ok(Cursor::new(Bytes::copy_from_slice(attachment_content)))
|
||||
}
|
||||
|
||||
pub async fn retrieve_nested_attachment_content(
|
||||
@@ -74,7 +59,7 @@ pub async fn retrieve_nested_attachment_content(
|
||||
envelope_id: String,
|
||||
content_hash: &str,
|
||||
nested_content_hash: &str,
|
||||
) -> BichonResult<File> {
|
||||
) -> BichonResult<Cursor<Bytes>> {
|
||||
let (_, eml) = reattach_eml_content(account_id, envelope_id).await?;
|
||||
let parent_message = MessageParser::default().parse(&eml).ok_or_else(|| {
|
||||
raise_error!(
|
||||
@@ -114,18 +99,5 @@ pub async fn retrieve_nested_attachment_content(
|
||||
)
|
||||
})?;
|
||||
|
||||
let mut path = DATA_DIR_MANAGER.temp_dir.clone();
|
||||
path.push(format!("{}.eml", nested_content_hash));
|
||||
{
|
||||
let mut file = File::create(&path)
|
||||
.await
|
||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?;
|
||||
file.write_all(attachment_content)
|
||||
.await
|
||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?;
|
||||
}
|
||||
let file = File::open(&path)
|
||||
.await
|
||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?;
|
||||
Ok(file)
|
||||
Ok(Cursor::new(Bytes::copy_from_slice(attachment_content)))
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ use crate::modules::envelope::extractor::{
|
||||
extract_envelope_from_nested_message, reattach_eml_content,
|
||||
};
|
||||
use crate::modules::error::code::ErrorCode;
|
||||
use crate::modules::indexer::envelope::Envelope;
|
||||
use crate::modules::blob::envelope::Envelope;
|
||||
use crate::modules::utils::compute_content_hash;
|
||||
use crate::{modules::error::BichonResult, raise_error};
|
||||
use mail_parser::{MessageParser, MimeHeaders};
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::modules::blob::manager::ENVELOPE_INDEX_MANAGER;
|
||||
use crate::modules::blob::storage::BLOB_MANAGER;
|
||||
use crate::modules::error::BichonResult;
|
||||
use crate::modules::indexer::attachment::ATTACHMENT_INDEX_MANAGER;
|
||||
use crate::modules::indexer::eml::EML_INDEX_MANAGER;
|
||||
use crate::modules::indexer::manager::ENVELOPE_INDEX_MANAGER;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub async fn delete_messages_impl(request: HashMap<u64, Vec<String>>) -> BichonResult<()> {
|
||||
@@ -27,8 +26,7 @@ pub async fn delete_messages_impl(request: HashMap<u64, Vec<String>>) -> BichonR
|
||||
.get_orphan_hashes_in_memory(request.clone())
|
||||
.await?;
|
||||
if !content_hashes.is_empty() {
|
||||
EML_INDEX_MANAGER.delete(&content_hashes).await?;
|
||||
ATTACHMENT_INDEX_MANAGER.delete(&content_hashes).await?;
|
||||
BLOB_MANAGER.delete(&content_hashes, &content_hashes)?;
|
||||
}
|
||||
ENVELOPE_INDEX_MANAGER
|
||||
.delete_envelopes_multi_account(request)
|
||||
|
||||
@@ -20,7 +20,7 @@ use crate::{
|
||||
modules::{
|
||||
account::migration::AccountModel,
|
||||
error::{code::ErrorCode, BichonResult},
|
||||
indexer::{envelope::Envelope, manager::ENVELOPE_INDEX_MANAGER},
|
||||
blob::{envelope::Envelope, manager::ENVELOPE_INDEX_MANAGER},
|
||||
rest::response::DataPage,
|
||||
},
|
||||
raise_error,
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
modules::{
|
||||
duckdb::init::duckdb,
|
||||
error::{code::ErrorCode, BichonResult},
|
||||
indexer::{envelope::Envelope, manager::ENVELOPE_INDEX_MANAGER},
|
||||
blob::{envelope::Envelope, manager::ENVELOPE_INDEX_MANAGER},
|
||||
rest::response::DataPage,
|
||||
},
|
||||
raise_error,
|
||||
|
||||
Reference in New Issue
Block a user