mail_headers_ng/lib.rs
1//!
2//! This crate provides header specific functionality for the `mail`
3//! crate. This includes:
4//!
5//! - `HeaderName`, `Header` and `HeaderMap` as for the general API
6//! - `HeaderTryFrom`, `HeaderTryInto` as the `TryFrom`/`TryInto`
7//! traits are not stable but we need something similar to their
8//! functionality.
9//! - a number of headers like `_To`,`_From`, `Sender`, `Subject`
10//! and many more (Note that `_To` and `_From` are prefixed with
11//! and `_` to prevent name collisions when importing them, i.e.
12//! importing `_From as From` would shadow `std::convert::From`
13//! which can lead to extremely irritating errors).
14//! - a number of components which are used to represent the
15//! content/field body of an header field e.g. `MailboxList`
16//! or `Email`. They are placed in the `components` module.
17//! - a `headers!` macro for making the creation of an `HeaderMap`
18//! with a number of headers easier.
19//! - a `def_headers!` macro for defining new custom headers
20//!
21//! ## Example (HeaderMap)
22//!
23//! A header map is a collection representing a number
24//! of mail headers in an specific order. It can be
25//! created like this:
26//!
27//! ```
28//! # #[macro_use]
29//! # extern crate mail_headers;
30//!
31//! // just import all headers
32//! use mail_headers::headers::*;
33//! use mail_headers::HeaderMap;
34//! use mail_headers::error::ComponentCreationError;
35//!
36//! fn create_headers() -> Result<HeaderMap, ComponentCreationError> {
37//! headers!{
38//! // from and to can have multiple values
39//! // until specialization is stable is array
40//! // is necessary
41//! _From: [("My Fancy Display Name", "theduck@example.com")],
42//! _To: [ "unknown@example.com", ],
43//! Subject: "Who are you?"
44//! }
45//! }
46//!
47//! fn main() {
48//! let headers = create_headers().unwrap();
49//! assert_eq!(headers.len(), 3);
50//! }
51//! ```
52//!
53//! ## Example (custom header)
54//!
55//! If needed users of the `mail` crate can create their own
56//! headers, through this should be done with care.
57//!
58//! Note that the second field (then `unchecked { <name> }`),
59//! expects a specific naming scheme, the auto-generated test
60//! do check if it's violated but if you just run the code and
61//! ignore the failing tests strange error can occure. (
62//! The scheme is a capitalise the first letter of each
63//! word and write all other letter in lower case, i.e.
64//! `X-Id` is ok but `X-ID` isn't). The reason for this is because
65//! of the way the header does the field lookup. While this
66//! is not nice, for most use cases there is no need to
67//! generate custom headers and in the future this might be
68//! circumvented by auto-generating the name with a proc-derive.
69//!
70//! ```
71//! # #[macro_use]
72//! # extern crate mail_headers;
73//!
74//! use mail_headers::header_components;
75//!
76//! // this will define two headers `XFooEmail` and `XBarMailbox`
77//! // the first will add a header field named `X-Foo-Email` with
78//! // a value which is an `components::Email` and the second will
79//! // add field with a value which is an `components::Mailbox`.
80//! //
81//! // Note that through the way they are defined `XFooEmail` can
82//! // at most appear 1 time in an header map, while `XBarMailbox`
83//! // can appear multiple times. Be aware that this is checked through
84//! // so called validators which needs to be explicitly run, which they
85//! // are if this header map is used to create a mail (running them
86//! // when adding fields would be a mess as you would have to add
87//! // transactions which can add/remove multiple fields at once, and
88//! // implementing auto-generation for some fields which are required if
89//! // some other fields are given in a certain way would be harder too).
90//!
91//! // If in scope both can be used in the `headers!` macro,
92//! // like any other header.
93//! //
94//! def_headers! {
95//! // the name of the auto-generated test
96//! test_name: validate_header_names,
97//!
98//! // the scope from which all components should be imported
99//! // E.g. `DateTime` refers to `components::DateTime`.
100//! scope: header_components,
101//!
102//! // definitions of the headers or the form
103//! // <type_name>, unchecked { <filed_name> }, <component>, <maxOne>, <validator>
104//! XFooEmail, unchecked { "X-Foo-Email" }, Email , maxOne, None,
105//! XBarMailbox, unchecked { "X-Bar-Mailbox" }, Mailbox, multi, None
106//! }
107//!
108//! fn main() {
109//! let headers = headers! {
110//! XFooEmail: "123@example.com",
111//! XBarMailbox: ("My Funy Name", "notfunny@example.com"),
112//! XBarMailbox: "without.display.name@example.com"
113//! }.unwrap();
114//! }
115//! ```
116
117extern crate media_type;
118#[doc(hidden)]
119pub extern crate soft_ascii_string;
120extern crate quoted_string;
121#[macro_use]
122extern crate failure;
123//extern crate owning_ref;
124mod owning_ref_rs;
125#[macro_use]
126extern crate nom;
127extern crate chrono;
128#[cfg_attr(test, macro_use)]
129extern crate vec1;
130extern crate total_order_multi_map;
131//FIXME[rust/macros use private] remove pub re-export
132#[cfg_attr(test, macro_use)]
133#[doc(hidden)]
134pub extern crate mail_internals as __internals;
135
136#[cfg(feature="serde")]
137extern crate serde;
138#[cfg(all(test, feature="serde"))]
139extern crate serde_test;
140
141#[cfg(all(test, not(feature="traceing")))]
142compile_error! { "testing needs feature `traceing` to be enabled" }
143
144#[cfg(all(feature="serde", not(feature="serde-impl")))]
145compile_error! { "you need to enable \"serde-impl\" when you enable \"serde\"" }
146
147#[macro_use]
148mod macros;
149mod name;
150#[macro_use]
151pub mod error;
152mod header;
153mod convert;
154pub mod data;
155#[macro_use]
156mod header_macro;
157#[macro_use]
158pub mod map;
159pub mod header_components;
160pub mod headers;
161
162pub use self::name::*;
163pub use self::header::*;
164pub use self::convert::*;
165pub use self::header_macro::*;
166pub use self::map::HeaderMap;
167
168
169// I can not reexport a private think anymore, so I need to reexport the
170// extern crate and then make the normal name available, too
171use __internals as internals;