10 releases

✓ Uses Rust 2018 edition

0.2.8 Apr 17, 2020
0.2.7 Nov 28, 2019
0.2.3 Sep 17, 2019
0.2.2 Aug 29, 2019
0.1.7 Mar 26, 2019

#22 in Email

Download history 20/week @ 2020-03-08 10/week @ 2020-03-15 50/week @ 2020-03-22 4/week @ 2020-03-29 37/week @ 2020-04-05 64/week @ 2020-04-12 15/week @ 2020-04-19 2/week @ 2020-04-26 6/week @ 2020-05-03 2/week @ 2020-05-10 36/week @ 2020-05-17 13/week @ 2020-05-24 29/week @ 2020-05-31 18/week @ 2020-06-07 12/week @ 2020-06-14 11/week @ 2020-06-21

114 downloads per month
Used in smtpbis

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

~4.5MB
~97K SLoC