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

extern crate media_type;
#[doc(hidden)]
pub extern crate soft_ascii_string;
extern crate quoted_string;
#[macro_use]
extern crate failure;
extern crate owning_ref;
#[macro_use]
extern crate nom;
extern crate chrono;
#[cfg_attr(test, macro_use)]
extern crate vec1;
extern crate total_order_multi_map;
//FIXME[rust/macros use private] remove pub re-export
#[cfg_attr(test, macro_use)]
#[doc(hidden)]
pub extern crate mail_internals as __internals;

#[cfg(feature="serde")]
extern crate serde;
#[cfg(all(test, feature="serde"))]
extern crate serde_test;

#[cfg(all(test, not(feature="traceing")))]
compile_error! { "testing needs feature `traceing` to be enabled" }

#[cfg(all(feature="serde", not(feature="serde-impl")))]
compile_error! { "you need to enable \"serde-impl\" when you enable \"serde\"" }

#[macro_use]
mod macros;
mod name;
#[macro_use]
pub mod error;
mod header;
mod convert;
pub mod data;
#[macro_use]
mod header_macro;
#[macro_use]
pub mod map;
pub mod header_components;
pub mod headers;

pub use self::name::*;
pub use self::header::*;
pub use self::convert::*;
pub use self::header_macro::*;
pub use self::map::HeaderMap;


// I can not reexport a private think anymore, so I need to reexport the
// extern crate and then make the normal name available, too
use __internals as internals;