rustyknife

crates.io Build Status codecov

Email parsing library with a focus on reliably handling malformed data

[Latest documentation]

Features: * [Python module] * Email header parsing * ESMTP command parsing * Unit testing with a high coverage * Supports internationalized email headers through [RFC 2047] and [RFC 2231] decoding * Used to parse the content of millions of emails every day

Roadmap: * [SMTPUTF8] support * [UTF-8 Internationalized Email Headers] support * Decoding of all common ESMTP extensions * Support more email content syntax

Examples

Email header decoding

```rust use rustyknife::types::{DomainPart, DotAtom, Mailbox}; use rustyknife::rfc5322::{Address, Group, Mailbox as IMFMailbox}; use rustyknife::rfc5322::from;

let (rem, parsed) = from(b" A Group(Some people)\r :Chris Jones ,\r joe@example.org,\r John jdoe@one.test (my dear friend); (the end of the group)\r\n").unwrap();

// rem contains the unparsed remainder. assert!(rem.isempty()); asserteq!(parsed, [Address::Group(Group{ dname: "A Group".into(), members: vec![ IMFMailbox { dname: Some("Chris Jones".into()), address: Mailbox::fromimf(b"c@public.example").unwrap() }, IMFMailbox { dname: None, address: Mailbox::fromimf(b"joe@example.org").unwrap() }, IMFMailbox { dname: Some("John".into()), address: Mailbox::from_imf(b"jdoe@one.test").unwrap() } ] })]); ```

ESMTP command parsing

```rust use rustyknife::types::{Mailbox, QuotedString, Domain}; use rustyknife::rfc5321::{mail_command, Path, ReversePath, Param};

let (, (path, params)) = mailcommand(b"MAIL FROM:<\"mr bob\"@example.com> RET=FULL ENVID=abc123\r\n").unwrap(); asserteq!(path, ReversePath::Path( Path(Mailbox(QuotedString::fromsmtp(b"\"mr bob\"").unwrap().into(), Domain::fromsmtp(b"example.com").unwrap().into()), vec![]))); asserteq!(params, [Param::new("RET", Some("FULL")).unwrap(), Param::new("ENVID", Some("abc123")).unwrap()]); ```

RFC 2047 encoded word decoding

rust use rustyknife::rfc2047::encoded_word; let (_, decoded) = encoded_word(b"=?x-sjis?B?lEWWQI7Kg4GM9ZTygs6CtSiPzik=?=").unwrap(); assert_eq!(decoded, "忍法写メ光飛ばし(笑)");