mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
feat(import): support X-Bichon-Metadata and optimize CLI progress reporting
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::common::AddrVec;
|
||||
use crate::envelope::meta::parse_bichon_metadata;
|
||||
use crate::envelope::utils::normalize_subject;
|
||||
use crate::error::code::ErrorCode;
|
||||
use crate::error::BichonResult;
|
||||
@@ -33,6 +34,7 @@ use async_imap::types::Fetch;
|
||||
use bytes::Bytes;
|
||||
use mail_parser::{Address, HeaderName, Message, MessageParser, MimeHeaders};
|
||||
use tantivy::TantivyDocument;
|
||||
use tantivy::schema::Facet;
|
||||
use tracing::error;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -159,6 +161,36 @@ async fn extract_envelope_core(
|
||||
let envelope_id = Uuid::new_v4().to_string();
|
||||
let now = utc_now!();
|
||||
|
||||
|
||||
let mut final_tags = Vec::new();
|
||||
|
||||
if let Some(meta_header) = message.header_raw("X-Bichon-Metadata") {
|
||||
if let Some(bmd) = parse_bichon_metadata(meta_header) {
|
||||
if let Some(tags) = bmd.tags {
|
||||
let validated_tags: Result<Vec<String>, _> = tags
|
||||
.iter()
|
||||
.map(|tag| {
|
||||
Facet::from_text(tag)
|
||||
.map(|_| tag.clone())
|
||||
.map_err(|e| e)
|
||||
})
|
||||
.collect();
|
||||
|
||||
match validated_tags {
|
||||
Ok(valid_list) => {
|
||||
final_tags = valid_list;
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!(
|
||||
"Tag validation failed, ignoring all tags: {:#?}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let attachment_docs: Vec<TantivyDocument> = attachments
|
||||
.iter()
|
||||
.filter(|a| !a.inline || a.content_id.is_none())
|
||||
@@ -210,7 +242,7 @@ async fn extract_envelope_core(
|
||||
thread_id,
|
||||
attachment_count,
|
||||
regular_attachment_count: attachment_docs.len(),
|
||||
tags: None,
|
||||
tags: (!final_tags.is_empty()).then_some(final_tags),
|
||||
account_email: None,
|
||||
mailbox_name: None,
|
||||
content_hash: email_content_hash,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::base64_decode;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct BichonMetadata {
|
||||
pub account_email: Option<String>,
|
||||
pub mailbox_name: Option<String>,
|
||||
pub tags: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
pub fn parse_bichon_metadata(header_value: &str) -> Option<BichonMetadata> {
|
||||
let decoded = base64_decode!(header_value.trim());
|
||||
serde_json::from_slice(&decoded).ok()
|
||||
}
|
||||
@@ -17,4 +17,5 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod extractor;
|
||||
pub mod meta;
|
||||
pub mod utils;
|
||||
|
||||
@@ -106,6 +106,12 @@ impl EnvelopeWithAttachments {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(tags) = &self.envelope.tags {
|
||||
for tag in tags {
|
||||
doc.add_facet(fields.f_tags, tag);
|
||||
}
|
||||
}
|
||||
|
||||
doc.add_u64(
|
||||
fields.f_attachment_count,
|
||||
self.envelope.attachment_count as u64,
|
||||
@@ -166,7 +172,7 @@ impl EnvelopeWithAttachments {
|
||||
fields.f_regular_attachment_count,
|
||||
F_REGULAR_ATTACHMENT_COUNT,
|
||||
)? as usize,
|
||||
tags: if tags.is_empty() { None } else { Some(tags) },
|
||||
tags: (!tags.is_empty()).then_some(tags),
|
||||
content_hash: extract_string_field(doc, fields.f_content_hash, F_CONTENT_HASH)?,
|
||||
ingest_at: extract_i64_field(doc, fields.f_ingest_at, F_INGEST_AT)?,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user