{"id":18041638,"url":"https://github.com/katyo/emailmessage-rs","last_synced_at":"2025-08-07T09:13:15.759Z","repository":{"id":57624540,"uuid":"130575386","full_name":"katyo/emailmessage-rs","owner":"katyo","description":"Email Message library for Rust","archived":false,"fork":false,"pushed_at":"2018-11-10T04:54:23.000Z","size":106,"stargazers_count":25,"open_issues_count":2,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-18T10:58:32.184Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/katyo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-22T14:30:22.000Z","updated_at":"2025-06-12T01:03:46.000Z","dependencies_parsed_at":"2022-08-26T22:21:18.031Z","dependency_job_id":null,"html_url":"https://github.com/katyo/emailmessage-rs","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/katyo/emailmessage-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Femailmessage-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Femailmessage-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Femailmessage-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Femailmessage-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/katyo","download_url":"https://codeload.github.com/katyo/emailmessage-rs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katyo%2Femailmessage-rs/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269230647,"owners_count":24382208,"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","status":"online","status_checked_at":"2025-08-07T02:00:09.698Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-10-30T16:11:10.263Z","updated_at":"2025-08-07T09:13:15.690Z","avatar_url":"https://github.com/katyo.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Email Message library for Rust\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)\n[![Crates.io Package](https://img.shields.io/crates/v/emailmessage.svg)](https://crates.io/crates/emailmessage)\n[![Docs.rs API Documentation](https://docs.rs/emailmessage/badge.svg)](https://docs.rs/emailmessage)\n[![Travis-CI Build Status](https://travis-ci.org/katyo/emailmessage-rs.svg?branch=master)](https://travis-ci.org/katyo/emailmessage-rs)\n[![Appveyor Build status](https://ci.appveyor.com/api/projects/status/29im4ud4xb3r9hlv)](https://ci.appveyor.com/project/katyo/emailmessage-rs)\n\nThis project aims to provide a proper strongly typed way to build and parse emails.\n\n## Features\n\n* Typed headers using `hyperx::Header`\n* Support for headers with unicode values\n* Support for **MIME 1.0** multipart contents\n* Streaming messages to save memory usage\n* Email `Address`, `Mailbox` and `Mailboxes` types\n\n## Usage\n\n### Format email messages\n\n#### With string body\n\nThe easiest way how we can create email message with simple string\n(see [format\\_string.rs](examples/format_string.rs)).\n\n```rust\nextern crate emailmessage;\n\nuse emailmessage::Message;\n\nfn main() {\n    let m: Message\u003c\u0026str\u003e = Message::builder()\n        .from(\"NoBody \u003cnobody@domain.tld\u003e\".parse().unwrap())\n        .reply_to(\"Yuin \u003cyuin@domain.tld\u003e\".parse().unwrap())\n        .to(\"Hei \u003chei@domain.tld\u003e\".parse().unwrap())\n        .subject(\"Happy new year\")\n        .body(\"Be happy!\");\n\n    println!(\"{}\", m);\n}\n```\n\nRun this example:\n\n```\n$ cargo run --example format_string\n\nFrom: NoBody \u003cnobody@domain.tld\u003e\nReply-To: Yuin \u003cyuin@domain.tld\u003e\nTo: Hei \u003chei@domain.tld\u003e\nSubject: Happy new year\n\nBe happy!\n```\n\nThe unicode header data will be encoded using _UTF8-Base64_ encoding.\n\n#### With mime body\n\n##### Single part\n\nThe more complex way is using MIME contents\n(see [format\\_mime.rs](examples/format_mime.rs)).\n\n```rust\nextern crate emailmessage;\n\nuse emailmessage::{header, Message, SinglePart};\n\nfn main() {\n    let m: Message\u003cSinglePart\u003c\u0026str\u003e\u003e = Message::builder()\n        .from(\"NoBody \u003cnobody@domain.tld\u003e\".parse().unwrap())\n        .reply_to(\"Yuin \u003cyuin@domain.tld\u003e\".parse().unwrap())\n        .to(\"Hei \u003chei@domain.tld\u003e\".parse().unwrap())\n        .subject(\"Happy new year\")\n        .mime_body(\n            SinglePart::builder()\n                .header(header::ContentType(\n                    \"text/plain; charset=utf8\".parse().unwrap(),\n                )).header(header::ContentTransferEncoding::QuotedPrintable)\n                .body(\"Привет, мир!\"),\n        );\n\n    println!(\"{}\", m);\n}\n```\n\nThe body will be encoded using selected `Content-Transfer-Encoding`.\n\n```\n$ cargo run --example format_mime\n\nFrom: NoBody \u003cnobody@domain.tld\u003e\nReply-To: Yuin \u003cyuin@domain.tld\u003e\nTo: Hei \u003chei@domain.tld\u003e\nSubject: Happy new year\nMIME-Version: 1.0\nContent-Type: text/plain; charset=utf8\nContent-Transfer-Encoding: quoted-printable\n\n=D0=9F=D1=80=D0=B8=D0=B2=D0=B5=D1=82, =D0=BC=D0=B8=D1=80!\n\n```\n\n##### Multiple parts\n\nAnd the more advanced way is a using multipart MIME contents\n(see [format\\_multipart.rs](examples/format_multipart.rs)).\n\n```rust\nextern crate emailmessage;\nuse emailmessage::{header, Message, MultiPart, SinglePart};\nfn main() {\n    let m: Message\u003cMultiPart\u003c\u0026str\u003e\u003e = Message::builder()\n        .from(\"NoBody \u003cnobody@domain.tld\u003e\".parse().unwrap())\n        .reply_to(\"Yuin \u003cyuin@domain.tld\u003e\".parse().unwrap())\n        .to(\"Hei \u003chei@domain.tld\u003e\".parse().unwrap())\n        .subject(\"Happy new year\")\n        .mime_body(\n            MultiPart::mixed()\n            .multipart(\n                MultiPart::alternative()\n                .singlepart(\n                    SinglePart::quoted_printable()\n                    .header(header::ContentType(\"text/plain; charset=utf8\".parse().unwrap()))\n                    .body(\"Привет, мир!\")\n                )\n                .multipart(\n                    MultiPart::related()\n                    .singlepart(\n                        SinglePart::eight_bit()\n                        .header(header::ContentType(\"text/html; charset=utf8\".parse().unwrap()))\n                        .body(\"\u003cp\u003e\u003cb\u003eHello\u003c/b\u003e, \u003ci\u003eworld\u003c/i\u003e! \u003cimg src=smile.png\u003e\u003c/p\u003e\")\n                    )\n                    .singlepart(\n                        SinglePart::base64()\n                        .header(header::ContentType(\"image/png\".parse().unwrap()))\n                        .header(header::ContentDisposition {\n                            disposition: header::DispositionType::Inline,\n                            parameters: vec![],\n                        })\n                        .body(\"\u003csmile-raw-image-data\u003e\")\n                    )\n                )\n            )\n            .singlepart(\n                SinglePart::seven_bit()\n                .header(header::ContentType(\"text/plain; charset=utf8\".parse().unwrap()))\n                .header(header::ContentDisposition {\n                                 disposition: header::DispositionType::Attachment,\n                                 parameters: vec![\n                                     header::DispositionParam::Filename(\n                                         header::Charset::Ext(\"utf-8\".into()),\n                                         None, \"example.c\".as_bytes().into()\n                                     )\n                                 ]\n                             })\n                .body(\"int main() { return 0; }\")\n            )\n        );\n\n    println!(\"{}\", m);\n}\n```\n\n```\n$ cargo run --example format_multipart\n\nFrom: NoBody \u003cnobody@domain.tld\u003e\nReply-To: Yuin \u003cyuin@domain.tld\u003e\nTo: Hei \u003chei@domain.tld\u003e\nSubject: Happy new year\nMIME-Version: 1.0\nContent-Type: multipart/mixed; boundary=\"RTxPCn9p31oAAAAAeQxtr1FbXr/i5vW1hFlH9oJqZRMWxRMK1QLjQ4OPqFk9R+0xUb/m\"\n\n--RTxPCn9p31oAAAAAeQxtr1FbXr/i5vW1hFlH9oJqZRMWxRMK1QLjQ4OPqFk9R+0xUb/m\nContent-Type: multipart/alternative; boundary=\"qW9QCn9p31oAAAAAodFBg1L1Qrraa5hEl0bDJ6kfJMUcRT2LLSWEoeyhSEbUBIqbjWqy\"\n\n--qW9QCn9p31oAAAAAodFBg1L1Qrraa5hEl0bDJ6kfJMUcRT2LLSWEoeyhSEbUBIqbjWqy\nContent-Transfer-Encoding: quoted-printable\nContent-Type: text/plain; charset=utf8\n\n=D0=9F=D1=80=D0=B8=D0=B2=D0=B5=D1=82, =D0=BC=D0=B8=D1=80!\n--qW9QCn9p31oAAAAAodFBg1L1Qrraa5hEl0bDJ6kfJMUcRT2LLSWEoeyhSEbUBIqbjWqy\nContent-Type: multipart/related; boundary=\"BV5RCn9p31oAAAAAUt42E9bYMDEAGCOWlxEz89Bv0qFA5Xsy6rOC3zRahMQ39IFZNnp8\"\n\n--BV5RCn9p31oAAAAAUt42E9bYMDEAGCOWlxEz89Bv0qFA5Xsy6rOC3zRahMQ39IFZNnp8\nContent-Transfer-Encoding: 8bit\nContent-Type: text/html; charset=utf8\n\n\u003cp\u003e\u003cb\u003eHello\u003c/b\u003e, \u003ci\u003eworld\u003c/i\u003e! \u003cimg src=smile.png\u003e\u003c/p\u003e\n--BV5RCn9p31oAAAAAUt42E9bYMDEAGCOWlxEz89Bv0qFA5Xsy6rOC3zRahMQ39IFZNnp8\nContent-Transfer-Encoding: base64\nContent-Type: image/png\nContent-Disposition: inline\n\nPHNtaWxlLXJhdy1pbWFnZS1kYXRhPg==\n--BV5RCn9p31oAAAAAUt42E9bYMDEAGCOWlxEz89Bv0qFA5Xsy6rOC3zRahMQ39IFZNnp8--\n--qW9QCn9p31oAAAAAodFBg1L1Qrraa5hEl0bDJ6kfJMUcRT2LLSWEoeyhSEbUBIqbjWqy--\n--RTxPCn9p31oAAAAAeQxtr1FbXr/i5vW1hFlH9oJqZRMWxRMK1QLjQ4OPqFk9R+0xUb/m\nContent-Transfer-Encoding: 7bit\nContent-Type: text/plain; charset=utf8\nContent-Disposition: attachment; filename=\"example.c\"\n\nint main() { return 0; }\n--RTxPCn9p31oAAAAAeQxtr1FbXr/i5vW1hFlH9oJqZRMWxRMK1QLjQ4OPqFk9R+0xUb/m--\n\n```\n\n#### Use streaming\n\nThe RAM-efficient way to formatting ans sending relatively big emails is a using streaming.\nFor example, you would like to send server access logs in attachments,\nHTML-documents with related media resources or PDFs.\n\nIn examples above we actually allocated formatted emails in memory,\nbut usually we don't want to do same for big emails which size measures in MBytes.\n\n##### Simple string\n\nThe simple example below shows actually sent chunks of streamed message\n(see [format\\_stream.rs](examples/format_stream.rs)).\n\n```rust\nextern crate emailmessage;\nextern crate futures;\nextern crate tokio;\n\nuse emailmessage::Message;\nuse futures::{Future, Stream};\nuse std::str::from_utf8;\nuse tokio::run;\n\nfn main() {\n    let m: Message = Message::builder()\n        .from(\"NoBody \u003cnobody@domain.tld\u003e\".parse().unwrap())\n        .reply_to(\"Yuin \u003cyuin@domain.tld\u003e\".parse().unwrap())\n        .to(\"Hei \u003chei@domain.tld\u003e\".parse().unwrap())\n        .subject(\"Happy new year\")\n        .body(\"Be happy!\".into());\n\n    let f = m\n        .into_stream()\n        .map(|chunk| {\n            println!(\"CHUNK[[\\n{}]]\", from_utf8(\u0026chunk).unwrap());\n            chunk\n        }).concat2()\n        .map(|message| {\n            println!(\"MESSAGE[[\\n{}]]\", from_utf8(\u0026message).unwrap());\n        }).map_err(|error| {\n            eprintln!(\"ERROR: {}\", error);\n        });\n\n    run(f);\n}\n```\n\n```\n$ cargo run --example format_stream\n\nCHUNK[[\nFrom: NoBody \u003cnobody@domain.tld\u003e\nReply-To: Yuin \u003cyuin@domain.tld\u003e\nTo: Hei \u003chei@domain.tld\u003e\nSubject: Happy new year\n]]\nCHUNK[[\n\nBe happy!]]\n```\n\nIn real world app we may do some buffering of stream to prevent too short and too long sendings.\n\n##### Multipart data\n\n(see [format\\_stream\\_multipart.rs](examples/format_stream_multipart.rs))\n\n```rust\nextern crate emailmessage;\nextern crate futures;\nextern crate tokio;\nuse emailmessage::{header, Message, MultiPart, SinglePart};\nuse futures::{Future, Stream};\nuse std::str::from_utf8;\nuse tokio::run;\nfn main() {\n    let b: MultiPart = MultiPart::mixed()\n        .multipart(\n            MultiPart::alternative()\n                .singlepart(\n                    SinglePart::quoted_printable()\n                        .header(header::ContentType(\n                            \"text/plain; charset=utf8\".parse().unwrap(),\n                        )).body(\"Привет, мир!\".into()),\n                ).multipart(\n                    MultiPart::related()\n                        .singlepart(\n                            SinglePart::eight_bit()\n                                .header(header::ContentType(\n                                    \"text/html; charset=utf8\".parse().unwrap(),\n                                )).body(\n                                    \"\u003cp\u003e\u003cb\u003eHello\u003c/b\u003e, \u003ci\u003eworld\u003c/i\u003e! \u003cimg src=smile.png\u003e\u003c/p\u003e\".into(),\n                                ),\n                        ).singlepart(\n                            SinglePart::base64()\n                                .header(header::ContentType(\"image/png\".parse().unwrap()))\n                                .header(header::ContentDisposition {\n                                    disposition: header::DispositionType::Inline,\n                                    parameters: vec![],\n                                }).body(\"\u003csmile-raw-image-data\u003e\".into()),\n                        ),\n                ),\n        ).singlepart(\n            SinglePart::seven_bit()\n                .header(header::ContentType(\n                    \"text/plain; charset=utf8\".parse().unwrap(),\n                )).header(header::ContentDisposition {\n                    disposition: header::DispositionType::Attachment,\n                    parameters: vec![header::DispositionParam::Filename(\n                        header::Charset::Ext(\"utf-8\".into()),\n                        None,\n                        \"example.c\".as_bytes().into(),\n                    )],\n                }).body(\"int main() { return 0; }\".into()),\n        );\n\n    let m = Message::builder()\n        .from(\"NoBody \u003cnobody@domain.tld\u003e\".parse().unwrap())\n        .reply_to(\"Yuin \u003cyuin@domain.tld\u003e\".parse().unwrap())\n        .to(\"Hei \u003chei@domain.tld\u003e\".parse().unwrap())\n        .subject(\"Happy new year\")\n        .mime_body(b.into_stream());\n\n    let f = m\n        .into_stream()\n        .map(|chunk| {\n            println!(\"CHUNK[[\\n{}]]\", from_utf8(\u0026chunk).unwrap());\n            chunk\n        }).concat2()\n        .map(|message| {\n            println!(\"MESSSAGE[[\\n{}]]\", from_utf8(\u0026message).unwrap());\n        }).map_err(|error| {\n            eprintln!(\"ERROR: {:?}\", error);\n        });\n\n    run(f);\n}\n```\n\n```\n$ cargo run --example format_stream_multipart\n\nCHUNK[[\nFrom: NoBody \u003cnobody@domain.tld\u003e\nReply-To: Yuin \u003cyuin@domain.tld\u003e\nTo: Hei \u003chei@domain.tld\u003e\nSubject: Happy new year\nMIME-Version: 1.0\n]]\nCHUNK[[\nContent-Type: multipart/mixed; boundary=\"1S8dCMR/31oAAAAApHRNMETjK2uRsQs4mVVFKVNujcqnm8FHOXWvqARiaYy9ZmnpQ7uQ\"\n]]\nCHUNK[[\n--1S8dCMR/31oAAAAApHRNMETjK2uRsQs4mVVFKVNujcqnm8FHOXWvqARiaYy9ZmnpQ7uQ\n]]\nCHUNK[[\n--1S8dCMR/31oAAAAApHRNMETjK2uRsQs4mVVFKVNujcqnm8FHOXWvqARiaYy9ZmnpQ7uQ\n]]\nCHUNK[[\nContent-Type: multipart/alternative; boundary=\"TCMeCMR/31oAAAAAmf7KBuXt4qRk2RnBJCj8YJNdwm2dsadXxjOlC74hlb1tO6U/SqXY\"\n]]\nCHUNK[[\n--TCMeCMR/31oAAAAAmf7KBuXt4qRk2RnBJCj8YJNdwm2dsadXxjOlC74hlb1tO6U/SqXY\n]]\nCHUNK[[\n--TCMeCMR/31oAAAAAmf7KBuXt4qRk2RnBJCj8YJNdwm2dsadXxjOlC74hlb1tO6U/SqXY\n]]\nCHUNK[[\nContent-Transfer-Encoding: quoted-printable\nContent-Type: text/plain; charset=utf8\n]]\nCHUNK[[\n=D0=9F=D1=80=D0=B8=D0=B2=D0=B5=D1=82, =D0=BC=D0=B8=D1=80!]]\nCHUNK[[\n]]\nCHUNK[[\n--TCMeCMR/31oAAAAAmf7KBuXt4qRk2RnBJCj8YJNdwm2dsadXxjOlC74hlb1tO6U/SqXY\n]]\nCHUNK[[\nContent-Type: multipart/related; boundary=\"YsgeCMR/31oAAAAAanzeyu/dFJGjfzDxpsAOLhRB0RfSw+DXefQybZxGq6HIBEzotZ5Y\"\n]]\nCHUNK[[\n--YsgeCMR/31oAAAAAanzeyu/dFJGjfzDxpsAOLhRB0RfSw+DXefQybZxGq6HIBEzotZ5Y\n]]\nCHUNK[[\n--YsgeCMR/31oAAAAAanzeyu/dFJGjfzDxpsAOLhRB0RfSw+DXefQybZxGq6HIBEzotZ5Y\n]]\nCHUNK[[\nContent-Transfer-Encoding: 8bit\nContent-Type: text/html; charset=utf8\n]]\nCHUNK[[\n\u003cp\u003e\u003cb\u003eHello\u003c/b\u003e, \u003ci\u003eworld\u003c/i\u003e! \u003cimg src=smile.png\u003e\u003c/p\u003e]]\nCHUNK[[\n]]\nCHUNK[[\n--YsgeCMR/31oAAAAAanzeyu/dFJGjfzDxpsAOLhRB0RfSw+DXefQybZxGq6HIBEzotZ5Y\n]]\nCHUNK[[\nContent-Transfer-Encoding: base64\nContent-Type: image/png\nContent-Disposition: inline\n\n]]\nCHUNK[[\nPHNtaWxlLXJhdy1pbWFnZS1kYXRhPg==]]\nCHUNK[[\n\n]]\nCHUNK[[\n--YsgeCMR/31oAAAAAanzeyu/dFJGjfzDxpsAOLhRB0RfSw+DXefQybZxGq6HIBEzotZ5Y--\n]]\nCHUNK[[\n--TCMeCMR/31oAAAAAmf7KBuXt4qRk2RnBJCj8YJNdwm2dsadXxjOlC74hlb1tO6U/SqXY--\n]]\nCHUNK[[\n--1S8dCMR/31oAAAAApHRNMETjK2uRsQs4mVVFKVNujcqnm8FHOXWvqARiaYy9ZmnpQ7uQ\n]]\nCHUNK[[\nContent-Transfer-Encoding: 7bit\nContent-Type: text/plain; charset=utf8\nContent-Disposition: attachment; filename=\"example.c\"\n\n]]\nCHUNK[[\nint main() { return 0; }]]\nCHUNK[[\n\n]]\nCHUNK[[\n--1S8dCMR/31oAAAAApHRNMETjK2uRsQs4mVVFKVNujcqnm8FHOXWvqARiaYy9ZmnpQ7uQ--\n]]\n...\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkatyo%2Femailmessage-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkatyo%2Femailmessage-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkatyo%2Femailmessage-rs/lists"}