When to Use
- Invoice processing: Watch an
invoices@company.com mailbox and start a data extraction workflow for each new supplier invoice email, pulling the PDF attachment for OCR or structured parsing.
- Order confirmation ingestion: Ingest order confirmation emails from a marketplace or supplier into your ERP by parsing the subject and body fields in a downstream Data Mapping node.
- Support ticket creation: Convert inbound customer support emails into help desk tickets automatically, mapping the sender address, subject, and body to ticket fields.
- Email-based approval workflows: Poll a dedicated approval mailbox for reply emails, extract the approval decision from the body text, and resume a suspended workflow accordingly.
- Automated reply systems: Detect inbound emails matching a subject pattern, generate a contextual reply using an AI Agent node, and route the response through an SMTP node.
One workflow run per email. The trigger fires separately for each matching email found in a poll cycle — it does not batch all emails into a single run. The batchSize setting controls how many emails are fetched per poll, not how many runs fire per email.
App passwords for Gmail and Outlook. Gmail and Microsoft 365 require an App Password or OAuth token rather than the account password when IMAP access is enabled. Store the credential in BizFirst Credentials Manager and reference it via the password key. Never use the account's primary login password directly.
Configuration
Connection
| Field | Required | Description |
host |
Required |
IMAP server hostname. Common values: imap.gmail.com, outlook.office365.com, imap.mail.yahoo.com, or your organisation's mail server. |
port |
Optional |
IMAP port. Default 993 (IMAPS with TLS). Use 143 for STARTTLS or unencrypted connections. Always use 993 in production. |
user |
Required |
IMAP login username, typically the full email address (e.g. invoices@company.com). |
password |
Required |
IMAP password or app password. Store in BizFirst Credentials Manager and reference as {{ $credentials.imap-password }}. Never store the raw value in node configuration. |
tls |
Optional |
Default true. Wraps the TCP connection with TLS/SSL. Should remain true in all production environments. |
allowUnauthorizedCerts |
Optional |
Default false. Disables TLS certificate verification. Development and test environments only. Always triggers an audit log entry when enabled outside development mode. |
Mailbox & Polling
| Field | Required | Description |
mailbox |
Optional |
Mailbox folder to poll. Default INBOX. Use standard IMAP folder names: INBOX, Sent, Drafts, or provider-specific names such as [Gmail]/All Mail. |
customEmailConfig |
Optional |
IMAP search criteria as a JSON array. Default ["UNSEEN"]. Examples: ["UNSEEN"], ["FROM", "boss@company.com"], ["SUBJECT", "Invoice", "UNSEEN"]. UID deduplication is appended automatically — you do not need to add it. |
batchSize |
Optional |
Maximum number of emails fetched per poll cycle. Default 20. Valid range 1–100. Reduce this value if individual emails are large or attachments are enabled. |
postProcessAction |
Optional |
Action taken on each email after successful processing. Default read (marks as read). Options: read, delete, nothing. Use nothing only when you have an alternative deduplication strategy. |
downloadEmailOnEveryTrigger |
Optional |
Default false. When true, disables UID tracking and re-fetches all matching emails on every poll cycle. This causes duplicate workflow executions and should only be used during testing. |
Output Format & Attachments
| Field | Required | Description |
format |
Optional |
Output format for email data. Default simple. Options: simple (structured fields), resolved (fully parsed including all MIME parts, always downloads attachments), raw (raw RFC 2822 message). |
downloadAttachments |
Optional |
Default false. When true and format=simple, attachment binary data is downloaded and stored in the output binary map. The resolved format always downloads attachments regardless of this setting. |
attachmentsBinaryPropertyPrefix |
Optional |
Default attachment_. Prefix for binary map keys when attachments are downloaded. The first attachment uses key attachment_0, the second attachment_1, and so on. |
Timeouts
| Field | Required | Description |
connectionTimeoutSeconds |
Optional |
Default 15. TCP connection establishment timeout in seconds. |
authTimeoutSeconds |
Optional |
Default 20. IMAP authentication handshake timeout in seconds. |
commandTimeoutSeconds |
Optional |
Default 30. Timeout for individual IMAP commands (SELECT, SEARCH, FETCH) in seconds. Increase for large mailboxes with slow FETCH responses. |
Sample Configuration JSON
{
"host": "imap.gmail.com",
"port": 993,
"user": "invoices@company.com",
"password": "{{ $credentials.gmail-app-password }}",
"tls": true,
"mailbox": "INBOX",
"customEmailConfig": "[\"UNSEEN\", \"SUBJECT\", \"Invoice\"]",
"batchSize": 10,
"postProcessAction": "read",
"downloadAttachments": true,
"attachmentsBinaryPropertyPrefix": "invoice_attachment_",
"format": "simple"
}
Validation Errors
| Error | Cause |
host is required | The host field is empty or missing. |
user is required | The user field is empty or missing. |
password is required | The password field is empty or missing. |
ImapAuthenticationException | The IMAP server rejected the credentials. Verify the username and password (or app password) are correct. |
ImapMailboxNotFoundException | The mailbox folder specified in mailbox does not exist on the server. |
ImapCommandTimeoutException | An IMAP command exceeded commandTimeoutSeconds. Increase the timeout or reduce batchSize. |
ImapAttachmentSizeLimitException | An attachment exceeded the configured size limit. The attachment metadata is included in the output but the binary data is not downloaded. The error field on the attachment record is populated. |
Output
Success Port — Per Email
One workflow execution fires per email. All fields below are available on the success port:
| Field | Type | Description |
uid | number | IMAP UID of the message. Used internally for deduplication tracking. |
messageId | string | RFC 2822 Message-ID header value. |
subject | string | Email subject line. |
from.name | string | Sender display name. Empty when not present. |
from.address | string | Sender email address. |
to | array | Array of recipient objects each with name and address fields. |
cc | array | Array of CC recipient objects, same structure as to. |
date | string | Email date header as ISO 8601 string. |
body.text | string | Plain text body of the email. Empty if the email is HTML-only. |
body.html | string | HTML body of the email. Empty if the email is text-only. |
attachments | array | Array of attachment metadata objects (see below). Present regardless of downloadAttachments setting. |
Attachment Metadata Object
| Field | Type | Description |
fileName | string | Attachment filename as declared in the MIME part. |
mimeType | string | MIME content type (e.g. application/pdf, image/png). |
size | number | Attachment size in bytes. |
contentId | string | Content-ID for inline attachments. null for regular attachments. |
binaryKey | string | Key into the binary output map when the attachment was downloaded (e.g. invoice_attachment_0). null when binary data was not downloaded. |
error | string | Set when the attachment exceeded the size limit and was not downloaded. null on success. |
Error Port
Fires on connection failure, authentication failure, mailbox not found, or configuration validation errors. The output contains errorCode and message fields. The trigger pauses polling and retries on the next scheduled interval.
Sample Output JSON
{
"uid": 4812,
"messageId": "<CABx1y2z3a4b5c6d7e8f9g@mail.gmail.com>",
"subject": "Invoice #2026-0512 from Acme Supplies",
"from": {
"name": "Acme Supplies Billing",
"address": "billing@acme-supplies.com"
},
"to": [
{ "name": "Invoices", "address": "invoices@company.com" }
],
"cc": [],
"date": "2026-05-26T07:42:15Z",
"body": {
"text": "Please find attached your invoice for May 2026.",
"html": "<p>Please find attached your invoice for May 2026.</p>"
},
"attachments": [
{
"fileName": "invoice-2026-0512.pdf",
"mimeType": "application/pdf",
"size": 148320,
"contentId": null,
"binaryKey": "invoice_attachment_0",
"error": null
}
]
}
Expression Reference
| Expression | Value returned |
{{ $output.email.subject }} | Email subject line. |
{{ $output.email.from.address }} | Sender email address. |
{{ $output.email.from.name }} | Sender display name. |
{{ $output.email.body.text }} | Plain text email body. |
{{ $output.email.body.html }} | HTML email body. |
{{ $output.email.date }} | Email date as ISO 8601 string. |
{{ $output.email.attachments[0].fileName }} | Filename of the first attachment. |
{{ $output.email.attachments[0].mimeType }} | MIME type of the first attachment. |
{{ $output.email.attachments[0].binaryKey }} | Binary map key for the first downloaded attachment. |
{{ $output.email.uid }} | IMAP UID of the message. |
Node Policies & GuardRails
- Store credentials in Credentials Manager. Reference stored credentials with
{{ $credentials.name }}. For Gmail, use an App Password generated in Google Account settings. For Microsoft 365, use an App Password or OAuth token — the primary account password will not work when modern authentication is enforced.
- Keep
tls: true in production. IMAP without TLS transmits credentials and email content in plaintext. Only set tls: false in isolated development environments, and never disable allowUnauthorizedCerts in production.
- Never set
downloadEmailOnEveryTrigger: true in production. This disables UID deduplication and will cause every matching email to re-trigger on every poll cycle, producing duplicate workflow executions. It exists only for testing purposes.
- Choose
postProcessAction deliberately. Use read (the default) for most workflows to prevent re-triggering on the same email. Use delete only when the mailbox is a dedicated processing inbox and emails are not needed after processing. Use nothing only with an alternative deduplication mechanism.
- Scope
customEmailConfig tightly. A broad ["UNSEEN"] criteria on a high-volume inbox may fetch hundreds of unrelated emails per cycle. Add FROM, SUBJECT, or SINCE criteria to limit what is fetched to only emails your workflow needs.
- Set reasonable timeouts for remote mail servers. Corporate IMAP servers accessed over VPN or the public internet may be slower than cloud providers. Increase
commandTimeoutSeconds if you see intermittent timeout errors rather than reducing batchSize first.
Examples
Invoice Processing — Detect and Extract PDF Attachment
{
"host": "imap.gmail.com",
"port": 993,
"user": "invoices@company.com",
"password": "{{ $credentials.gmail-invoices-app-password }}",
"tls": true,
"mailbox": "INBOX",
"customEmailConfig": "[\"UNSEEN\", \"SUBJECT\", \"Invoice\"]",
"batchSize": 5,
"postProcessAction": "read",
"downloadAttachments": true,
"attachmentsBinaryPropertyPrefix": "invoice_",
"format": "simple"
}
Polls the invoices inbox every cycle for unread emails with "Invoice" in the subject. Each qualifying email triggers a separate workflow run. The PDF attachment is downloaded and available in the binary map under key invoice_0 for an OCR or parsing node downstream. Processed emails are marked as read so they are excluded from the next poll.
Support Ticket Creation from Customer Email
{
"host": "outlook.office365.com",
"port": 993,
"user": "support@company.com",
"password": "{{ $credentials.outlook-support-app-password }}",
"tls": true,
"mailbox": "INBOX",
"customEmailConfig": "[\"UNSEEN\"]",
"batchSize": 20,
"postProcessAction": "read",
"downloadAttachments": false,
"format": "simple"
}
Each new email to the support inbox triggers a workflow that maps {{ $output.email.from.address }} to the customer record, {{ $output.email.subject }} to the ticket title, and {{ $output.email.body.text }} to the ticket description. Attachments are not downloaded because the downstream Jira node only requires text fields.
Approval Reply Detection
{
"host": "imap.gmail.com",
"port": 993,
"user": "approvals@company.com",
"password": "{{ $credentials.gmail-approvals-app-password }}",
"tls": true,
"mailbox": "INBOX",
"customEmailConfig": "[\"UNSEEN\", \"SUBJECT\", \"RE: Approval Request\"]",
"batchSize": 10,
"postProcessAction": "delete",
"downloadAttachments": false,
"format": "simple"
}
Watches for reply emails to approval requests. The subject filter limits fetching to replies, and postProcessAction: delete removes processed emails from the dedicated approvals mailbox. A downstream Code Execute node inspects {{ $output.email.body.text }} for approval keywords (approved, rejected) to resume the suspended parent workflow.