# Forward received emails

> Forward an inbound email to another address — either with the built-in forward endpoint, or by downloading the raw message, parsing it, and re-sending via POST /emails.

Received emails can be **forwarded** on to another address. There are two approaches: the built-in **forward endpoint**, which re-sends the stored parsed message body **with the original attachments** (inline images preserved) in one call, or a **manual re-send**, where you download and parse the raw message yourself for full RFC 5322 fidelity.

> **Warning:** Webhooks include metadata only — not the body, headers, or attachment content. Retrieve the message with the [Receiving API](https://www.sendping.co/docs/receiving/get-email-content) (and the [Attachments API](https://www.sendping.co/docs/receiving/attachments) for files) before forwarding.

## Forward endpoint

The quickest way to forward is [`POST /emails/receiving/:id/forward`](https://www.sendping.co/docs/api/emails-received-forward). It re-sends the received email's stored parsed `subject`, `html`, and `text` — along with the original attachments — as a new outbound email. Pass `from` (required) and the recipient(s); the original subject, body, and files are reused.

**Body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `from` | string | No | Required. The sender address for the forwarded message. Must be an address on a [verified sending domain](https://www.sendping.co/docs/domains/managing). |
| `to` | string | string[] | No | The recipient address(es) to forward to. |
| `subject` | string | No | Optional. Overrides the original subject on the forwarded message. |

**Node.js**

```js
import { SendPing } from 'sendping';

const mb = new SendPing('mb_xxxxxxxxx');

const { data, error } = await mb.emails.receiving.forward('56761188-7520-42d8-8898-ff6fc54ce618', {
  "from": "Acme <hello@yourdomain.com>",
  "to": ["delivered@test.sendping.co"]
});
console.log({ data, error });
```

**Ruby**

```ruby
require "sendping"

SendPing.api_key = "mb_xxxxxxxxx"

SendPing::Emails::Receiving.forward("56761188-7520-42d8-8898-ff6fc54ce618", {
  "from": "Acme <hello@yourdomain.com>",
  "to": [
    "delivered@test.sendping.co"
  ]
})
```

**PHP**

```php
<?php
require 'vendor/autoload.php';

use SendPing\SendPing;

$sendping = SendPing::client('mb_xxxxxxxxx');

$sendping->emails->receiving->forward('56761188-7520-42d8-8898-ff6fc54ce618', [
  'from' => "Acme <hello@yourdomain.com>",
  'to' => [
    "delivered@test.sendping.co"
  ]
]);
```

**Python**

```python
import sendping

sendping.api_key = "mb_xxxxxxxxx"

sendping.Emails.Receiving.forward("56761188-7520-42d8-8898-ff6fc54ce618", {
  "from": "Acme <hello@yourdomain.com>",
  "to": [
    "delivered@test.sendping.co"
  ]
})
```

**Go**

```go
import "github.com/shekhu10/sendping-sdks/sendping-go"

client := sendping.NewClient("mb_xxxxxxxxx")

forwarded, err := client.Emails.Receiving.Forward("56761188-7520-42d8-8898-ff6fc54ce618", &sendping.ForwardReceivedEmailRequest{
    From: "Acme <hello@yourdomain.com>",
    To:   []string{"delivered@test.sendping.co"},
})
```

**Rust**

```rust
use sendping::{ForwardReceivedEmailOptions, SendPing};

let mb = SendPing::new("mb_xxxxxxxxx");

let params = ForwardReceivedEmailOptions::new(
    "Acme <hello@yourdomain.com>",
    ["delivered@test.sendping.co"],
);
let _forwarded = mb.emails.receiving.forward("56761188-7520-42d8-8898-ff6fc54ce618", params).await?;
```

**Java**

```java
import co.sendping.SendPing;
import co.sendping.SendPingResponse;
import co.sendping.requests.ForwardEmailRequest;

SendPing sendping = new SendPing("mb_xxxxxxxxx");

ForwardEmailRequest request = ForwardEmailRequest.builder()
        .from("Acme <hello@yourdomain.com>")
        .to("delivered@test.sendping.co")
        .build();

SendPingResponse response = sendping.emails().receiving().forward(
        "56761188-7520-42d8-8898-ff6fc54ce618",
        request);
```

**.NET**

```csharp
using SendPing;

ISendPing sendping = SendPingClient.Create("mb_xxxxxxxxx");

var resp = await sendping.ReceivedEmailForwardAsync("56761188-7520-42d8-8898-ff6fc54ce618", new ReceivedEmailForwardOptions
{
    From = "Acme <hello@yourdomain.com>",
    To = "delivered@test.sendping.co",
});
```

**cURL**

```bash
curl -X POST 'https://www.sendping.co/api/emails/receiving/56761188-7520-42d8-8898-ff6fc54ce618/forward' \
  -H 'Authorization: Bearer mb_xxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
  "from": "Acme <hello@yourdomain.com>",
  "to": ["delivered@test.sendping.co"]
}'
```

**CLI**

```bash
sendping emails receiving forward 56761188-7520-42d8-8898-ff6fc54ce618 \
  --from 'Acme <hello@yourdomain.com>' \
  --to 'delivered@test.sendping.co'
```

> **Note:** The forward endpoint re-sends the parsed subject and body **and** re-attaches the original attachments — inline images are preserved via their `content_id`, so embedded images still render. Attachments are best-effort: any whose stored bytes can't be loaded are skipped, and the same per-attachment / total size caps as a normal send apply. For full RFC 5322 fidelity (exact original MIME, custom headers), use the manual re-send below instead.

## Forward by re-sending

The most faithful way to forward is to download the **raw** RFC 5322 message and parse it, so you correctly extract the HTML/text bodies and every attachment — especially inline images referenced by `Content-ID`. Then re-send the extracted content with [POST /emails](https://www.sendping.co/docs/api/emails-send).

The retrieved received email exposes a `raw.download_url` you can fetch to get the original bytes — it is an authenticated endpoint, so send your `Authorization: Bearer` header with that request too. Strip the angle brackets from each inline part's `content_id` so the forwarded HTML still resolves its embedded images.

**Node.js**

```js
// app/api/events/route.ts
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { simpleParser } from 'mailparser';

const API_KEY = 'mb_xxxxxxxxx';

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

  if (event.type === 'email.received') {
    // 1. Get the received email (includes raw.download_url)
    const metaRes = await fetch(
      `https://www.sendping.co/api/emails/receiving/${event.data.email_id}`,
      { headers: { Authorization: `Bearer ${API_KEY}` } },
    );
    const email = await metaRes.json();

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

    // 2. Download and parse the raw RFC 5322 message
    const rawResponse = await fetch(email.raw.download_url, {
      headers: { Authorization: `Bearer ${API_KEY}` },
    });
    const rawEmailContent = await rawResponse.text();
    const parsed = await simpleParser(rawEmailContent, { skipImageLinks: true });

    // 3. Re-build attachments, keeping inline content_ids
    const attachments = parsed.attachments.map((attachment) => {
      const contentId = attachment.contentId
        ? attachment.contentId.replace(/^<|>$/g, '')
        : undefined;
      return {
        filename: attachment.filename,
        content: attachment.content.toString('base64'),
        content_type: attachment.contentType,
        content_id: contentId || undefined,
      };
    });

    // 4. Forward by sending a new email
    const sendRes = await fetch('https://www.sendping.co/api/emails', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        from: 'Acme <hello@yourdomain.com>',
        to: ['delivered@test.sendping.co'],
        subject: email.subject || '(no subject)',
        html: parsed.html || undefined,
        text: parsed.text || undefined,
        attachments: attachments.length > 0 ? attachments : undefined,
      }),
    });

    return NextResponse.json(await sendRes.json());
  }

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

