Skip to main content

Service

Struct Service 

Source
pub struct Service { /* private fields */ }

Implementations§

Source§

impl Service

Source

pub async fn build(cfg: CoreConfig, sink: Arc<dyn EventSink>) -> Result<Service>

Build the engine: open the DB, migrate, spawn workers, prepare listeners. Doesn’t bind any sockets — call Service::start_all.

Source

pub fn subscribe(&self) -> Receiver<CoreEvent>

Subscribe to engine events. Each call returns a fresh broadcast::Receiver; consumers that lag behind by more than the channel capacity (currently 1024) will receive Lagged errors and must reconnect. This is the canonical way for the CLI tail, the SSE endpoint, the wait_for_email primitive, and external consumers to observe events.

Source

pub fn set_log_level_controller(&self, ctl: Arc<dyn Fn(bool) + Send + Sync>)

Install a callback the engine invokes when the persisted AdvancedPrefs.debug_logging value changes (and once at start_all to honor the initial value). The embedder owns the tracing_subscriber stack; this lets the engine drive a filter reload without depending on the subscriber implementation.

Idempotent — calling it again replaces the previous controller.

Source

pub async fn start_all(&self) -> Result<()>

Start every persisted mailbox’s listener + the HTTP API. Idempotent.

Source

pub async fn restart_http(&self) -> Result<()>

Tear down the running HTTP listener (if any) and start a fresh one with whatever’s currently persisted in BackendSettings. Used by update_settings to apply network-pref changes live without requiring an app restart.

No-op when the service hasn’t reached start_all yet — the boot path will pick up the new settings when it gets there. If the rebind fails, the previous listener stays torn down and the error is propagated so the caller can revert the patch.

Source

pub async fn stop_all(&self) -> Result<()>

Source

pub fn status(&self) -> ServerStatus

Source

pub fn http_addr(&self) -> Option<SocketAddr>

The HTTP API’s bound socket address, if the server is running.

Source

pub fn mailbox_addr(&self, mailbox_id: &str) -> Option<SocketAddr>

The bound SMTP socket address for a given mailbox listener.

Source

pub fn handle(&self) -> ServiceHandle

Source

pub fn config(&self) -> &CoreConfig

Source

pub async fn list_mailboxes( &self, project_id: Option<&str>, ) -> Result<Vec<Mailbox>>

Source

pub async fn get_mailbox(&self, id: &str) -> Result<Mailbox>

Source

pub async fn create_mailbox(&self, input: CreateMailboxInput) -> Result<Mailbox>

Source

pub async fn update_mailbox( &self, id: &str, patch: UpdateMailboxInput, ) -> Result<Mailbox>

Source

pub async fn delete_mailbox(&self, id: &str) -> Result<()>

Source

pub async fn suggest_mailbox_port(&self, start: Option<u16>) -> Result<u16>

Suggest a free SMTP port for a new mailbox. Walks upward from start (defaulting to 1025), skipping ports already in use by another mailbox in this DB and probe-binding each candidate so external collisions are caught too. Cheap (microseconds per probe on loopback) so we don’t bother caching engine-side.

Advisory only: the actual create_mailbox is authoritative and will return PortInUse if the suggestion was beaten by a racing create or by a process that grabbed the port between the suggestion and the bind.

Source

pub async fn start_mailbox(&self, id: &str) -> Result<()>

Bring a mailbox’s SMTP listener online and clear the persistent paused intent. Idempotent — calling it on a running mailbox returns Ok. Bind failures propagate so the UI can revert its optimistic update and show the actual reason.

Source

pub async fn stop_mailbox(&self, id: &str) -> Result<()>

Tear down a mailbox’s SMTP listener and remember the user intent so the listener stays down across restarts. Idempotent.

Source

pub async fn create_ephemeral( &self, input: CreateEphemeralInput, ) -> Result<EphemeralHandle>

Source

pub async fn list_emails( &self, mailbox_id: &str, limit: u32, offset: u32, ) -> Result<Vec<EmailSummary>>

Source

pub async fn get_email(&self, id: &str) -> Result<EmailDetail>

Source

pub async fn get_email_raw(&self, id: &str) -> Result<Vec<u8>>

Source

pub async fn get_email_smtp_transcript( &self, id: &str, ) -> Result<Option<String>>

Load the SMTP transcript captured at ingest time, if present. Returns Ok(None) when the email exists but the transcript pref was off when it was received (the common case for older mail).

Source

pub async fn delete_email(&self, id: &str) -> Result<()>

Source

pub async fn clear_mailbox(&self, mailbox_id: &str) -> Result<u64>

Clear all non-pinned emails from a mailbox. Pinned emails (set via Self::set_pinned) survive. Use Self::purge_mailbox to wipe everything including pinned.

Source

pub async fn purge_mailbox(&self, mailbox_id: &str) -> Result<u64>

Wipe every email in a mailbox — pinned ones included. Use only for explicit “purge” actions (rare).

Source

pub async fn set_pinned(&self, id: &str, pinned: bool) -> Result<()>

Source

pub async fn set_starred(&self, id: &str, starred: bool) -> Result<()>

Source

pub async fn set_note(&self, id: &str, note: Option<&str>) -> Result<()>

Source

pub async fn set_tag(&self, id: &str, tag: Option<&str>) -> Result<()>

