summaryrefslogtreecommitdiffstats
path: root/headers/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'headers/README.md')
-rw-r--r--headers/README.md150
1 files changed, 150 insertions, 0 deletions
diff --git a/headers/README.md b/headers/README.md
new file mode 100644
index 0000000..8a49553
--- /dev/null
+++ b/headers/README.md
@@ -0,0 +1,150 @@
+
+# mail-headers
+
+**Provides header specific functionality for the `mail` crate**
+
+---
+
+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:
+
+```rust
+#[macro_use]
+extern crate mail_headers;
+
+// just import all headers
+use mail_headers::*;
+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);
+
+ if let Some(subject) = headers.get_single(Subject) {
+ // as long a you don't play around with custom headers AND
+ // don't mix multiple implementations for the same header
+ // `.unwrap()` is just fine.
+ let subject = subject.expect("mixed different Subject header implementations");
+ println!("found subject: {}", subject);
+ }
+}
+```
+
+## 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.
+
+```rust
+#[macro_use]
+extern crate mail_headers;
+
+use mail_headers::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: components,
+
+ // definitions of the headers or the form
+ // <type_name>, unchecked { <filed_name> }, <component>, <validator>
+ XFooEmail, unchecked { "X-Foo-Email" }, Email , maxOne,
+ XBarMailbox, unchecked { "X-Bar-Mailbox" }, Mailbox, None
+}
+
+fn main() {
+ let headers = headers! {
+ XFooEmail: "123@example.com",
+ XBarMailbox: ("My Funy Name", "notfunny@example.com"),
+ XBarMailbox: "without.display.name@example.com"
+ }.unwrap();
+}
+```
+
+
+## Documentation
+
+Documentation can be [viewed on docs.rs](https://docs.rs/mail-headers).
+(once it is published ;) )
+
+
+## License
+
+Licensed under either of
+
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
+additional terms or conditions.