**Python**

```python
import base64, email as email_lib, requests
from email import policy
from flask import Flask, request, jsonify

app = Flask(__name__)
API_KEY = "mb_xxxxxxxxx"

@app.post("/api/events")
def events():
    event = request.get_json()
    if event.get("type") != "email.received":
        return jsonify({})

    # 1. Get the received email (includes raw.download_url)
    meta = requests.get(
        f"https://www.sendping.co/api/emails/receiving/{event['data']['email_id']}",
        headers={"Authorization": f"Bearer {API_KEY}"},
    ).json()

    raw = (meta.get("raw") or {}).get("download_url")
    if not raw:
        return "Raw email not available", 500

    # 2. Download and parse the raw RFC 5322 message
    raw_bytes = requests.get(raw, headers={"Authorization": f"Bearer {API_KEY}"}).content
    parsed = email_lib.message_from_bytes(raw_bytes, policy=policy.default)

    html = parsed.get_body(("html",))
    text = parsed.get_body(("plain",))

    attachments = []
    for part in parsed.iter_attachments():
        cid = part.get("Content-ID")
        attachments.append({
            "filename": part.get_filename(),
            "content": base64.b64encode(part.get_content()).decode(),
            "content_type": part.get_content_type(),
            "content_id": cid.strip("<>") if cid else None,
        })

    # 3. Forward by sending a new email
    sent = requests.post(
        "https://www.sendping.co/api/emails",
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={
            "from": "Acme <hello@yourdomain.com>",
            "to": ["delivered@test.sendping.co"],
            "subject": meta.get("subject") or "(no subject)",
            "html": html.get_content() if html else None,
            "text": text.get_content() if text else None,
            "attachments": attachments or None,
        },
    )
    return jsonify(sent.json())
```

> **Note:** The Node.js example uses [`mailparser`](https://www.npmjs.com/package/mailparser) (`npm install mailparser`). In any language, use an [RFC 5322](https://datatracker.ietf.org/doc/html/rfc5322)-capable parser — the example above uses Python's built-in `email` package.

## Forward style: passthrough vs. wrapped

Re-sending the parsed `html`/`text` and attachments reproduces the original message as it arrived — a clean **passthrough** forward. If you instead want a "forwarded message" footer like an email client, send your own intro `html`/`text` and append the original content (and a quoted header block) beneath it:

```js
const footer = `
  <p>See attached forwarded message.</p>
  <hr>
  <p>---------- Forwarded message ----------<br>
     From: ${email.from}<br>
     Subject: ${email.subject}</p>
`;

await fetch('https://www.sendping.co/api/emails', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    from: 'Acme <hello@yourdomain.com>',
    to: ['delivered@test.sendping.co'],
    subject: `Fwd: ${email.subject || '(no subject)'}`,
    html: footer + (parsed.html || ''),
    attachments: attachments.length > 0 ? attachments : undefined,
  }),
});
```

> **Warning:** The forwarding `from` must be an address on a [verified sending domain](https://www.sendping.co/docs/domains/managing) — it is a brand-new outbound send via `POST /emails`, not a relay of the original envelope.
