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;