mirror of
https://github.com/nushell/nushell.git
synced 2024-12-04 22:33:50 +01:00
142 lines
3.9 KiB
Rust
142 lines
3.9 KiB
Rust
use crate::commands::WholeStreamCommand;
|
|
use crate::prelude::*;
|
|
use ::eml_parser::eml::*;
|
|
use ::eml_parser::EmlParser;
|
|
use nu_errors::ShellError;
|
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue};
|
|
use nu_source::Tagged;
|
|
|
|
pub struct FromEML;
|
|
|
|
const DEFAULT_BODY_PREVIEW: usize = 50;
|
|
|
|
#[derive(Deserialize, Clone)]
|
|
pub struct FromEMLArgs {
|
|
#[serde(rename(deserialize = "preview-body"))]
|
|
preview_body: Option<Tagged<usize>>,
|
|
}
|
|
|
|
#[async_trait]
|
|
impl WholeStreamCommand for FromEML {
|
|
fn name(&self) -> &str {
|
|
"from eml"
|
|
}
|
|
|
|
fn signature(&self) -> Signature {
|
|
Signature::build("from eml").named(
|
|
"preview-body",
|
|
SyntaxShape::Int,
|
|
"How many bytes of the body to preview",
|
|
Some('b'),
|
|
)
|
|
}
|
|
|
|
fn usage(&self) -> &str {
|
|
"Parse text as .eml and create table."
|
|
}
|
|
|
|
async fn run(
|
|
&self,
|
|
args: CommandArgs,
|
|
registry: &CommandRegistry,
|
|
) -> Result<OutputStream, ShellError> {
|
|
from_eml(args, registry).await
|
|
}
|
|
}
|
|
|
|
fn emailaddress_to_value(tag: &Tag, email_address: &EmailAddress) -> TaggedDictBuilder {
|
|
let mut dict = TaggedDictBuilder::with_capacity(tag, 2);
|
|
let (n, a) = match email_address {
|
|
EmailAddress::AddressOnly { address } => {
|
|
(UntaggedValue::nothing(), UntaggedValue::string(address))
|
|
}
|
|
EmailAddress::NameAndEmailAddress { name, address } => {
|
|
(UntaggedValue::string(name), UntaggedValue::string(address))
|
|
}
|
|
};
|
|
|
|
dict.insert_untagged("Name", n);
|
|
dict.insert_untagged("Address", a);
|
|
|
|
dict
|
|
}
|
|
|
|
fn headerfieldvalue_to_value(tag: &Tag, value: &HeaderFieldValue) -> UntaggedValue {
|
|
use HeaderFieldValue::*;
|
|
|
|
match value {
|
|
SingleEmailAddress(address) => emailaddress_to_value(tag, address).into_untagged_value(),
|
|
MultipleEmailAddresses(addresses) => UntaggedValue::Table(
|
|
addresses
|
|
.iter()
|
|
.map(|a| emailaddress_to_value(tag, a).into_value())
|
|
.collect(),
|
|
),
|
|
Unstructured(s) => UntaggedValue::string(s),
|
|
Empty => UntaggedValue::nothing(),
|
|
}
|
|
}
|
|
|
|
async fn from_eml(
|
|
args: CommandArgs,
|
|
registry: &CommandRegistry,
|
|
) -> Result<OutputStream, ShellError> {
|
|
let tag = args.call_info.name_tag.clone();
|
|
let registry = registry.clone();
|
|
let (eml_args, input): (FromEMLArgs, _) = args.process(®istry).await?;
|
|
let value = input.collect_string(tag.clone()).await?;
|
|
|
|
let body_preview = eml_args
|
|
.preview_body
|
|
.map(|b| b.item)
|
|
.unwrap_or(DEFAULT_BODY_PREVIEW);
|
|
|
|
let eml = EmlParser::from_string(value.item)
|
|
.with_body_preview(body_preview)
|
|
.parse()
|
|
.map_err(|_| {
|
|
ShellError::labeled_error(
|
|
"Could not parse .eml file",
|
|
"could not parse .eml file",
|
|
&tag,
|
|
)
|
|
})?;
|
|
|
|
let mut dict = TaggedDictBuilder::new(&tag);
|
|
|
|
if let Some(subj) = eml.subject {
|
|
dict.insert_untagged("Subject", UntaggedValue::string(subj));
|
|
}
|
|
|
|
if let Some(from) = eml.from {
|
|
dict.insert_untagged("From", headerfieldvalue_to_value(&tag, &from));
|
|
}
|
|
|
|
if let Some(to) = eml.to {
|
|
dict.insert_untagged("To", headerfieldvalue_to_value(&tag, &to));
|
|
}
|
|
|
|
for HeaderField { name, value } in eml.headers.iter() {
|
|
dict.insert_untagged(name, headerfieldvalue_to_value(&tag, &value));
|
|
}
|
|
|
|
if let Some(body) = eml.body {
|
|
dict.insert_untagged("Body", UntaggedValue::string(body));
|
|
}
|
|
|
|
Ok(OutputStream::one(ReturnSuccess::value(dict.into_value())))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::FromEML;
|
|
use super::ShellError;
|
|
|
|
#[test]
|
|
fn examples_work_as_expected() -> Result<(), ShellError> {
|
|
use crate::examples::test as test_examples;
|
|
|
|
Ok(test_examples(FromEML {})?)
|
|
}
|
|
}
|