{"id":13637028,"url":"https://github.com/stalwartlabs/mail-parser","last_synced_at":"2025-05-14T07:08:23.204Z","repository":{"id":38397563,"uuid":"413137418","full_name":"stalwartlabs/mail-parser","owner":"stalwartlabs","description":"Fast and robust e-mail parsing library for Rust","archived":false,"fork":false,"pushed_at":"2025-05-11T14:33:11.000Z","size":2391,"stargazers_count":366,"open_issues_count":17,"forks_count":46,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-05-11T15:30:44.640Z","etag":null,"topics":["email","mail","mime","mime-parser","parser","parsing","rust"],"latest_commit_sha":null,"homepage":"https://docs.rs/mail-parser/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stalwartlabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSES/Apache-2.0.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"open_collective":"stalwart","github":"stalwartlabs","ko_fi":null,"patreon":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2021-10-03T16:45:32.000Z","updated_at":"2025-05-11T14:30:10.000Z","dependencies_parsed_at":"2024-06-19T05:26:27.388Z","dependency_job_id":"c9ea2291-3a22-4565-86b9-2575f4c1bfca","html_url":"https://github.com/stalwartlabs/mail-parser","commit_stats":{"total_commits":168,"total_committers":12,"mean_commits":14.0,"dds":0.06547619047619047,"last_synced_commit":"c7790a89256510f0f09382b73bff6ddcef5f0a5c"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalwartlabs%2Fmail-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalwartlabs%2Fmail-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalwartlabs%2Fmail-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalwartlabs%2Fmail-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stalwartlabs","download_url":"https://codeload.github.com/stalwartlabs/mail-parser/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254092659,"owners_count":22013290,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["email","mail","mime","mime-parser","parser","parsing","rust"],"created_at":"2024-08-02T00:01:09.427Z","updated_at":"2025-05-14T07:08:23.186Z","avatar_url":"https://github.com/stalwartlabs.png","language":"Rust","funding_links":["https://opencollective.com/stalwart","https://github.com/sponsors/stalwartlabs"],"categories":["Libraries","库 Libraries","Rust"],"sub_categories":["Email","电子邮件 Email"],"readme":"# mail-parser\n\n[![crates.io](https://img.shields.io/crates/v/mail-parser)](https://crates.io/crates/mail-parser)\n[![build](https://github.com/stalwartlabs/mail-parser/actions/workflows/rust.yml/badge.svg)](https://github.com/stalwartlabs/mail-parser/actions/workflows/rust.yml)\n[![docs.rs](https://img.shields.io/docsrs/mail-parser)](https://docs.rs/mail-parser)\n[![crates.io](https://img.shields.io/crates/l/mail-parser)](http://www.apache.org/licenses/LICENSE-2.0)\n\n_mail-parser_ is an **e-mail parsing library** written in Rust that fully conforms to the Internet Message Format standard (_RFC 5322_), the\nMultipurpose Internet Mail Extensions (MIME; _RFC 2045 - 2049_) as well as many other [internet messaging RFCs](#conformed-rfcs).\n\nIt also supports decoding messages in [41 different character sets](#supported-character-sets) including obsolete formats such as UTF-7.\nAll Unicode (UTF-*) and single-byte character sets are handled internally by the library while support for legacy multi-byte encodings of Chinese\nand Japanese languages such as BIG5 or ISO-2022-JP is provided by the optional dependency [encoding_rs](https://crates.io/crates/encoding_rs).\n\nIn general, this library abides by the Postel's law or [Robustness Principle](https://en.wikipedia.org/wiki/Robustness_principle) which \nstates that an implementation must be conservative in its sending behavior and liberal in its receiving behavior. This means that\n_mail-parser_ will make a best effort to parse non-conformant e-mail messages as long as these do not deviate too much from the standard.\n\nUnlike other e-mail parsing libraries that return nested representations of the different MIME parts in a message, this library \nconforms to [RFC 8621, Section 4.1.4](https://datatracker.ietf.org/doc/html/rfc8621#section-4.1.4) and provides a more human-friendly\nrepresentation of the message contents consisting of just text body parts, html body parts and attachments. Additionally, conversion to/from\nHTML and plain text inline body parts is done automatically when the _alternative_ version is missing.\n\nPerformance and memory safety were two important factors while designing _mail-parser_:\n\n- **Zero-copy**: Practically all strings returned by this library are `Cow\u003cstr\u003e` references to the input raw message.\n- **High performance Base64 decoding** based on Chromium's decoder ([the fastest non-SIMD decoder](https://github.com/lemire/fastbase64)). \n- **Fast parsing** of message header fields, character set names and HTML entities using [perfect hashing](https://en.wikipedia.org/wiki/Perfect_hash_function).\n- Written in **100% safe** Rust with no external dependencies.\n- Every function in the library has been [fuzzed](#testing-fuzzing--benchmarking) and thoroughly [tested with MIRI](#testing-fuzzing--benchmarking).\n- **Battle-tested** with millions of real-world e-mail messages dating from 1995 until today. \n- Used in production environments worldwide by [Stalwart Mail Server](https://github.com/stalwartlabs/mail-server).\n\n## Usage Example\n\n```rust\n    let input = br#\"From: Art Vandelay \u003cart@vandelay.com\u003e (Vandelay Industries)\nTo: \"Colleagues\": \"James Smythe\" \u003cjames@vandelay.com\u003e; Friends:\n    jane@example.com, =?UTF-8?Q?John_Sm=C3=AEth?= \u003cjohn@example.com\u003e;\nDate: Sat, 20 Nov 2021 14:22:01 -0800\nSubject: Why not both importing AND exporting? =?utf-8?b?4pi6?=\nContent-Type: multipart/mixed; boundary=\"festivus\";\n\n--festivus\nContent-Type: text/html; charset=\"us-ascii\"\nContent-Transfer-Encoding: base64\n\nPGh0bWw+PHA+SSB3YXMgdGhpbmtpbmcgYWJvdXQgcXVpdHRpbmcgdGhlICZsZHF1bztle\nHBvcnRpbmcmcmRxdW87IHRvIGZvY3VzIGp1c3Qgb24gdGhlICZsZHF1bztpbXBvcnRpbm\ncmcmRxdW87LDwvcD48cD5idXQgdGhlbiBJIHRob3VnaHQsIHdoeSBub3QgZG8gYm90aD8\ngJiN4MjYzQTs8L3A+PC9odG1sPg==\n--festivus\nContent-Type: message/rfc822\n\nFrom: \"Cosmo Kramer\" \u003ckramer@kramerica.com\u003e\nSubject: Exporting my book about coffee tables\nContent-Type: multipart/mixed; boundary=\"giddyup\";\n\n--giddyup\nContent-Type: text/plain; charset=\"utf-16\"\nContent-Transfer-Encoding: quoted-printable\n\n=FF=FE=0C!5=D8\"=DD5=D8)=DD5=D8-=DD =005=D8*=DD5=D8\"=DD =005=D8\"=\n=DD5=D85=DD5=D8-=DD5=D8,=DD5=D8/=DD5=D81=DD =005=D8*=DD5=D86=DD =\n=005=D8=1F=DD5=D8,=DD5=D8,=DD5=D8(=DD =005=D8-=DD5=D8)=DD5=D8\"=\n=DD5=D8=1E=DD5=D80=DD5=D8\"=DD!=00\n--giddyup\nContent-Type: image/gif; name*1=\"about \"; name*0=\"Book \";\n              name*2*=utf-8''%e2%98%95 tables.gif\nContent-Transfer-Encoding: Base64\nContent-Disposition: attachment\n\nR0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\n--giddyup--\n--festivus--\n\"#;\n\n    let message = MessageParser::default().parse(input).unwrap();\n\n    // Parses addresses (including comments), lists and groups\n    assert_eq!(\n        message.from().unwrap().first().unwrap(),\n        \u0026Addr::new(\n            \"Art Vandelay (Vandelay Industries)\".into(),\n            \"art@vandelay.com\"\n        )\n    );\n\n    assert_eq!(\n        message.to().unwrap().as_group().unwrap(),\n        \u0026[\n            Group::new(\n                \"Colleagues\",\n                vec![Addr::new(\"James Smythe\".into(), \"james@vandelay.com\")]\n            ),\n            Group::new(\n                \"Friends\",\n                vec![\n                    Addr::new(None, \"jane@example.com\"),\n                    Addr::new(\"John Smîth\".into(), \"john@example.com\"),\n                ]\n            )\n        ]\n    );\n\n    assert_eq!(\n        message.date().unwrap().to_rfc3339(),\n        \"2021-11-20T14:22:01-08:00\"\n    );\n\n    // RFC2047 support for encoded text in message readers\n    assert_eq!(\n        message.subject().unwrap(),\n        \"Why not both importing AND exporting? ☺\"\n    );\n\n    // HTML and text body parts are returned conforming to RFC8621, Section 4.1.4\n    assert_eq!(\n        message.body_html(0).unwrap(),\n        concat!(\n            \"\u003chtml\u003e\u003cp\u003eI was thinking about quitting the \u0026ldquo;exporting\u0026rdquo; to \",\n            \"focus just on the \u0026ldquo;importing\u0026rdquo;,\u003c/p\u003e\u003cp\u003ebut then I thought,\",\n            \" why not do both? \u0026#x263A;\u003c/p\u003e\u003c/html\u003e\"\n        )\n    );\n\n    // HTML parts are converted to plain text (and viceversa) when missing\n    assert_eq!(\n        message.body_text(0).unwrap(),\n        concat!(\n            \"I was thinking about quitting the “exporting” to focus just on the\",\n            \" “importing”,\\nbut then I thought, why not do both? ☺\\n\"\n        )\n    );\n\n    // Supports nested messages as well as multipart/digest\n    let nested_message = message\n        .attachment(0)\n        .unwrap()\n        .message();\n        .unwrap();\n\n    assert_eq!(\n        nested_message.subject().unwrap(),\n        \"Exporting my book about coffee tables\"\n    );\n\n    // Handles UTF-* as well as many legacy encodings\n    assert_eq!(\n        nested_message.body_text(0).unwrap(),\n        \"ℌ𝔢𝔩𝔭 𝔪𝔢 𝔢𝔵𝔭𝔬𝔯𝔱 𝔪𝔶 𝔟𝔬𝔬𝔨 𝔭𝔩𝔢𝔞𝔰𝔢!\"\n    );\n    assert_eq!(\n        nested_message.body_html(0).unwrap(),\n        \"\u003chtml\u003e\u003cbody\u003eℌ𝔢𝔩𝔭 𝔪𝔢 𝔢𝔵𝔭𝔬𝔯𝔱 𝔪𝔶 𝔟𝔬𝔬𝔨 𝔭𝔩𝔢𝔞𝔰𝔢!\u003c/body\u003e\u003c/html\u003e\"\n    );\n\n    let nested_attachment = nested_message.attachment(0).unwrap();\n\n    assert_eq!(nested_attachment.len(), 42);\n\n    // Full RFC2231 support for continuations and character sets\n    assert_eq!(\n        nested_attachment.attachment_name().unwrap(),\n        \"Book about ☕ tables.gif\"\n    );\n\n    // Integrates with Serde\n    println!(\"{}\", serde_json::to_string_pretty(\u0026message).unwrap());\n```\n\nMore examples available under the [examples](examples) directory. Please note that this library does not support building e-mail messages as this functionality is provided separately by the [`mail-builder`](https://crates.io/crates/mail-builder) crate.\n\n## Testing, Fuzzing \u0026 Benchmarking\n\nTo run the testsuite:\n\n```bash\n $ cargo test --all-features\n```\n\nor, to run the testsuite with MIRI:\n\n```bash\n $ cargo +nightly miri test --all-features\n```\n\nTo fuzz the library with `cargo-fuzz`:\n\n```bash\n $ cargo +nightly fuzz run mail_parser\n```\n\nand, to run the benchmarks:\n\n```bash\n $ cargo +nightly bench --all-features\n```\n\n## Conformed RFCs\n\n- [RFC 822 - Standard for ARPA Internet Text Messages](https://datatracker.ietf.org/doc/html/rfc822)\n- [RFC 5322 - Internet Message Format](https://datatracker.ietf.org/doc/html/rfc5322)\n- [RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies](https://datatracker.ietf.org/doc/html/rfc2045)\n- [RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types](https://datatracker.ietf.org/doc/html/rfc2046)\n- [RFC 2047 - MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text](https://datatracker.ietf.org/doc/html/rfc2047)\n- [RFC 2048 - Multipurpose Internet Mail Extensions (MIME) Part Four: Registration Procedures](https://datatracker.ietf.org/doc/html/rfc2048)\n- [RFC 2049 - Multipurpose Internet Mail Extensions (MIME) Part Five: Conformance Criteria and Examples](https://datatracker.ietf.org/doc/html/rfc2049)\n- [RFC 2231 - MIME Parameter Value and Encoded Word Extensions: Character Sets, Languages, and Continuations](https://datatracker.ietf.org/doc/html/rfc2231)\n- [RFC 2557 - MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)](https://datatracker.ietf.org/doc/html/rfc2557)\n- [RFC 2183 - Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field](https://datatracker.ietf.org/doc/html/rfc2183)\n- [RFC 2392 - Content-ID and Message-ID Uniform Resource Locators](https://datatracker.ietf.org/doc/html/rfc2392)\n- [RFC 3282 - Content Language Headers](https://datatracker.ietf.org/doc/html/rfc3282)\n- [RFC 6532 - Internationalized Email Headers](https://datatracker.ietf.org/doc/html/rfc6532)\n- [RFC 2152 - UTF-7 - A Mail-Safe Transformation Format of Unicode](https://datatracker.ietf.org/doc/html/rfc2152)\n- [RFC 2369 - The Use of URLs as Meta-Syntax for Core Mail List Commands and their Transport through Message Header Fields](https://datatracker.ietf.org/doc/html/rfc2369)\n- [RFC 2919 - List-Id: A Structured Field and Namespace for the Identification of Mailing Lists](https://datatracker.ietf.org/doc/html/rfc2919)\n- [RFC 3339 - Date and Time on the Internet: Timestamps](https://datatracker.ietf.org/doc/html/rfc3339)\n- [RFC 8621 - The JSON Meta Application Protocol (JMAP) for Mail (Section 4.1.4)](https://datatracker.ietf.org/doc/html/rfc8621#section-4.1.4)\n- [RFC 5957 - Internet Message Access Protocol - SORT and THREAD Extensions (Section 2.1)](https://datatracker.ietf.org/doc/html/rfc5256#section-2.1)\n\n## Supported Character Sets\n\n- UTF-8\n- UTF-16, UTF-16BE, UTF-16LE\n- UTF-7\n- US-ASCII\n- ISO-8859-1 \n- ISO-8859-2 \n- ISO-8859-3 \n- ISO-8859-4 \n- ISO-8859-5 \n- ISO-8859-6 \n- ISO-8859-7 \n- ISO-8859-8 \n- ISO-8859-9 \n- ISO-8859-10 \n- ISO-8859-13 \n- ISO-8859-14 \n- ISO-8859-15 \n- ISO-8859-16\n- CP1250 \n- CP1251 \n- CP1252 \n- CP1253 \n- CP1254 \n- CP1255 \n- CP1256 \n- CP1257 \n- CP1258\n- KOI8-R\n- KOI8_U\n- MACINTOSH\n- IBM850\n- TIS-620\n  \nSupported character sets via the optional dependency [encoding_rs](https://crates.io/crates/encoding_rs):\n  \n- SHIFT_JIS\n- BIG5\n- EUC-JP \n- EUC-KR \n- GB18030\n- GBK\n- ISO-2022-JP \n- WINDOWS-874\n- IBM-866\n\n## License\n\nLicensed under either of\n\n * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n## Copyright\n\nCopyright (C) 2020, Stalwart Labs LLC\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstalwartlabs%2Fmail-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstalwartlabs%2Fmail-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstalwartlabs%2Fmail-parser/lists"}