Skip to main content

InboundEmail

Struct InboundEmail 

Source
pub struct InboundEmail { /* private fields */ }
Expand description

An email that Cloudflare Email Routing delivered to the Worker, handed to the app’s mailbox.

receive builds it. The envelope (from, to) comes from Cloudflare; headers and bodies are parsed from the raw message (multipart, quoted-printable, base64, RFC 2047 encoded words; files in attachments, the bytes in raw). Bounce it with reject or pass it on with forward. Receiving is free and unlimited on every plan.

§Examples

use ocre::mail::InboundEmail;
use ocre::{Ctx, Result};

// src/mailbox.rs
pub async fn receive(_ctx: Ctx, email: InboundEmail) -> Result<()> {
    match email.to() {
        "support@example.com" => email.forward("team@example.com").await?,
        _ => email.reject("Unknown address"),
    }
    Ok(())
}

Implementations§

Source§

impl InboundEmail

Source

pub fn from(&self) -> &str

Returns the envelope sender (SMTP MAIL FROM), checked by Cloudflare.

The From header may differ: read it with email.header("From").

§Examples
if email.from().ends_with("@example.com") {
    // a colleague
}
Source

pub fn to(&self) -> &str

Returns the envelope recipient: the address of this app that received the email.

Match on it to route several addresses to one Worker.

§Examples
let team = email.to().starts_with("support@");
Source

pub fn subject(&self) -> &str

Returns the decoded Subject header, or "" when it is missing.

§Examples
let urgent = email.subject().contains("URGENT");
Source

pub fn header(&self, name: &str) -> Option<&str>

Returns the first header with this name (case-insensitive), decoded.

Folded lines are joined and RFC 2047 encoded words decoded. None when the message has no such header.

§Examples
let id = email.header("message-id").unwrap_or("");
Source

pub fn headers(&self) -> &[(String, String)]

Returns every header, in message order, as decoded (name, value) pairs.

Repeated headers (Received, …) appear once per occurrence.

§Examples
let hops = email.headers().iter().filter(|(name, _)| name.eq_ignore_ascii_case("Received")).count();
Source

pub fn text(&self) -> Option<&str>

Returns the first text/plain part, decoded to UTF-8, or None when there is none.

§Examples
let body = email.text().unwrap_or_default();
Source

pub fn attachments(&self) -> &[Attachment]

Returns the files of the email, decoded: every part that is not the first text or HTML body.

Inline images carry their content_id. Store them in R2 (ocre::storage) rather than D1; they are the sender’s files, so check the type and size before keeping them.

§Examples
for file in email.attachments() {
    worker::console_log!("{} ({}, {} bytes)", file.filename, file.content_type, file.content.len());
}
Source

pub fn html(&self) -> Option<&str>

Returns the first text/html part, decoded to UTF-8, or None when there is none.

It is the sender’s HTML: never render it unescaped.

§Examples
let has_html = email.html().is_some();
Source

pub fn raw(&self) -> &[u8] ⓘ

Returns the whole message as received (RFC 5322 bytes), e.g. to store it in R2 or read attachments.

§Examples
let size = email.raw().len();
Source

pub fn reject(&self, reason: &str)

Bounces the email: the sending server gets a permanent SMTP error with reason.

The mailbox handler still returns normally; receive also bounces the email when the handler returns an Err.

§Examples
if email.to() != "support@example.com" {
    email.reject("Unknown address");
}
Source

pub async fn forward(&self, to: &str) -> Result<()>

Forwards the email unchanged to to, which must be a verified destination address of the Cloudflare account.

§Errors

Error::Internal when Cloudflare refuses, typically because to is not a verified destination address in Email Routing (the message says so).

§Examples
email.forward("team@example.com").await?;

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
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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.

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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<S, T> Upcast<T> for S
where T: UpcastFrom<S> + ?Sized, S: ?Sized,

Source§

fn upcast(&self) -> &T
where Self: ErasableGeneric, T: Sized + ErasableGeneric<Repr = Self::Repr>,

Perform a zero-cost type-safe upcast to a wider ref type within the Wasm bindgen generics type system. Read more
Source§

fn upcast_into(self) -> T
where Self: Sized + ErasableGeneric, T: Sized + ErasableGeneric<Repr = Self::Repr>,

Perform a zero-cost type-safe upcast to a wider type within the Wasm bindgen generics type system. Read more
§

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

§

fn vzip(self) -> V