Set or clear the tag on an email. Plus-addressing (user+tag@host) sets this automatically at ingest; this method lets users override or clear it manually.

Source

pub async fn release_email( &self, id: &str, to: &str, relay: &RelayConfig, ) -> Result<()>

Forward a captured email to a real address via an external SMTP relay. The original raw bytes are sent unchanged; the envelope MAIL FROM defaults to the captured sender and the envelope recipient is the new to.

Audit-logged (PROD.md §9.3): this is the only public-Service method that produces outbound network traffic, so users need a clear trail of when releases happen.

Source

pub async fn search_emails( &self, q: &str, mailbox_id: Option<&str>, limit: u32, ) -> Result<Vec<EmailSummary>>

Source

pub async fn mark_read(&self, id: &str, read: bool) -> Result<()>

Source

pub async fn get_attachment_blob( &self, attachment_id: &str, ) -> Result<(Vec<u8>, Option<String>, Option<String>)>

Source

pub async fn get_chaos(&self, mailbox_id: &str) -> Result<ChaosConfig>

Source

pub async fn set_chaos(&self, mailbox_id: &str, cfg: ChaosConfig) -> Result<()>

Source

pub async fn list_bounce_rules( &self, mailbox_id: &str, ) -> Result<Vec<BounceRule>>

Source

pub async fn upsert_bounce_rule(&self, rule: BounceRule) -> Result<BounceRule>

Source

pub async fn delete_bounce_rule(&self, id: &str) -> Result<()>

Source

pub async fn get_settings(&self) -> Result<BackendSettings>

Source

pub async fn update_settings(&self, patch: SettingsPatch) -> Result<()>

Source

pub async fn analyze_spam(&self, id: &str) -> Result<SpamReport>

Score a captured email’s spam-likelihood. Local heuristics only; no network.

Extract + classify every link in a captured email . Does not HEAD-check links.

Source

pub async fn analyze_auth(&self, id: &str) -> Result<AuthReport>

Inspect SPF / DKIM / DMARC headers and predict pass/fail . Header inspection only.

Source

pub async fn analyze_list_unsub(&self, id: &str) -> Result<UnsubReport>

Validate the List-Unsubscribe / List-Unsubscribe-Post headers per RFC 2369 + RFC 8058.

Source

pub async fn render_preview( &self, id: &str, profile: Profile, ) -> Result<RenderedPreview>

Render the email’s HTML body through a client profile . Returns the transformed HTML + a list of transforms that ran.

Source

pub async fn lint_html(&self, id: &str) -> Result<LintReport>

Lint the email’s HTML for known client incompatibilities.

Source

pub async fn audit_a11y(&self, id: &str) -> Result<A11yReport>

Accessibility check on the email’s HTML.

Source

pub async fn export_recording( &self, mailbox_id: &str, label: Option<String>, ) -> Result<Recording>

Snapshot every email in a mailbox into a portable .postcrate recording. The result serializes to JSON via serde; the caller is responsible for persisting it.

Source

pub async fn replay_recording( &self, mailbox_id: &str, recording: &Recording, ) -> Result<u64>

Replay a recording’s messages straight into a mailbox by pushing them through the ingest worker. SMTP listeners, chaos, and bounce rules are bypassed — this is for fixture restoration, not for re-running a scenario. Use Self::replay_email for a single SMTP-driven re-send.

Source

pub async fn replay_email( &self, id: &str, target_mailbox_id: &str, ) -> Result<()>

Re-inject one captured email’s raw bytes into a (possibly different) mailbox via the local SMTP listener — exercises chaos + bounce rules + parsing the way a real send would.

Source

pub async fn wait_for_email( &self, predicate: EmailPredicate, timeout: Duration, ) -> Result<WaitOutcome>

Block up to timeout for an email that satisfies predicate.

Sequence:

  1. Subscribe to the event stream first (so we don’t miss an email that arrives between scan + subscribe).
  2. Do a one-shot scan of recent emails in case it already arrived before the call.
  3. Otherwise consume the broadcast until timeout.

The returned crate::matcher::WaitOutcome always carries the list of emails seen during the wait, so callers can distinguish “no email at all” from “email arrived but didn’t match”.

Source

pub async fn assert_email_matches( &self, id: &str, predicate: &EmailPredicate, ) -> Result<MatchResult>

Check a specific email against a predicate. The full crate::matcher::MatchResult is returned (including any mismatches) so callers can produce a structured diff.

Source

pub async fn list_webhooks(&self) -> Result<Vec<Webhook>>

Source

pub async fn create_webhook(&self, input: CreateWebhook) -> Result<Webhook>

Source

pub async fn delete_webhook(&self, id: &str) -> Result<()>

Source

pub async fn list_forwarding_rules(&self) -> Result<Vec<ForwardingRule>>

Source

pub async fn create_forwarding_rule( &self, input: CreateForwardingRule, ) -> Result<ForwardingRule>

Source

pub async fn delete_forwarding_rule(&self, id: &str) -> Result<()>

Source

pub async fn list_audit( &self, limit: u32, offset: u32, ) -> Result<Vec<AuditEntry>>

Source

pub async fn clear_audit(&self, older_than_days: Option<u32>) -> Result<u64>

Trait Implementations§

Source§

impl Debug for Service

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more