mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
fix: Imported emails and UTF-8 folders missing #182
This commit is contained in:
@@ -60,3 +60,75 @@ pub fn determine_folder(labels_raw: &str) -> String {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use mail_parser::{HeaderValue, MessageParser};
|
||||
|
||||
use super::*;
|
||||
|
||||
fn parse_x_gmail_labels(raw_message: &[u8]) -> Option<String> {
|
||||
// MessageParser::new() has an empty header_map so the hardcoded match at
|
||||
// parsers/header.rs:76 treats ALL unknown headers as raw (no RFC 2047
|
||||
// decoding). We need three things to get decoding:
|
||||
// 1. A non-empty header_map (so the else branch runs)
|
||||
// 2. default_header_text() so the fallback fn is parse_unstructured
|
||||
// 3. OR register X-Gmail-Labels explicitly via header_text()
|
||||
let message = MessageParser::new()
|
||||
.with_minimal_headers()
|
||||
.default_header_text()
|
||||
.parse(raw_message)?;
|
||||
let value: &HeaderValue<'_> = message.header("X-Gmail-Labels")?;
|
||||
value.as_text().map(|s| s.to_string())
|
||||
}
|
||||
|
||||
/// Construct a raw MIME message with RFC 2047 encoded X-Gmail-Labels,
|
||||
/// parse it, and verify the header is correctly decoded.
|
||||
fn build_email(x_gmail_labels: &str) -> Vec<u8> {
|
||||
format!(
|
||||
"From: sender@example.com\r\n\
|
||||
To: recipient@example.com\r\n\
|
||||
Subject: Test\r\n\
|
||||
X-Gmail-Labels: {}\r\n\
|
||||
\r\n\
|
||||
Body text here.\r\n",
|
||||
x_gmail_labels
|
||||
)
|
||||
.into_bytes()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rfc2047_encoded_labels_are_decoded() {
|
||||
// Exactly the format the user reported: French Gmail labels
|
||||
let raw = build_email("=?UTF-8?Q?Corbeille?=, =?UTF-8?Q?Messages_archiv=C3=A9s?=");
|
||||
let labels = parse_x_gmail_labels(&raw).expect("failed to parse X-Gmail-Labels");
|
||||
|
||||
// mail-parser decodes RFC 2047 header values during initial parsing.
|
||||
// The decoded text should NOT contain raw =?UTF-8?Q?... sequences.
|
||||
assert!(!labels.contains("=?UTF-8"), "labels still encoded: {labels:?}");
|
||||
assert!(labels.contains("Corbeille"), "missing 'Corbeille': {labels:?}");
|
||||
assert!(
|
||||
labels.contains("archivés"),
|
||||
"missing decoded 'archivés': {labels:?}",
|
||||
);
|
||||
|
||||
// Full pipeline: decoded labels → determine_folder
|
||||
let folder = determine_folder(&labels);
|
||||
assert_eq!(folder, "Corbeille");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plain_ascii_labels_passthrough() {
|
||||
let raw = build_email("Inbox, Important");
|
||||
let labels = parse_x_gmail_labels(&raw).expect("failed to parse X-Gmail-Labels");
|
||||
assert_eq!(labels, "Inbox, Important");
|
||||
assert_eq!(determine_folder(&labels), "Important");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_x_gmail_labels_header() {
|
||||
let raw = b"From: sender@example.com\r\nTo: r@example.com\r\n\r\nBody.\r\n";
|
||||
let message = MessageParser::new().parse(raw.as_slice()).unwrap();
|
||||
assert!(message.header("X-Gmail-Labels").is_none());
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -28,7 +28,6 @@ use bichon_core::envelope::meta::{parse_bichon_metadata, BichonMetadata};
|
||||
use console::style;
|
||||
use dialoguer::{theme::ColorfulTheme, Input};
|
||||
use dialoguer::{Confirm, Select};
|
||||
use mail_parser::parsers::MessageStream;
|
||||
use mail_parser::MessageParser;
|
||||
use reqwest::Client;
|
||||
|
||||
@@ -161,7 +160,11 @@ pub async fn run_import(
|
||||
continue;
|
||||
}
|
||||
|
||||
let message = match MessageParser::new().parse(body) {
|
||||
let message = match MessageParser::new()
|
||||
.with_minimal_headers()
|
||||
.default_header_text()
|
||||
.parse(body)
|
||||
{
|
||||
Some(msg) => msg,
|
||||
None => {
|
||||
eprintln!(
|
||||
@@ -181,15 +184,12 @@ pub async fn run_import(
|
||||
}
|
||||
|
||||
let get_default_folder = || {
|
||||
let gmail_labels = message.header_raw("X-Gmail-Labels").unwrap_or("INBOX");
|
||||
let text_cow = MessageStream::new(gmail_labels.as_bytes())
|
||||
.parse_unstructured()
|
||||
.into_text();
|
||||
let data: &str = match &text_cow {
|
||||
Some(c) => c.as_ref(),
|
||||
None => "INBOX",
|
||||
};
|
||||
determine_folder(data)
|
||||
let labels = message
|
||||
.header("X-Gmail-Labels")
|
||||
.and_then(|h| h.as_text())
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(|| "INBOX".to_string());
|
||||
determine_folder(&labels)
|
||||
};
|
||||
|
||||
let folder_name = if let Some(ref folder) = target_folder {
|
||||
|
||||
Reference in New Issue
Block a user