---
id: messaging--smtp-mail-collector
title: "Mail collector"
summary: "Downloads e-mail from a mailbox over IMAP or POP3 and emits every message as a `SmtpMessage`. Trigger it periodically (for example from a timer) to process incoming mail, optionally deleting it from the server after processing."
audience: user
keywords: "start, output, continue, protocol, host, port, authtype, username, password, folder, enablessl, deleteafter"
---
# Mail collector

Downloads e-mail from a mailbox over IMAP or POP3 and emits every message as a `SmtpMessage`. Trigger it periodically (for example from a timer) to process incoming mail, optionally deleting it from the server after processing.

## Pins

| Pin | Kind | Types | Description |
|---|---|---|---|
| Start | start | any | Starts one collection run. When unconnected, the system calls it once when the flow starts. |
| Output | output | `Viaducta.Plugins.Smtp.Types.SmtpMessage` | Called once per downloaded message. |
| Continue | continue | `Viaducta.TypeSystem.Metadata.NoInputData` | Called once after the collection run finished, also when no message was collected. |

## Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `Protocol` | dropdown: `1` IMAP, `2` POP3 | `1` | Mailbox protocol. |
| `Host` | string | | Required. Host name or IP of the IMAP / POP3 server. |
| `Port` | integer | `993` | Server port. Typical: IMAP `993` (SSL) / `143`, POP3 `995` (SSL) / `110`. Change it when you switch to POP3. |
| `AuthType` | dropdown | `0` | How to sign in, see Authentication. |
| `UserName` | string (max 256) | | Mailbox user (mailbox address with OAuth2). With `AuthType` `0` and empty, no authentication is done. |
| `Password` | password (max 256) | | Mailbox password or app password, `AuthType` `0` only. Use an expression setting (`=Secrets.MailboxPassword`). |
| `Folder` | string (max 256) | `Inbox` | IMAP folder to read. Only visible and used when `Protocol` is `1`. |
| `EnableSSL` | boolean | `true` | `true`: TLS from the start of the connection (ports 993 / 995). `false`: plain connection, upgraded with STARTTLS when the server offers it (ports 143 / 110). |
| `DeleteAfter` | boolean | `false` | Delete each message from the server after it was emitted on `Output`. |

## Authentication

`AuthType` selects how the component signs in. Every option runs unattended: tokens are fetched, cached in memory and renewed by the engine, so nobody has to sign in while flows run. Store secrets as expression settings (`=Secrets.X`).

| `AuthType` | Fields | Use for |
|---|---|---|
| `0` Username and password (default) | `UserName`, `Password` | Classic servers; Gmail / Google accounts with an **app password**. No sign-in when `UserName` is empty. |
| `1` OAuth2 client credentials | `TokenEndpoint`, `ClientId`, `ClientSecret`, `Scope` | Microsoft 365 / Exchange Online, app-only: endpoint `https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token`, scope `https://outlook.office365.com/.default`. The Entra app needs the IMAP / POP / SMTP `.AccessAsApp` permission and an Exchange service principal with mailbox access. |
| `2` OAuth2 refresh token | `TokenEndpoint` (empty = Google), `ClientId`, `ClientSecret`, `RefreshToken`, optional `Scope` | Personal Gmail accounts. Get the refresh token once (for example with the Google OAuth Playground, scope `https://mail.google.com/`), using an OAuth client whose consent screen is *published*: in *Testing* status Google expires refresh tokens after 7 days. |
| `3` Google service account | `ServiceAccountKey` (JSON key), optional `Scope` | Google Workspace. Needs domain-wide delegation of `https://mail.google.com/`; the service account acts as the mailbox in `UserName`. |
| `4` OAuth2 access token | `AccessToken` | A token produced elsewhere, e.g. by an expression. Not renewed by the component. |

- With OAuth2 (`1`-`4`) `UserName` is the mailbox address and is required; the sign-in uses SASL XOAUTH2.
- If the server rejects a cached token, the component fetches a new one and retries once.
- Refresh tokens rotated by the server are kept in memory for the life of the engine process; the configured `RefreshToken` is used again after a restart.

## Behaviour

- Every call on `Start` connects, authenticates (if `UserName` is set), reads **all** messages in the folder (IMAP) or mailbox (POP3), and disconnects. Messages are processed from newest to oldest, one at a time; each `Output` call is awaited before the next message is downloaded.
- Each message is converted to `SmtpMessage`:
  - `MailFrom`: address of the first `From` mailbox; `To`, `CC`, `Bcc`: `"Name" <address>` entries joined with `; `; `ReplyTo`: Reply-To addresses joined with `;`.
  - `Subject`, `MessageId`, `InReplyTo`, `References`, `ReceiveDateTime` (the message `Date` header).
  - `Body`: the HTML body when present (`IsBodyHtml` = `true`), otherwise the plain-text body.
  - `Priority`: `2` urgent, `1` non-urgent, `0` normal.
  - `Attachments`: every attachment part with `FileName`, `ContentType` and decoded `Content` bytes.
  - `Headers`: all headers except From, To, Subject, Date, Message-ID, MIME-Version and Delivered-To.
- `DeleteAfter` = `true`: IMAP messages are flagged deleted after their `Output` call and expunged at the end of the run; POP3 deletions are committed when the session ends normally.
- After the last message (and the IMAP expunge) the component disconnects and calls `Continue` once with a `NoInputData` record.
- Connection, authentication or folder errors throw an exception for the `Start` call; `Continue` is then not called.

## Notes

- There is no "unread only" or "new since last run" filter: with `DeleteAfter` = `false` every run emits the whole mailbox again. Either enable `DeleteAfter`, or de-duplicate on `MessageId` downstream.
- If processing of a message throws, the run stops; already processed IMAP messages are flagged but not expunged, and POP3 deletions of that run are not committed.
- The IMAP folder is opened read-write, so the server may mark fetched messages as read.
- `ReceiveDateTime` is the date and time from the `Date` header in the sender's time zone (the offset is dropped).
- Very large mailboxes are read in one run; for an archive, use a dedicated folder and `DeleteAfter`.

## Example

```json
{ "Protocol": 1, "Host": "imap.example.com", "Port": 993, "EnableSSL": true, "UserName": "orders@example.com", "Password": "=Secrets.MailboxPassword", "Folder": "Inbox", "DeleteAfter": true }
```

Timer → **Mail collector** → (map `SmtpMessage` fields, store attachments) → ...
