#safe #robust #fast #focus #handling #email-parsing

bin+lib rustyknife

Fast, robust and safe email parsing library

13 releases

0.2.11 Jan 4, 2021
0.2.10 Nov 17, 2020
0.2.9 Sep 4, 2020
0.2.8 Apr 17, 2020
0.1.7 Mar 26, 2019

#18 in Email

Download history 12/week @ 2021-05-27 9/week @ 2021-06-03 28/week @ 2021-06-10 11/week @ 2021-06-17 52/week @ 2021-06-24 116/week @ 2021-07-01 14/week @ 2021-07-08 63/week @ 2021-07-15 10/week @ 2021-07-22 144/week @ 2021-07-29 44/week @ 2021-08-05 29/week @ 2021-08-12 14/week @ 2021-08-19 9/week @ 2021-08-26 9/week @ 2021-09-02 21/week @ 2021-09-09

177 downloads per month
Used in 3 crates (2 directly)

GPL-3.0+

115KB
2.5K SLoC

rustyknife

crates.io Build Status codecov

Email parsing library with a focus on reliably handling malformed data

Latest documentation

Features:

Roadmap:

  • Decoding of all common ESMTP extensions
  • Support more email content syntax

Examples

Email header decoding

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

let (rem, parsed) = from::<Intl>(b"  A Group(Some people)\r
 :Chris Jones <c@(Chris's host.)public.example>,\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.is_empty());
assert_eq!(parsed, [Address::Group(Group{
       dname: "A Group".into(),
       members: vec![
           IMFMailbox { dname: Some("Chris Jones".into()),
                        address: Mailbox::from_imf(b"c@public.example").unwrap() },
           IMFMailbox { dname: None,
                        address: Mailbox::from_imf(b"joe@example.org").unwrap() },
           IMFMailbox { dname: Some("John".into()),
                        address: Mailbox::from_imf(b"jdoe@one.test").unwrap() }
       ]
   })]);

ESMTP command parsing

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

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

RFC 2047 encoded word decoding

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

Dependencies

~5.5–7.5MB
~156K SLoC