summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorPhilipp Korber <p.korber@1aim.com>2018-11-16 15:46:43 +0100
committerPhilipp Korber <p.korber@1aim.com>2018-11-16 15:46:43 +0100
commit652d6f0ffeee7302a2cb51059bef75d8b0bb50be (patch)
treec3851592642938172f280f7428d43e08b0fe2cbe /core
parent0947fe8996149fe20a6d47a793f9555790eb2eae (diff)
refactor: merged sources of mail-headers,mail-internals,mail-core, mail
Originally it was palaned to do a merge with `--allow-unrelated-history` but this can not be doesn as `mail-core` has a "invalid" history which has a merge conflict **with itself**. So even rewinding the history on a empty repo is not possible. Instead the code was directly coppied over losing history. But the history is still available in the different `history-backup-*` branches. It is just that the past history is decoupled from the current history.
Diffstat (limited to 'core')
-rw-r--r--core/Cargo.toml43
-rw-r--r--core/README.md94
-rw-r--r--core/examples/readme.rs57
-rw-r--r--core/notes/features/archive_resources.md34
-rw-r--r--core/notes/notes.md334
-rw-r--r--core/notes/structure.md157
-rw-r--r--core/src/compose.rs430
-rw-r--r--core/src/context.rs328
-rw-r--r--core/src/default_impl/cpupool.rs47
-rw-r--r--core/src/default_impl/fs.rs262
-rw-r--r--core/src/default_impl/message_id_gen.rs154
-rw-r--r--core/src/default_impl/mod.rs42
-rw-r--r--core/src/default_impl/mux.rs64
-rw-r--r--core/src/default_impl/simple_context.rs85
-rw-r--r--core/src/encode.rs203
-rw-r--r--core/src/error.rs293
-rw-r--r--core/src/iri.rs276
-rw-r--r--core/src/lib.rs63
-rw-r--r--core/src/macros.rs52
-rw-r--r--core/src/mail.rs906
-rw-r--r--core/src/mime.rs121
-rw-r--r--core/src/resource/data.rs348
-rw-r--r--core/src/resource/mod.rs181
-rw-r--r--core/src/resource/source.rs71
-rw-r--r--core/src/utils.rs33
-rwxr-xr-xcore/test.sh8
-rw-r--r--core/test_resources/img.jpgbin0 -> 630 bytes
-rw-r--r--core/test_resources/img.pngbin0 -> 324 bytes
-rw-r--r--core/test_resources/test.pdfbin0 -> 1779 bytes
-rw-r--r--core/test_resources/test2.pdfbin0 -> 24771 bytes
-rw-r--r--core/test_resources/text.txt1
-rw-r--r--core/test_resources/text.utf8.txt1
-rw-r--r--core/tests/mail.rs7
-rw-r--r--core/tests/resource/load_file.rs55
-rw-r--r--core/tests/resource/mod.rs2
35 files changed, 4752 insertions, 0 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml
new file mode 100644
index 0000000..7f6b7b2
--- /dev/null
+++ b/core/Cargo.toml
@@ -0,0 +1,43 @@
+[package]
+name = "mail-core"
+version = "0.6.0-wip"
+description = "[internal/mail-api] provides the Mail type for the mail-api crates (inkl. multipart mime bodies, builder and resource type)"
+authors = ["Philipp Korber <p.korber@1aim.com>"]
+keywords = ["mail-api", "internal"]
+categories = []
+license = "MIT OR Apache-2.0"
+readme = "./README.md"
+documentation = "https://docs.rs/mail-core"
+repository = "https://github.com/1aim/mail-core"
+
+[features]
+serde-impl = ["serde", "mail-headers/serde-impl"]
+default = ["default_impl_cpupool"]
+default_impl_cpupool = ["futures-cpupool"]
+
+[dependencies]
+failure = "0.1.2"
+futures = "0.1.24"
+log = "0.3.8"
+rand = "0.3.15"
+vec1 = "1"
+mail-internals = { git="https://github.com/1aim/mail-internals" }
+mail-headers = { git="https://github.com/1aim/mail-headers" }
+chrono = "0.4"
+soft-ascii-string = "1.0"
+serde = { version="1.0", optional=true, features=["derive"] }
+checked_command = "0.2.2"
+
+[dependencies.mime]
+git="https://github.com/1aim/mime"
+branch="parser_revamp"
+version="0.4.0"
+
+[dependencies.futures-cpupool]
+optional = true
+version = "0.1.5"
+
+[dev-dependencies]
+serde_json = "1.0"
+serde_test = "1.0.80"
+
diff --git a/core/README.md b/core/README.md
new file mode 100644
index 0000000..c1d04af
--- /dev/null
+++ b/core/README.md
@@ -0,0 +1,94 @@
+
+# mail-core
+
+**Provides the core mail type `Mail` for the `mail` crate.**
+
+---
+
+This crate provides the type called `mail` as well as ways
+to create it. It also provides the builder context interface
+and the `Resource` type, which is used to represent mail bodies.
+Especially such which are attachments or embedded images.
+
+
+# Example
+
+```rust
+extern crate futures;
+// Note that the `mail` crate provides a facade re-exporting
+// all relevant parts.
+extern crate mail_core;
+extern crate mail_internals;
+#[macro_use]
+extern crate mail_headers;
+
+use std::str;
+use futures::Future;
+
+use mail_internals::MailType;
+
+// In the facade this is the `headers` module.
+use mail_headers::{
+ headers::*,
+ header_components::Domain
+};
+
+// In the facade this types (and the default_impl module)
+// are also exposed at top level
+use mail_core::{
+ Mail,
+ default_impl::simple_context,
+ error::MailError
+};
+
+fn print_some_mail() -> Result<(), MailError> {
+ // Domain will implement `from_str` in the future,
+ // currently it doesn't have a validator/parser.
+ // So this will become `"example.com".parse()`
+ let domain = Domain::from_unchecked("example.com".to_owned());
+ // Normally you create this _once per application_.
+ let ctx = simple_context::new(domain, "xqi93".parse().expect("we know it's ascii"))
+ .expect("this is basically: failed to get cwd from env");
+
+ let mut mail = Mail::plain_text("Hy there! 😁");
+ mail.insert_headers(headers! {
+ _From: [("I'm Awesome 😁", "bla@examle.com")],
+ _To: ["unknow@example.com"],
+ Subject: "Hy there message 😁"
+ }?);
+
+ // We don't added any think which needs loading but we could have
+ // and all of it would have been loaded concurrent and async.
+ let encoded = mail.into_encodable_mail(ctx.clone())
+ .wait()?
+ .encode_into_bytes(MailType::Ascii)?;
+
+ let mail_str = str::from_utf8(&encoded).unwrap();
+ println!("{}", mail_str);
+ Ok(())
+}
+
+fn main() {
+ print_some_mail().unwrap()
+}
+```
+
+
+Documentation can be [viewed on docs.rs](https://docs.rs/mail-core)
+(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.
diff --git a/core/examples/readme.rs b/core/examples/readme.rs
new file mode 100644
index 0000000..5e0cd42
--- /dev/null
+++ b/core/examples/readme.rs
@@ -0,0 +1,57 @@
+extern crate futures;
+// Note that the `mail` crate provides a facade re-exporting
+// all relevant parts.
+extern crate mail_core;
+extern crate mail_internals;
+#[macro_use]
+extern crate mail_headers;
+
+use std::str;
+use futures::Future;
+
+use mail_internals::MailType;
+
+// In the facade this is the `headers` module.
+use mail_headers::{
+ headers::*,
+ header_components::Domain
+};
+
+// In the facade this types (and the default_impl module)
+// are also exposed at top level
+use mail_core::{
+ Mail,
+ default_impl::simple_context,
+ error::MailError
+};
+
+fn print_some_mail() -> Result<(), MailError> {
+ // Domain will implement `from_str` in the future,
+ // currently it doesn't have a validator/parser.
+ // So this will become `"example.com".parse()`
+ let domain = Domain::from_unchecked("example.com".to_owned());
+ // Normally you create this _once per application_.
+ let ctx = simple_context::new(domain, "xqi93".parse().expect("we know it's ascii"))
+ .expect("this is basically: failed to get cwd from env");
+
+ let mut mail = Mail::plain_text("Hy there! 😁", &ctx);
+ mail.insert_headers(headers! {
+ _From: [("I'm Awesome 😁", "bla@examle.com")],
+ _To: ["unknow@example.com"],
+ Subject: "Hy there message 😁"
+ }?);
+
+ // We don't added any think which needs loading but we could have
+ // and all of it would have been loaded concurrent and async.
+ let encoded = mail.into_encodable_mail(ctx.clone())
+ .wait()?
+ .encode_into_bytes(MailType::Ascii)?;
+
+ let mail_str = str::from_utf8(&encoded).unwrap();
+ println!("{}", mail_str);
+ Ok(())
+}
+
+fn main() {
+ print_some_mail().unwrap()
+} \ No newline at end of file
diff --git a/core/notes/features/archive_resources.md b/core/notes/features/archive_resources.md
new file mode 100644
index 0000000..6cc5071
--- /dev/null
+++ b/core/notes/features/archive_resources.md
@@ -0,0 +1,34 @@
+
+# Feature: Archive Resources
+
+## Context
+
+Currently the resources are loaded over a IRI it is possible to make
+a iri point _into_ an archive e.g. the Java `jar` scheme does support
+it so a program which wants to use e.g. whole templates from a
+archive could implement a resource loaded with a `archiev` prefix pointing
+into an archive.
+
+## Problem
+
+If you point into an archive you would want to 1. open/load it 2.
+get all resources you need for the given mail 3. close it. But the
+per resource IRI architecture would require you to open/load it
+for every Resource in it separately, clever caching can be done to some degree
+(while it's open we do not need to open it another time etc.) but has
+limitations.
+
+## Solution / Feature
+
+let templates define a `resource_preload` and iri which
+would point the the archive (but could also be used for other,
+similar use cases, e.g. sharing a db connection).
+
+Add a function to `ResourceLoaderComponent` like `fn use_preload(&self, preload: &IRI) {}`
+and `fn stop_using_preload(preload: &IRI) {}` which resource loader,
+who can handle archives can use to preload/open an archive.
+
+### Alternations
+
+instead of a start/stop preload function have some scope based function,
+potentially attached to the _Context_ instead of the `ResourceLoaderComponent` \ No newline at end of file
diff --git a/core/notes/notes.md b/core/notes/notes.md
new file mode 100644
index 0000000..1c69749
--- /dev/null
+++ b/core/notes/notes.md
@@ -0,0 +1,334 @@
+
+# Outer Most interface
+
+something like a Mailer which might implement tokio_servie::Service (if
+so multiple parameters are wrapped into a tupple)
+
+mailer contains information like `from`
+
+`mailer.send_mails( recipients_data, mail_gen )`
+
+where recipients_data is a iterable mapping from address to recipient specific data,
+e.g. `Vec<(Address, Data)>`
+
+and mail_gen is something like `trait MailGen { fn gen_mail( from, to, data, bits8support ) -> MailBody; }`
+
+`MailBody` is not `tokio_smtp::MailBody` but has to implement nessesray contraints,
+(e.g. implemnting `toki_smtp::IntoMailBody` not that for the beginning this will be
+hard encoded but later one a generic variation allowing `smtp` to be switched out
+by something else is also possible`)
+
+MailGen implementations are not done by hand but implemented ontop of something
+like a template spec e.g. `struct TemplateSpec { id_template: TemplateId, additional_appendixes: Vec<Appendix> }`
+
+Where `TemplateId` can is e.g. `reset_link` leading to the creation of a `html` with alternate `plain`
+mail iff there is a `reset_link.html` and a `reset_link.plain` template. A `reset_link.html.data`
+folder could be used to define inline (mime related) appendixes like embedded images,
+but we might want to have a way to define such embeddigns through the data (
+E.g. by mapping `Data => TemplateEnginData` and replacing `EmbeddedFile` variations
+by a new related id and adding the `EmbeddedFile(data)` data to the list of embeddings)
+
+
+
+# List of parts possible non-ascii and not ascii encodable
+
+- local-part (address/addr-spec/local-part)
+
+# Limitations
+
+Line length limit:
+
+SHOULD be no more than 78 chars (excluding CRLF!)
+MUST NOT be more than 998 chars (excluding CRLF)
+
+# Orphan `\n`,`\r`
+
+MUST NOT occur in header (except for folding)
+MUST NOT occur in body (except for newline)
+
+## Header specific limitations
+
+- encoded word max length of 75 chars
+- spaces around encoed words are ignored??
+
+
+# Email Address part (a@b.e)
+
+- there is a `domain-literal` version which does use somthing like `[some_thing]`,
+ we can use puny code for converting domains into ascii but probably can't use
+ this with `domain-literal`'s
+
+- `local-part` is `dot-atom` which has leading and trailing `[CFWS]` so comments are alowed
+
+- MessageId uses a email address like syntax but without supporting spaces/comments
+
+
+# MIME
+
+fields containing mime types can have parameters with a `<type>; key=value` style
+this is mainly used for `multipart/mixed; boundary=blablabla` and similar.
+
+You have to make sure the boundary does not appear in any of the "sub-bodies",
+this is kinda easy for bodies with e.g. content transfer encoding Base64,
+but can be tricky in combination with some other content as normal text
+can totally contain the boundary. To prevent this:
+
+- use long boundary strings
+- encode the body with base64 even if it's "just" ascii
+ - OR check the content and encode parts of it if necessary
+
+you can have multipart in multipart creating a tree,
+make sure you don't mix up the boundaries
+
+
+A body part does not have to have any headers, assume default values if
+there is no header, bodies which have no header _have to start with a
+blank line_ separating 0 headers from the body.
+
+Header fields of bodies which do not start with `Content-` _are ignored_!
+
+Contend types:
+
+- `mixed`, list of sub-bodies with mixed mime types, might be displayed inline or as appendix
+ - use >>`Content-Disposition` (RFC 2183)<< to controll this, even through it's not standarized yet (or is it by now?)
+ - default body mime type is `text/plain`
+- `digest` for combining muliple messages of content type `message/rfc822`
+ - e.g. `(multipar/mixed ("table of content") (multipart/digest "message1", "message2"))`
+ - `message` (mainly `message/rfc822`) contains _another_ email, e.g. for digest
+ - wait is there a `multipart/message`?? proably not!
+- `alternative` multiple alternative versions of the "same" information
+ - e.g. `(multipart/alternative (text/plain ...) (text/html ...))`
+ - _place preferred form last!_ (i.e. increasing order of preference)
+ - interesting usage with `application/X-FixedRecord`+`application/octet-stream`
+- `related` (RFC 2387) all bodies are part of one howl, making no (less) sense if placed alone
+ - the first part is normally the entry point, but this can be chaged through parameters
+ - (only relevant for parsing AND interpreting it, but not for generating as we can always use the default)
+ - Content-ID is used to specify a id on each body respectivly which can be used to refer to it (e.g. in HTML)
+ - in html use e.g. `<img src="cid:the_content_id@goes.here>....</img>`
+ - example is `(multipart/relat (text/html ...) (image/jpeg (Content-ID <bala@bal.bla>) ...))` for embedding a image INTO a HTML mail
+- `report`
+- `signed` (body part + signature part)
+- `encrypted` (encryption information part + encrypted data (`application/octet-stream`))
+- `form-data`
+- `x-mixed-replace` (for server push, don't use by now there are better ways)
+- `byteranges`
+
+
+Example mail structure:
+
+```
+(multipart/mixed
+ (multipart/alternative
+ (text/plain ... )
+ (multipart/related
+ (text/hmtl ... '<img src="cid:contentid@1aim.com"></img>' ... )
+ (image/png (Content-ID <contentid@1aim.com>) ... )
+ ... ))
+ (image/png (Content-Disposition attachment) ...)
+ (image/png (Content-Disposition attachment) ...))
+```
+
+Possible alternate structure:
+
+```
+(multipart/mixed
+ (multipart/related
+
+ (multipart/alternative
+ (text/plain ... '[cid:contentid@1aim.com]' ... )
+ (text/html ... '<img src="cid:contentid@1aim.com"></img>' ... ) )
+
+ (image/png (Content-ID <contentid@1aim.com>) ... ) )
+
+ (image/png (Content-Disposition attachment) ...)
+ (image/png (Content-Disposition attachment) ...))
+```
+
+but I have not seen the `[cid:...]` for text/plain in any standard, through it might be there.
+Also if se we might still have a related specific for the html (for html only stuff) so:
+- place Embedding in Data in the outer `multipart/related`
+- place Embedding returned by the template in inner `multipart/related`
+
+# Attatchment
+
+proposed filenames for attachments can be given through parameters of the disposition header
+
+it does not allow non ascii character there!
+
+see rfc2231 for more information, it extends some part wrt.:
+
+- splitting long parameters (e.g. long file names)
+- specifying language and character set
+- specifying language for encoded words
+
+# Encoded Words
+
+extended by rfc2231
+
+additional limits in header fields
+
+header containing encoded words are limited to 76 bytes
+
+a "big" text chunk can be split in multiple encoded words seperated by b'\r\n '
+
+non encoded words and encoded words can apear in the same header field, but
+must be seperate by "linear-white-space" (space) which is NOT removed when
+decoding encoded words
+
+encoded words can appear in:
+
+- `text` sections where `text` is based on RFC 822! (e.g. Content-Description )
+ - in context of RFC 5322 this means `unstructured` count's as text
+- `comments` (as alternative to `ctext`,`quoted-pair`,`comment`
+- `word`'s within a `phrase`
+
+**Therefor it MUST NOT appear in any structured header field except withing a `comment` or `phrase`!**
+
+**You have to encode text which looks like an encoded word**
+
+
+
+limitations:
+
+- in comment's no ')',')' and '"'
+- in headers no ' '
+
+
+# Other
+
+there is no `[CFWS]` after the `:` in Header fields,
+but most (all?) of the parts following them are allowed
+to start with a `[CFWS]`. (exception is unstructured where
+a `CFWS` can be allowed but also MIGHT be part of the
+string)
+
+CFWS -> (un-) foldable whitespace allowing comments
+FWS -> (un-) foldable whitespace without comments
+
+
+# Relevant RFCs
+5321, 5322, 6854, 3492, 2045, 2046, 2047, 4288, 4289, 2049, 6531, 5890
+
+make sure to not use the outdated versions
+
+RFC7595: Registering URI schemes
+
+
+# Parsing Notes
+
+be strict when parsing (e.g. only ws and printable in subject line)
+
+if "some other" strings should still be supported do not do zero
+copy, but instead add the data to a new buff _replacing invalid
+chars with replacement symbol or just stripping them_
+
+
+# Non-utf8 Non-Ascci bytes in Mail body
+
+The mail body can contain non-utf8, non-ascii data (e.g.
+utf16 data, images etc.) WITHOUT base64 encoding if
+8BITMIME is supported (note there is also BINARY and CHUNKING)
+
+smtp still considers _the bytes_ corresponding to CR LF and DOT special.
+
+- there is a line length limit, lines terminate with b'CRLF'
+- b'.CRLF' does sill end the body (if preceeded by CRLF, or body starts with it)
+ - so dot-staching is still done on protocol level
+
+
+
+## Hot to handle `obs-` parsings
+
+we have to be able to parse mails with obsolete syntax (theoretically)
+but should never genrate such mails, the encder excepts its underlying
+data to be correct, but it might not be if we directly place `obs-`
+parsed data there. For many parts this is no problem as the
+`obs-` syntax is a lot about having FWS at other positions,
+_between components_ (so we won't have a problem with the encoder).
+Or some additional obsolete infromations (which we often/allways can just
+"skip" over). So we have to check if there are any braking cases and if
+we have to not zero copy them when parsing but instead transform them
+into a valide representation, in worst case we could add a `not_encodable`
+field to some structs.
+
+# TODO
+check if some parts are empty and error if encode is called on them
+e.g. empty domain
+
+make sure trace and resend fields are:
+
+1. encoded in order (MUST)
+2. encoded as blocks (MUST?)
+3. encoded before other fields (SHOULD)
+
+as people may come up with their own trace like fileds,
+rule 1 and 2 should appy to all fields
+
+
+make sure trace,resent-* are multi fields
+
+add a RawUnstructured not doing any encoding, but only validity checking
+
+# Postponded
+
+`component::Disposition` should have a `Other` variant, using `Token` (which
+means a general extension token type is needed)
+
+other features like signature, encryption etc.
+
+check what happens if I "execute" a async/mio/>tokio<
+based future in a CPU pool? Does it just do live
+polling in the thread? Or does it act more intelligent?
+or does it simply fail?
+
+just before encoding singlepart bodies, resource is resolved,
+therefore:
+
+1. we now have the MediaType + File meta + TransferEncoding
+2. add* ContentType header to headers
+3. add* ContentTransferEncoding header to headers
+4. add* file meta infor to ContentDisposition header if it exists
+5. note that >add*< is not modifying Mail, but adds it to the list of headers to encode
+
+
+warn when encoding a Disposition of kind Attachment which's
+file_meta has no name set
+
+
+// From RFC 2183:
+// NOTE ON PARAMETER VALUE LENGHTS: A short (length <= 78 characters)
+// parameter value containing only non-`tspecials' characters SHOULD be
+// represented as a single `token'. A short parameter value containing
+// only ASCII characters, but including `tspecials' characters, SHOULD
+// be represented as `quoted-string'. Parameter values longer than 78
+// characters, or which contain non-ASCII characters, MUST be encoded as
+// specified in [RFC 2184].
+provide a gnneral way for encoding header parameter which follow the scheme:
+`<mainvalue> *(";" <key>"="<value> )` this are ContentType and ContentDisposition
+ for now
+
+
+IF Item::Encoded only appears as encoded word, make it Item::Encoded word,
+possible checking for "more" validity then noew
+
+
+email::quote => do not escape WSP, and use FWS when encoding
+also make quote, generally available for library useers a
+create_quoted_string( .. )
+
+# Dependencies
+
+quoted_printable and base64 have some problems:
+1. it's speaking of a 76 character limit where it is 78
+ it seems they treated the RFC as 78 character including
+ CRLF where the RFC speaks of 78 characters EXCLUDING
+ CRLF
+2. it's only suited for content transfer encoding the body
+ as there is a limit of the length of encoded words (75)
+ which can't be handled by both
+
+also quoted_printable has another problem:
+3. in headers the number of character which can be displayed without
+ encoding is more limited (e.g. no ' ' ) quoted_printable does not
+ respect this? (TODO CHECK THIS)
+ \ No newline at end of file
diff --git a/core/notes/structure.md b/core/notes/structure.md
new file mode 100644
index 0000000..775fa47
--- /dev/null
+++ b/core/notes/structure.md
@@ -0,0 +1,157 @@
+# **Warning: document is not up to date**
+
+# Naming differences
+
+(note that `foo/bar` means crate `foo` with feature `bar` enabled)
+
+- `mail-codec` => `mail-encode`
+- `mail-codec-composition` => `mail-encode-compose`
+- `mail-codec-composition/smtp` => `mail-tokio-smtp/encode`
+- `mail-headers` => `mail-headers/encode`
+- `mail-internals` => `mail-core/encode`
+
+
+# Dependency Chart
+
+(updated)
+```ascii
+
+
+ mail-smtp mail-templates (maybe at some point)mail-parser
+new-tokio-smtp---------/ | | \ |
+ | | \-handle-bars |
+ <[mail-core]>----/--------------/-----------------------------------/
+ |
+ |
+ mail-headers
+ |
+ |
+ mail-internals
+```
+
+crates marked with a * have both parser and encoder specific parts,
+which are opt-in/-out through features.
+
+# Descriptions
+
+## Mail-Core
+
+This crate provides parts used by all other parts using
+the `encode`/`parse` features encoding/parsing specific
+parts are enabled/disabled. (Currently it's just encoding).
+
+Parts included are the EncodingBuffer, HeaderMap, Header traits,
+encoding traits, bindings to other encoding libraries like
+base64, percent-encode and similar.
+
+## Mail-Headers
+
+A create providing implementations for the most
+mail-internals headers. Like `mail-core` encoding/parsing specific
+parts can be enabled/disabled using the `encode`/`decode`
+feature. A Header basically consists of a name and a Header component,
+which can be encoded and represents the header field.
+
+Many of those components can be reused at different
+points, e.g. `Mailbox`/`MailboxList`/`Email`/`Phrase`/...
+
+
+## Mail-Encode
+
+This crate provides a basic mechanism to create and
+encode mails with includes a Mail types which can
+represent any form of mails, from simple text mails
+to complex multipart mails. While this API can be
+used to represent any mail it is not nessesary the
+most convinient to use, as it requires the user to
+handle aspects like e.g. which multipart content type
+is used, and how they are structured.
+
+Additional to the Mail struct it provides a mechanism
+to encode the Mail struct with the EncodingBuffer provided
+by `mail-core` produceing a mail in form of a
+string, ascii-string or bytes a required by the consumer.
+(the encoder does know about 7bit, 8bit and utf8 i.e.
+internationalized mails).
+
+As a mail can contain all kinds of embedded data (e.g.
+atachments, embeded images in a html mail etc.). This
+create also provides a way to handle such resources
+as part of a mail.
+
+
+## Mail-Encode-Compose
+
+Is build on-top of `mail-encode` providing traits and mechanism,
+to bind in template engines, allowing the API consumer to
+create mails based on from, to, subject, template_id and
+template_data. The template engine only has to provide
+a number of alternate bodies with embeddings/attachments
+caused by them. The mail-composition crate takes care of
+composing them into a mail multipart tree
+(using `multipart/related`,`multipart/mixed`, etc.)
+
+Currently `mail-composition` does not have explicit support for
+e.g. encryption and some other "more special" multipart
+bodies. Nevertheless by using the API provided by Mail this
+mail can still be created, they do just not jet bind with
+the template engine by default.
+
+The crate also provides a pre-build template engine through a
+feature which just needs another template engine to render
+mail content bodies (e.g. text/html) and handles all the
+other parts, like e.g. providing a logo for an HTML mail
+as an embedding (as a side note generation of CID's and
+providing them to the template data is already handled)
+
+# Mail
+
+A facade for all `mail-*` crates, providing a `encode`
+`parse` feature to enable/disable the encoding/parsing
+parts, and more fine grained features for more fain
+grained control over what is included. This
+takes advantage of rust features being additive, e.g.
+if one dependency includes `mail/encode` and one `mail/decode`
+than rust will only include one time `mail` with both
+`encode` and `decode` enabled.
+
+(this crate does not yet exist)
+
+
+# Mail-Tokio-Smtp
+
+This crate will provide bindings between the mail
+crates and a crate providing tokio-smtp support.
+While smtp is mainly a transport protocol this
+crate provides bindings to make thinks easy to
+use and setup, e.g. the `mail-encode-compose`
+library does provide a method `compose_mail(MailSendData) -> Result<Mail>`
+(called on a combination of Context and TemplateEngine),
+but if you want to use this as a request in a smtp
+service to send a mail, there is quite a bit of bind
+code doing everything from calling compose_mail, making
+it encodable, encoding it and sending the right smtp
+commands.
+
+Currently this functionality lives in `mail-encode-compose`
+under the `smtp` feature and use `tokio-smtp` as binding
+library and is limited to binding with the mechanism provided
+in `mail-encode-compose` but not general `Mail` structs (through
+is will change in the future)
+
+
+# Mail-parse
+
+A crate providing functionality for parsing mails, it
+will use a combination of `Arc`/`Rc` and `OwningRef`
+to allow a zero-copy parsing of mails, nevertheless
+as mail normaly do contain parts further encoded in
+e.g. base64 it will provide a mechanism where parts
+of the mail can be shadowed by a decoded version
+of the part generated on-demand/lazily.
+
+**This crate currently does not exist, and focus lies
+on the encoding based crates**
+
+Through the crate structure is setup to include parsing
+specific parts in the future. \ No newline at end of file
diff --git a/core/src/compose.rs b/core/src/compose.rs
new file mode 100644
index 0000000..a928628
--- /dev/null
+++ b/core/src/compose.rs
@@ -0,0 +1,430 @@
+//! This module provides utilities for composing multipart mails.
+//!
+//! While the `Mail` type on itself can represent any multipart
+//! mail most mails have a certain pattern to their structure,
+//! consisting mainly of `multipart/mixed` for attachments,
+//! `multipart/alternative` for alternative bodies and
+//! `multipart/related` for including embedded resources which
+//! can be used in the mail bodies like e.g. a logo.
+//!
+//! This module provides the needed utilities to more simply
+//! create a `Mail` instance which represents this kind of
+//! mails.
+
+//-------------------------------------------------------------\\
+// NOTE: Implementations for creating (composing) mails are ||
+// split from the type dev, and normal impl blocks and placed ||
+// in the later part of the file for better readability. ||
+//-------------------------------------------------------------//
+
+use media_type::{MULTIPART, ALTERNATIVE, RELATED, MIXED};
+use vec1::Vec1;
+
+#[cfg(feature="serde")]
+use serde::{Serialize, Deserialize};
+