branch:
receive-email-agent.ts
3387 bytesRaw
import { PlaygroundAgent as Agent } from "../../shared/playground-agent";
import type { AgentEmail } from "agents/email";
import PostalMime from "postal-mime";
// ─────────────────────────────────────────────────────────────────────────────
// Types
// ─────────────────────────────────────────────────────────────────────────────
export interface ParsedEmail {
id: string;
from: string;
to: string;
subject: string;
text?: string;
html?: string;
timestamp: string;
messageId?: string;
headers: Record<string, string>;
}
export interface ReceiveEmailState {
emails: ParsedEmail[];
totalReceived: number;
lastReceivedAt?: string;
}
// ─────────────────────────────────────────────────────────────────────────────
// Agent
// ─────────────────────────────────────────────────────────────────────────────
/**
* ReceiveEmailAgent - Demonstrates basic email receiving
*
* This agent receives emails via Cloudflare Email Routing and stores them
* in its state. No auto-reply, just receives and displays.
*
* To use:
* 1. Deploy to Cloudflare
* 2. Configure Email Routing in Cloudflare dashboard
* 3. Route emails to: receive+{instanceId}@yourdomain.com
*/
export class ReceiveEmailAgent extends Agent<Env, ReceiveEmailState> {
initialState: ReceiveEmailState = {
emails: [],
totalReceived: 0
};
async onEmail(email: AgentEmail): Promise<void> {
console.log("📧 ReceiveEmailAgent: Email from", email.from, "to", email.to);
try {
// Parse the email using postal-mime
const raw = await email.getRaw();
const parsed = await PostalMime.parse(raw);
// Convert postal-mime headers to a simple key-value object
const headers = Object.fromEntries(
parsed.headers.map((h) => [h.key, h.value])
);
// Create parsed email record
const parsedEmail: ParsedEmail = {
id: crypto.randomUUID(),
from: parsed.from?.address || email.from,
to: email.to,
subject: parsed.subject || "(No Subject)",
text: parsed.text,
html: parsed.html,
timestamp: new Date().toISOString(),
messageId: parsed.messageId,
headers
};
// Add to state (keep last 50 emails)
this.setState({
emails: [...this.state.emails.slice(-49), parsedEmail],
totalReceived: this.state.totalReceived + 1,
lastReceivedAt: parsedEmail.timestamp
});
// Broadcast to connected clients
this.broadcast(
JSON.stringify({
type: "email_received",
email: parsedEmail
})
);
console.log("📧 Email stored:", parsedEmail.subject);
} catch (error) {
console.error("❌ Error processing email:", error);
throw error;
}
}
}