# Forward Received Emails

Received emails can also be forwarded to another email address.

:::callout{intent="info"}
Webhooks do not include the email body, headers, or attachments, only their
metadata. You must call the [Received emails
API](/guides/receiving-retrieve-received-email) or the [Attachments
API](/guides/receiving-list-received-email-attachments) to retrieve them.
This design choice supports large attachments in serverless environments that
have limited request body sizes.
:::

## Using the `forward` helper method

The Node.js SDK provides a `forward()` helper method that simplifies forwarding received emails. This method automatically handles fetching the email content and attachments.

Here's how you can implement this:

:::code-group
```ts Next.js theme={"theme":{"light":"github-light","dark":"vesper"}}
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

export const POST = async (request: NextRequest) => {
  const event = await request.json();

  if (event.type === 'email.received') {
    const { data, error } = await resend.emails.receiving.forward({
      emailId: event.data.email_id,
      to: 'delivered@resend.dev',
      from: 'onboarding@resend.dev',
    });

    if (error) {
      return new NextResponse(`Error: ${error.message}`, { status: 500 });
    }

    return NextResponse.json(data);
  }

  return NextResponse.json({});
};
```

```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
use axum::{
    extract::State,
    http::StatusCode,
    response::{IntoResponse, Json, Response},
};
use resend_rs::{
    types::{ForwardReceivingEmail, InboundEmailId},
    Resend,
};
use serde::Serialize;
use std::sync::Arc;

struct AppState {
    resend: Resend,
}

#[derive(Serialize)]
struct Empty {}

async fn example(
    State(state): State<Arc<AppState>>,
    Json(event): Json<resend_rs::events::EmailEvent>,
) -> Result<Response, Response> {
    if matches!(
        event.r#type,
        resend_rs::events::EmailEventType::EmailReceived
    ) {
        let opts = ForwardReceivingEmail::new(
            InboundEmailId::new(&event.data.email_id),
            "onboarding@resend.dev",
            vec!["delivered@resend.dev"],
        );
        let data = state.resend.receiving.forward(opts).await.map_err(|e| {
            (StatusCode::INTERNAL_SERVER_ERROR, format!("Error: {}", e)).into_response()
        })?;
        Ok(Json(data).into_response())
    } else {
        Ok(Json(Empty {}).into_response())
    }
}
```
:::

By default, the `forward` method forwards the email in a way that preserves the original email content and attachments exactly as received.

Alternatively, you can forward emails as if they had been forwarded through an email client, with the `forwarded message` footer. For that, use `passthrough: false` and provide custom text or HTML content. The original email will be shown after the `forwarded message` footer:

:::code-group
```ts Next.js theme={"theme":{"light":"github-light","dark":"vesper"}}
import { Resend, type EmailReceivedEvent } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

export async function forwardEmail(event: EmailReceivedEvent) {
  const { data, error } = await resend.emails.receiving.forward({
    emailId: event.data.email_id,
    to: 'delivered@resend.dev',
    from: 'onboarding@resend.dev',
    passthrough: false,
    text: 'See attached forwarded message.',
    html: '<p>See attached forwarded message.</p>',
  });
}
```

```rust Rust theme={"theme":{"light":"github-light","dark":"vesper"}}
use resend_rs::{
    events::EmailEvent,
    types::{ForwardReceivingEmail, InboundEmailId},
    Resend,
};

async fn forward(resend: &Resend, event: EmailEvent) {
    let opts = ForwardReceivingEmail::new(
        InboundEmailId::new(&event.data.email_id),
        "onboarding@resend.dev",
        vec!["delivered@resend.dev"],
    )
    .with_passthrough(false)
    .with_text("See attached forwarded message.")
    .with_html("<p>See attached forwarded message.</p>");

    let data = resend.receiving.forward(opts).await;
}
```
:::

## Manual forwarding

If you're not using Node.js or prefer not to use the `forward` helper method, you can manually forward received emails using the [Send Email API](/guides/sending-2-send-email).

The recommended approach is to download the raw email and parse it to properly extract content and attachments (especially for inline images). Then, you can send a new email with the extracted content and attachments using the [Send Email API](/guides/sending-2-send-email).

:::code-group
```js app/api/events/route.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { Resend } from 'resend';
import { simpleParser } from 'mailparser';

const resend = new Resend('re_xxxxxxxxx');

export const POST = async (request: NextRequest) => {
  const event = await request.json();

  if (event.type === 'email.received') {
    // Get the email metadata
    const { data: email } = await resend
      .emails
      .receiving
      .get(event.data.email_id);

    // Download the raw email content if available
    if (!email?.raw?.download_url) {
      return new NextResponse('Raw email not available', { status: 500 });
    }

    const rawResponse = await fetch(email.raw.download_url);
    const rawEmailContent = await rawResponse.text();

    // Parse the raw email to extract content and attachments
    const parsed = await simpleParser(rawEmailContent, {
      skipImageLinks: true,
    });

    // Extract attachments with content_id for inline images
    const attachments = parsed.attachments.map((attachment) => {
      // Strip < and > from content IDs for proper inline image handling
      const contentId = attachment.contentId
        ? attachment.contentId.replace(/^<|>$/g, '')
        : undefined;

      return {
        filename: attachment.filename,
        content: attachment.content.toString('base64'),
        contentType: attachment.contentType,
        contentId: contentId || undefined,
      };
    });

    const { data, error } = await resend.emails.send({
      from: 'Acme <onboarding@resend.dev>',
      to: ['delivered@resend.dev'],
      subject: email.subject || '(no subject)',
      html: parsed.html || undefined,
      text: parsed.text || '',
      attachments: attachments.length > 0 ? attachments : undefined,
    });

    if (error) {
      return new NextResponse(`Error: ${error.message}`, { status: 500 });
    }

    return NextResponse.json(data);
  }

  return NextResponse.json({});
};
```
:::

:::callout{intent="note"}
This example uses the [`mailparser`](https://www.npmjs.com/package/mailparser)
library (`npm install mailparser`) to parse the raw email. For other
languages/SDKs, you'll need an equivalent email parsing library capable of
processing emails compliant to [RFC
5322](https://datatracker.ietf.org/doc/html/rfc5322).
:::

## Related pages

- [Receiving Emails](./learn-dashboard-receiving-introduction.md)
- [Managing Emails](./learn-dashboard-receiving-manage-emails.md)
- [Custom Receiving Domains](./learn-dashboard-receiving-custom-domains.md)
- [Create a receiving Webhook](./learn-dashboard-receiving-create-receiving-webhook.md)
- [Process Receiving Attachments](./learn-dashboard-receiving-attachments.md)
- [Get Email Content](./learn-dashboard-receiving-get-email-content.md)
- [Reply to Receiving Emails](./learn-dashboard-receiving-reply-to-emails.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
