# Email Reply Classifier for Bounce, Out of Office, Auto Reply (`infinit_bubulus/email-reply-classifier`) Actor

Classify incoming emails as bounce, out of office, auto reply, receipt confirmation, newsletter, transactional or human reply. Reads delivery status reports, hard and soft bounces, provider blocks and return dates. Rule based, no AI cost, works offline.

- **URL**: https://apify.com/infinit\_bubulus/email-reply-classifier.md
- **Developed by:** [Infinityware](https://apify.com/infinit_bubulus) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 email classifieds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Email Reply Classifier for Bounce, Out of Office, Auto Reply

Send your incoming emails to this Actor and get back one row per email that says what it is. Bounce, out of office, auto reply, receipt confirmation, newsletter, transactional mail, service notification or a real human reply. Each row explains why and gives you the details you need next.

- **Bounces** come with the failed address, whether the failure is permanent (5.x.x) or temporary (4.x.x), a reason class and whether the receiving server only rejected your **sending server**. In that case the address is usually fine and should not be suppressed.
- **Out of office replies** come with the return date when the text names one.
- **Human replies** are flagged when they contain an unsubscribe request.

It works with rules only. No AI service, no external calls, no cost per token. Fast, cheap, explainable and privacy friendly.

### Who it is for

- Sales and CRM automations in n8n, Make or Zapier that must not stop a sequence because of an auto reply
- People who run their own sending tools and need clean bounce handling
- Helpdesks and AI agents that work through a mailbox, for example over the Apify MCP server

### Categories

| Category | Meaning |
|---|---|
| `bounce` | Delivery failure or delay report from a mail server |
| `out-of-office` | Absence notice, with return date if found |
| `auto-reply` | Other automatic answer without a ticket or absence |
| `receipt-confirmation` | Automatic confirmation from a ticket or support system |
| `newsletter` | Mailing list or bulk mail (List-Id, List-Unsubscribe, Precedence bulk) |
| `transactional` | Invoice, order, shipping, payment or login code |
| `service` | Notification from a known platform or a no-reply sender |
| `own` | Sent from one of your own addresses (copies, loops) |
| `human` | Everything else. A real person wrote it |

The order matters. The first matching category wins. When in doubt the Actor says `human`, because treating a real reply as automatic costs more than one extra click.

### How bounces are read

The Actor reads machine readable delivery status reports (`multipart/report`) and the plain text formats of Postfix, Exim, Exchange and Gmail.

| `bounce.reason` | When |
|---|---|
| `mailbox-unknown` | 5.1.1, 5.1.10, user unknown, no such user, recipient not found |
| `domain-unknown` | 5.1.2, unrouteable address, host not found |
| `mailbox-full` | 4.2.2 or 5.2.2, quota exceeded, mailbox full |
| `provider-block` | The receiver rejected your sending server (reputation, block lists, policy) |
| `spam-rejected` | 5.7.1 with spam or content in the reason |
| `temporary` | Other 4.x.x codes, greylisting, delays |
| `other` | Anything else |

`permanent` is only true for 5.x.x status codes or `Action: failed`. Greylisting and other 4.x.x answers are temporary, so you do not lose valid contacts because a server hesitated once.

`addressInvalid` is true only for permanent `mailbox-unknown` or `domain-unknown`. Example of a provider block that keeps `addressInvalid` false.

```
SMTP error from remote mail server after initial connection:
554 IP=203.0.113.9 - None/bad reputation (...) (NOWL)
```

### Input

Each email is either the raw source or a set of fields. An optional `id` is copied to the output.

```json
{
  "emails": [
    { "id": "1", "raw": "From: Mail Delivery System <MAILER-DAEMON@mx.example.net>\nSubject: Mail delivery failed\n\n..." },
    { "id": "2", "from": "Petra Muster <petra@example.de>", "subject": "Abwesenheitsnotiz", "text": "Ich bin bis zum 12.10. nicht im Büro." },
    { "id": "3", "rawBase64": "RnJvbTogLi4u" }
  ],
  "ownAddresses": ["sales@yourcompany.example"]
}
```

Fields are `from`, `to`, `subject`, `date`, `headers` (object), `text` and `html`. For large batches put a JSON array or NDJSON file somewhere reachable over HTTPS and pass it as `emailsUrl`.

Other options are `detectReturnDate`, `detectUnsubscribe`, `extraAutoReplyPhrases` (sentences from auto reply templates you know) and `includeBodyPreview`.

### Output example

```json
{
  "id": "1",
  "category": "bounce",
  "isHuman": false,
  "confidence": "high",
  "reasons": ["sender mailer-daemon@mx.example.net", "status 5.1.1"],
  "bounce": {
    "failedRecipient": "info@nobody.example",
    "permanent": true,
    "status": "5.1.1",
    "reason": "mailbox-unknown",
    "providerBlock": false,
    "addressInvalid": true,
    "diagnostic": "550 5.1.1 User unknown",
    "remoteMta": "mx.nobody.example"
  },
  "outOfOffice": null,
  "unsubscribeRequest": false,
  "looksLikeInquiry": false,
  "language": "en",
  "from": "mailer-daemon@mx.example.net",
  "fromFreemail": false,
  "subject": "Mail delivery failed",
  "inReplyTo": [],
  "bodyPreview": null,
  "failedRecipient": "info@nobody.example",
  "bouncePermanent": true,
  "bounceReason": "mailbox-unknown",
  "returnDate": null
}
```

An absence looks like `"outOfOffice": {"returnDate": "2026-10-12", "returnDateText": "bis zum 12.10."}`. `confidence` is `high` when a header or a delivery report decided, otherwise `medium`. A mail without any match is `human` with `medium` confidence and an empty `reasons` list. The last four fields are flat copies for spreadsheets.

Emails that cannot be read are not written to the dataset and are not charged. They are listed with their index and error in the key-value record `ERRORS`. The record `OUTPUT` holds a summary of the run.

### Use it from n8n, Make or Zapier

Call the synchronous endpoint and get the rows back in the same request.

```bash
curl -X POST "https://api.apify.com/v2/acts/infinit_bubulus~email-reply-classifier/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"emails":[{"id":"42","from":"anna@example.de","subject":"Out of Office","text":"I am away until October 14."}]}'
```

In n8n use an HTTP Request node with this URL. In Make and Zapier use the Apify app and the action that runs an Actor and returns the dataset items.

### Pricing

You pay per classified email. 1,000 emails cost about 1 USD, with lower prices on higher Apify plans. Unreadable emails cost nothing. The run stops cleanly when your spending limit is reached.

### Privacy

This Actor reads the emails you send to it and nothing else. It makes no network requests except loading your own file from `emailsUrl`, uses no AI service and stores nothing outside the default dataset and key-value store of your run. You are the controller of the personal data in your emails. Bounce results help you stop sending to dead addresses. Unsubscribe requests are flagged so you can honour them, which the GDPR and, in Germany, § 7 UWG expect.

No field contains mail text unless you switch on `includeBodyPreview`.

### Limits

- Rule based. Unusual templates end up as `human` with `medium` confidence.
- Patterns for German, English, French, Spanish, Italian, Dutch and Polish. Return dates in other languages than German and English are only read in numeric form, for example 15/10/2026.
- Quoted parts of a reply are cut off before the check, so a quoted automatic sentence of your own mail does not turn a real answer into an auto reply.
- Domains in the subject are ignored. "Re: Ein Punkt auf urlaub-am-see.de" is not a vacation notice.

### FAQ

**Does it connect to my mailbox?** No. You pass the emails in. That keeps your credentials away from the Actor.

**Can I teach it my own auto reply templates?** Yes, add sentences from them to `extraAutoReplyPhrases`.

**Why is a bounce with 554 and "bad reputation" not marked as invalid?** Because the receiver rejected your sending server, not the address. Fix your sender reputation or relay and send again later.

# Actor input Schema

## `emails` (type: `array`):

List of emails. Each item is either {"raw": "full RFC 822 source"}, {"rawBase64": "..."} or fields {"from", "to", "subject", "date", "headers", "text", "html"}. An optional "id" is copied to the output.

## `emailsUrl` (type: `string`):

HTTPS URL of a JSON array or NDJSON file with the same item format. Use this for large batches.

## `ownAddresses` (type: `array`):

Emails from these addresses are classified as own (copies, loops).

## `detectReturnDate` (type: `boolean`):

Reads dates like "bis zum 12.10.", "until October 14" or "back on 2026-10-12".

## `detectUnsubscribe` (type: `boolean`):

Only in the sender's own text, never in the quoted part.

## `extraAutoReplyPhrases` (type: `array`):

Sentences from auto reply templates you know. A mail whose own text contains one of them is classified as auto reply.

## `includeBodyPreview` (type: `boolean`):

Adds the first 300 characters of the sender's own text, without the quoted part. Off by default to keep personal data out of the dataset.

## Actor input object example

```json
{
  "emails": [
    {
      "id": "ooo-de",
      "from": "Petra Muster <petra@example.de>",
      "subject": "Abwesenheitsnotiz: Re: Ihre Anfrage",
      "text": "Vielen Dank für Ihre Nachricht. Ich bin bis zum 12.10. nicht im Büro. In dringenden Fällen wenden Sie sich bitte an info@example.de."
    },
    {
      "id": "bounce",
      "raw": "From: Mail Delivery System <MAILER-DAEMON@mx.example.net>\nSubject: Mail delivery failed: returning message to sender\nContent-Type: text/plain\n\nThis message was created automatically by mail delivery software.\n\nA message that you sent could not be delivered to one or more of its\nrecipients. This is a permanent error. The following address(es) failed:\n\n  info@nobody.example\n    host mx.nobody.example [203.0.113.5]\n    SMTP error from remote mail server after RCPT TO:<info@nobody.example>:\n    550 5.1.1 User unknown\n"
    },
    {
      "id": "human",
      "from": "Hans Huber <hans@example.de>",
      "subject": "Re: Ein Punkt auf example.de",
      "text": "Guten Tag, danke für den Hinweis. Schicken Sie mir gern ein Angebot.\n\nAm 01.10.2026 um 10:12 schrieb Antonio:\n> Dies ist eine automatische Zusammenfassung ..."
    }
  ],
  "detectReturnDate": true,
  "detectUnsubscribe": true,
  "includeBodyPreview": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "emails": [
        {
            "id": "ooo-de",
            "from": "Petra Muster <petra@example.de>",
            "subject": "Abwesenheitsnotiz: Re: Ihre Anfrage",
            "text": "Vielen Dank für Ihre Nachricht. Ich bin bis zum 12.10. nicht im Büro. In dringenden Fällen wenden Sie sich bitte an info@example.de."
        },
        {
            "id": "bounce",
            "raw": "From: Mail Delivery System <MAILER-DAEMON@mx.example.net>\nSubject: Mail delivery failed: returning message to sender\nContent-Type: text/plain\n\nThis message was created automatically by mail delivery software.\n\nA message that you sent could not be delivered to one or more of its\nrecipients. This is a permanent error. The following address(es) failed:\n\n  info@nobody.example\n    host mx.nobody.example [203.0.113.5]\n    SMTP error from remote mail server after RCPT TO:<info@nobody.example>:\n    550 5.1.1 User unknown\n"
        },
        {
            "id": "human",
            "from": "Hans Huber <hans@example.de>",
            "subject": "Re: Ein Punkt auf example.de",
            "text": "Guten Tag, danke für den Hinweis. Schicken Sie mir gern ein Angebot.\n\nAm 01.10.2026 um 10:12 schrieb Antonio:\n> Dies ist eine automatische Zusammenfassung ..."
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("infinit_bubulus/email-reply-classifier").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "emails": [
        {
            "id": "ooo-de",
            "from": "Petra Muster <petra@example.de>",
            "subject": "Abwesenheitsnotiz: Re: Ihre Anfrage",
            "text": "Vielen Dank für Ihre Nachricht. Ich bin bis zum 12.10. nicht im Büro. In dringenden Fällen wenden Sie sich bitte an info@example.de.",
        },
        {
            "id": "bounce",
            "raw": """From: Mail Delivery System <MAILER-DAEMON@mx.example.net>
Subject: Mail delivery failed: returning message to sender
Content-Type: text/plain

This message was created automatically by mail delivery software.

A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:

  info@nobody.example
    host mx.nobody.example [203.0.113.5]
    SMTP error from remote mail server after RCPT TO:<info@nobody.example>:
    550 5.1.1 User unknown
""",
        },
        {
            "id": "human",
            "from": "Hans Huber <hans@example.de>",
            "subject": "Re: Ein Punkt auf example.de",
            "text": """Guten Tag, danke für den Hinweis. Schicken Sie mir gern ein Angebot.

Am 01.10.2026 um 10:12 schrieb Antonio:
> Dies ist eine automatische Zusammenfassung ...""",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("infinit_bubulus/email-reply-classifier").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "emails": [
    {
      "id": "ooo-de",
      "from": "Petra Muster <petra@example.de>",
      "subject": "Abwesenheitsnotiz: Re: Ihre Anfrage",
      "text": "Vielen Dank für Ihre Nachricht. Ich bin bis zum 12.10. nicht im Büro. In dringenden Fällen wenden Sie sich bitte an info@example.de."
    },
    {
      "id": "bounce",
      "raw": "From: Mail Delivery System <MAILER-DAEMON@mx.example.net>\\nSubject: Mail delivery failed: returning message to sender\\nContent-Type: text/plain\\n\\nThis message was created automatically by mail delivery software.\\n\\nA message that you sent could not be delivered to one or more of its\\nrecipients. This is a permanent error. The following address(es) failed:\\n\\n  info@nobody.example\\n    host mx.nobody.example [203.0.113.5]\\n    SMTP error from remote mail server after RCPT TO:<info@nobody.example>:\\n    550 5.1.1 User unknown\\n"
    },
    {
      "id": "human",
      "from": "Hans Huber <hans@example.de>",
      "subject": "Re: Ein Punkt auf example.de",
      "text": "Guten Tag, danke für den Hinweis. Schicken Sie mir gern ein Angebot.\\n\\nAm 01.10.2026 um 10:12 schrieb Antonio:\\n> Dies ist eine automatische Zusammenfassung ..."
    }
  ]
}' |
apify call infinit_bubulus/email-reply-classifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,infinit_bubulus/email-reply-classifier"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/wqulcGEiEfCd9hkxY/builds/mFHfXjZOb0bZ5goVr/openapi.json
