dovemail 0.0.1

Use Microsoft's PNP CLI with email clients.
Documentation
//! Mbox data definition.
//!
//! Useful websites:
//!
//! - https://en.wikipedia.org/wiki/Mbox
//! - Qhttps://access.redhat.com/articles/6167512
//! - https://github.com/catmin/inetsim/blob/44d92c8ec95b68af41064c4ddadb1f0f7916a8ec/data/pop3/sample.mbox

use crate::outlook::OutlookMessage;
use time::format_description::well_known::Rfc2822;

/// Write a message.
pub fn write_message<W: std::io::Write>(
    message: &OutlookMessage,
    out: &mut W,
) -> Result<(), MessageWriteError> {
    writeln!(out, "Message-ID: {}", message.internet_message_id)?;
    writeln!(out, "Date: {}", message.sent_date_time.format(&Rfc2822)?)?;
    writeln!(
        out,
        "From: {}",
        message
            .from
            .as_ref()
            .map(|x| x.to_string())
            .unwrap_or_default()
    )?;

    let recipients = [
        ("To", &message.to_recipients),
        ("CC", &message.cc_recipients),
        ("BCC", &message.bcc_recipients),
    ];
    for (header_name, recipients_list) in recipients {
        let csv = to_csv(recipients_list);
        if !csv.is_empty() {
            writeln!(out, "{}: {}", header_name, csv)?;
        }
    }

    writeln!(out, "Subject: {}", message.subject)?;
    writeln!(out, "Content-Type: {}", message.body.content_type.as_str())?;
    writeln!(out, "X-Has-Attachments: {:?}", message.has_attachments)?;
    writeln!(out, "X-Importance: {}", message.importance.as_str())?;
    writeln!(out, "X-Web-Link: {}", message.web_link)?;
    writeln!(out, "X-Parent-Folder-Id: {}", message.parent_folder_id)?;
    writeln!(out, "X-Conversation-Id: {}", message.conversation_id)?;
    writeln!(out, "X-Conversation-Index: {}", message.conversation_index)?;
    writeln!(out, "\n{}", message.body.content)?;
    Ok(())
}

/// Possible errors which occur while writing
#[derive(thiserror::Error, Debug)]
pub enum MessageWriteError {
    #[error(transparent)]
    DateFormat(#[from] time::error::Format),
    #[error(transparent)]
    Io(#[from] std::io::Error),
}

fn to_csv<S: ToString>(list_of_recipients: &[S]) -> String {
    list_of_recipients
        .iter()
        .map(|recipient| recipient.to_string())
        .collect::<Vec<_>>()
        .join(", ")
}