Provider-agnostic mail message types and MailReader/MailSender capability traits
| Tier | foundation |
| Role | unclassified (baselined) |
| Path | crates/foundation/mail-message |
| Edition | 2021 |
| Targets | foundation_mail_message |
| Public items | 20 across 5 modules |
| Tests | 25 |
What it is for
# foundation-mail-message
Provider-agnostic mail message types and capability traits.
See README.md for the full design rationale (OQ1-OQ3 resolutions).
Capabilities
address (other)
Shared From-style address parsing: email/display-name extraction, root-domain
| Item |
|---|
fn extract_email_address(raw : & str) -> Option <String> |
fn extract_display_name(raw : & str) -> Option <String> |
fn extract_root_domain(domain : & str) -> String |
fn is_noreply_local_part(local_part : & str) -> bool |
fn is_machine_sender_local_part(local_part : & str) -> bool |
MailError
Mail operation errors.
| Item |
|---|
pub enum MailError |
MailReader
MailReader — list/fetch capability trait.
| Item |
|---|
pub trait MailReader |
MailSender
MailSender — send capability trait.
| Item |
|---|
pub trait MailSender |
SendReceipt
MailSender — send capability trait.
| Item |
|---|
pub struct SendReceipt |
Attachment
Provider-agnostic mail message types.
| Item |
|---|
pub struct Attachment |
Cursor
Provider-agnostic mail message types.
| Item |
|---|
pub struct Cursor |
Cursor :: fn new(token : impl Into <String>) -> Self |
Cursor :: fn as_str(& self) -> & str |
Email
Provider-agnostic mail message types.
| Item |
|---|
pub struct Email |
Email :: fn body_text(& self) -> Option <& str> |
Email :: fn body_html(& self) -> Option <& str> |
Email :: fn attachments(& self) -> Vec <& Attachment> |
ListPage
Provider-agnostic mail message types.
| Item |
|---|
pub struct ListPage |
MessageId
Provider-agnostic mail message types.
| Item |
|---|
pub struct MessageId |
MessagePart
Provider-agnostic mail message types.
| Item |
|---|
pub enum MessagePart |
How to use it
No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.
Module structure
foundation_mail_message
addresserrorreadersendertypes
flowchart TD n_foundation_mail_message["foundation_mail_message"] n_foundation_mail_message --> n_address["address"] n_foundation_mail_message --> n_error["error"] n_foundation_mail_message --> n_reader["reader"] n_foundation_mail_message --> n_sender["sender"] n_foundation_mail_message --> n_types["types"]
Public surface
`address`
| Item | What it is |
|---|---|
fn extract_email_address(raw : & str) -> Option <String> | Extract the email address embedded in a raw From-style header value ("Name" <email@domain>, bare email@domain, or a quoted-name variant) |
fn extract_display_name(raw : & str) -> Option <String> | Extract the display name from "Name" <email> / Name <email>, if present. |
fn extract_root_domain(domain : & str) -> String | The registrable root domain: the last two labels of domain (e.g |
fn is_noreply_local_part(local_part : & str) -> bool | True for the closed set of conventional noreply local parts (noreply, no-reply, no_reply, donotreply, do-not-reply, do_not_reply) — exact match only, not a prefix check. |
fn is_machine_sender_local_part(local_part : & str) -> bool | True for is_noreply_local_part plus a broader set of automated-sender local parts (notifications, alerts, billing, mailer-daemon, ...), matched as an exact local part or a {pattern}-/{pattern}+ prefix (so alerts-prod@ and alerts+2@ both match alerts). |
`error`
| Item | What it is |
|---|---|
pub enum MailError | Errors that can occur during MailReader/MailSender operations |
`reader`
| Item | What it is |
|---|---|
pub trait MailReader | Capability trait for backends that can list and fetch mail |
`sender`
| Item | What it is |
|---|---|
pub struct SendReceipt | The result of a successful MailSender::send call. |
pub trait MailSender | Capability trait for backends that can send mail |
`types`
| Item | What it is |
|---|---|
pub enum MessagePart | A single content piece of a message: one of its text/HTML bodies, or one attachment |
pub struct Attachment | A file attached to (or embedded in) a message. |
pub struct Email | A provider-agnostic mail message — the input to MailSender::send and the output of MailReader::fetch |
Email :: fn body_text(& self) -> Option <& str> | The first text/plain part, if any. |
Email :: fn body_html(& self) -> Option <& str> | The first text/html part, if any. |
Email :: fn attachments(& self) -> Vec <& Attachment> | All attachment parts, in order. |
pub struct MessageId | A bare message identifier returned by MailReader::list (OQ1) |
pub struct Cursor | An opaque, backend-issued pagination cursor (OQ2) |
Cursor :: fn new(token : impl Into <String>) -> Self | Wrap a backend-issued token |
Cursor :: fn as_str(& self) -> & str | The raw token, to hand back to the same backend on the next call. |
pub struct ListPage | One page of MessageIds from MailReader::list. |
Re-exports. Exported here, defined elsewhere.
| Export | Defined in |
|---|---|
MailError | error::MailError |
MailReader | reader::MailReader |
{Attachment,Cursor,Email,ListPage,MessageId,MessagePart} | types::{Attachment,Cursor,Email,ListPage,MessageId,MessagePart} |
{MailSender,SendReceipt} | sender::{MailSender,SendReceipt} |
{extract_display_name,extract_email_address,extract_root_domain,is_machine_sender_local_part,is_noreply_local_part,} | address::{extract_display_name,extract_email_address,extract_root_domain,is_machine_sender_local_part,is_noreply_local_part,} |
Boundary
Depends on no other workspace tier.
Shares tier foundation with 27 other crates: foundation-audit-log, foundation-basemodels, foundation-bounded-io, foundation-conversation-closure, foundation-crypto-sign, foundation-decisioning, foundation-encounter-vocabulary, foundation-fs-metadata, … (27 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | foundation |
| Architectural role (taxonomy) | unclassified (baselined) |
| Location | crates/foundation/mail-message |
| Vocabulary in force (lexicon) | current |
Dependencies
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
async-trait | ^0.1 | — | no | always |
chrono | ^0.4 | serde | no | always |
serde | ^1 | derive | no | always |
serde_json | ^1 | — | no | always |
thiserror | ^2 | — | no | always |
Development, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
tokio | ^1 | full | no | always |
tokio-test | ^0.4 | — | no | always |
Build. None.
Depended on by. 9 workspace crates.
Signal flow — what reaches this crate, and what it reaches.
flowchart LR n_domain_sender_reputation["domain-sender-reputation"] -->|uses| SELF n_foundation_refresh_policy["foundation-refresh-policy"] -->|uses| SELF n_infrastructure_adapters_google_gmail["infrastructure-adapters-google-gmail"] -->|uses| SELF n_infrastructure_imap["infrastructure-imap"] -->|uses| SELF n_infrastructure_mail_extract["infrastructure-mail-extract"] -->|uses| SELF n_infrastructure_mail_headers["infrastructure-mail-headers"] -->|uses| SELF n_infrastructure_smtp["infrastructure-smtp"] -->|uses| SELF n_operations_mail_sync["operations-mail-sync"] -->|uses| SELF n_tools_mail_manager["tools-mail-manager"] -->|uses| SELF SELF["foundation-mail-message"] classDef self fill:#1f883d,stroke:#1f883d,color:#fff; class SELF self;
Feature flags
No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.
Targets
| Kind | Name | Source |
|---|---|---|
| lib | foundation_mail_message | `src/lib.rs` |
Error model
| Error type | Named by |
|---|---|
MailError | declared, no public signature returns it |
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | none detected |
| async runtime | none detected |
| database access | none detected |
| network I/O | none detected |
| unsafe code | none detected |
| environment variables | none detected |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.
Related capabilities
9 workspace crates depend on this one: domain-sender-reputation, foundation-refresh-policy, infrastructure-adapters-google-gmail, infrastructure-imap, infrastructure-mail-extract, infrastructure-mail-headers, infrastructure-smtp, operations-mail-sync, tools-mail-manager.
Verification
| Kind | Count |
|---|---|
| Unit tests | 25 |
| Integration tests | 0 |
| Examples | 0 |
| Doctests | 0 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
address | 5 | 0 | 10 |
error | 1 | 0 | 5 |
reader | 1 | 0 | 6 |
sender | 2 | 0 | 10 |
types | 6 | 0 | 27 |
What the tests establish, by name:
display_name_absent_for_bare_address—src/address.rsdisplay_name_present—src/address.rsextracts_bare_address—src/address.rsextracts_from_angle_brackets—src/address.rsextracts_quoted_sender—src/address.rsmachine_sender_check_matches_the_pre_hoist_format_based_reference—src/address.rsmachine_sender_matches_hyphen_and_plus_suffixes—src/address.rsnoreply_local_part_is_exact_match_only—src/address.rsroot_domain_strips_subdomains—src/address.rsreader_fetch_missing_id_returns_not_found—src/reader.rsreader_list_folders_returns_provider_native_names—src/reader.rsreader_list_respects_max_results—src/reader.rsreader_only_backend_lists_and_fetches—src/reader.rsdual_capability_backend_implements_both_traits_independently—src/sender.rssender_only_backend_sends_through_trait_object—src/sender.rssender_rejects_message_with_no_recipients—src/sender.rsattachment_holds_metadata_and_optional_content—src/types.rscursor_does_not_parse_or_interpret_its_contents—src/types.rscursor_is_opaque_and_round_trips_through_serde—src/types.rsemail_attachments_are_extracted_from_parts—src/types.rsemail_body_text_and_html_read_from_parts—src/types.rsemail_with_no_body_parts_returns_none—src/types.rsfolders_field_holds_arbitrary_provider_native_names_gmail_and_imap_alike—src/types.rslist_page_carries_messages_and_optional_next_cursor—src/types.rsmessage_id_is_just_id_and_optional_thread_id—src/types.rs
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 20 | 20 |
Public modules with a //! block | 5 | 5 |
pie showData
title Public items with rustdoc
"Documented" : 20
"No rustdoc detected" : 0
Metrics
| Metric | Value |
|---|---|
| Rust source files | 6 |
| Source lines | 1069 |
| Code lines | 718 |
| Public API items | 20 |
| Public modules | 5 |
| Tests | 25 |
| Examples | 0 |
| Cargo features | 0 |
| Direct runtime dependencies | 5 |
| Workspace reverse dependencies | 9 |
pie showData
title Public API by kind
"enum" : 2
"function" : 5
"method" : 5
"struct" : 6
"trait" : 2
pie showData
title Rust source composition
"Code" : 718
"Blank or comment" : 351
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.