Crate mail_headers_ng

source ·
Expand description

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:


// 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.


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();
}

Re-exports

Modules

  • A number of little helper types, which contain text.
  • module contains the (new) errors emitted by this crate
  • This modules contains all components provided by this library.
  • Module containing the HeaderMap.

Macros

  • Defines a new header types with given type name, filed name and component
  • Create a header map from a list of header’s with ther fields

Structs

  • Note: Normally you will never have the need to create a HeaderName instance by yourself (except maybe for testing). At last as long as you use def_header! for defining custom Headers, which is highly recommended
  • A str wrapper adding a “is us-ascii” soft constraint.

Traits

Type Definitions

  • Type alias for HeaderObjTrait’s trait object.