Martini Email Functions
Overview
Martini Email Functions gives you a set of functions for sending, reading, searching, and organizing email directly from your services and workflows. Every function handles its own connection lifecycle — you supply the server credentials, and Martini opens the connection, performs the operation, and closes it when done.
What You Will Learn
- How to send new messages, replies, and forwarded messages with attachments
- How to fetch, paginate, and search inbound messages from a mailbox
- How to organize email by moving and deleting messages between IMAP folders
When To Use This
Use Martini Email Functions when you need to automate email-driven processes directly from a service or workflow — without writing low-level SMTP/IMAP session management code.
Common scenarios include:
- Polling a shared inbox (e.g.,
invoices@company.com) and routing messages to downstream systems - Sending transactional notifications, order confirmations, or alerts from within a workflow
- Replying to or forwarding emails as part of an approval or escalation process
- Archiving processed messages into specific IMAP folders for audit purposes
- Building paginated inbox views or search interfaces on top of a live mailbox
Prerequisites
- Martini Designer installed and running
- A Martini package in the current workspace
- A service or workflow to invoke the functions from
- Valid mail server credentials (account address, password or app-specific password, host, and port)
- Basic understanding of the following:
- Invoke Function Node for workflows
- Function Step for services
Connecting to a Mail Server
Every email function shares a common set of connection input properties. Understanding them once means you can configure any function quickly — whether you are sending, reading, or organizing messages.
Mail Server Connection Properties
The table below covers every shared connection property. Set these consistently across all function calls in a single workflow to keep your credential management simple.
| Property | Example Value | What It Controls |
|---|---|---|
protocol |
imaps |
The transport protocol: smtp, smtps, imap, imaps, pop3, or pop3s |
login |
invoices@company.com |
The mailbox account address used to authenticate |
password |
app-specific-pw |
The account password or app-specific password; never a plain account password in prod |
host |
imap.gmail.com |
The mail server hostname for the chosen protocol |
port |
993 |
The TCP port that pairs with the protocol (see reference table below) |
debug |
false |
When true, prints the raw IMAP/POP3 session to the console for diagnostics |
Supported Email Protocols and Ports
Choose the encrypted variant of each protocol in all production environments. Unencrypted protocols transmit credentials in plain text and should only be used in isolated local testing.
| Protocol | Port | Use When |
|---|---|---|
smtps |
465 | SMTP submission over implicit TLS |
smtp |
587 | SMTP submission with STARTTLS (standard message submission port) |
imaps |
993 | Reading and organizing mail over implicit TLS |
imap |
143 | IMAP with STARTTLS upgrade or legacy unencrypted IMAP |
pop3s |
995 | POP3 over implicit TLS |
pop3 |
110 | POP3 with STLS upgrade or legacy unencrypted POP3 |
Common Mail Server Hostnames
If you are unsure of your server's hostname, use these standard values for the major cloud mail providers.
| Provider | SMTP Host | IMAP Host |
|---|---|---|
| Gmail / Google Workspace | smtp.gmail.com |
imap.gmail.com |
| Outlook / Microsoft 365 | smtp-mail.outlook.com |
imap-mail.outlook.com |
| Yahoo Mail | smtp.mail.yahoo.com |
imap.mail.yahoo.com |
Troubleshooting Mail Server Connection Issues
| Problem | Detection | Cause | Fix |
|---|---|---|---|
| Authentication rejected | Function throws a login failure exception | Invalid credentials, app password required, or provider blocked the sign-in | Verify credentials and generate an app-specific password if required |
| Connection refused | Function throws a connection refused exception | Wrong host, wrong port, firewall restrictions, or service unavailable | Verify hostname, protocol, port, and network connectivity |
| SSL handshake failure | Function throws an SSL exception | Certificate issues, TLS incompatibility, or protocol/port mismatch | Verify certificates and ensure the protocol matches the expected TLS mode |
debug output flooding logs |
Console fills with raw session data | debug left enabled in production |
Set debug to false before deploying |
Email Data Models Reference
Every email function uses one or more of the following data models. Understanding their properties helps you map data correctly in services and workflows.
| Data Model | Description |
|---|---|
Message |
The central model returned when reading email. Holds to, cc, bcc, from, replyTo, subject, body, contentType, messageId, attachments, bodyParts, and headers. |
Address |
Represents an RFC 822 email address. type identifies the address type; address holds the address string (e.g., vendor@example.com); personal holds the display name (e.g., Acme Supplies). |
DataSource |
Represents a file attachment. When sending, populate name, contentType, and inputStream. |
Header |
A name-value pair for a single MIME header. Use it to set custom headers on outgoing mail, for example X-Priority: 1 for high priority or X-Correlation-ID to carry a trace identifier across systems. |
MailMetadata |
Returned after sending. The most useful properties are messageId (for correlating with later events), sentDate, from, recipients, subject, size, and headers. |
PaginatedMessages |
Wraps the current page of Message data models together with totalCount (total messages in the folder) and totalPages (total pages at the requested limit). |
DeleteEmailsResult |
Returned after deletion. Contains a messageIds array of the values that were successfully removed — use this to detect and log any IDs the server could not find. |
Sending Email
The sending functions cover three scenarios:
- Composing a new message from scratch (
sendEmail) - Replying to an existing message with proper threading (
replyToEmail) - Re-routing a message to new recipients (
forwardEmail)
All three return a MailMetadata model describing the sent message.
Sending a New Message with sendEmail
Use sendEmail to compose and deliver a new message.
CC, BCC, attachments, and custom headers are all optional.
Recipients: Pass one or more Address data models in the to property.
Each Address has an address property (the email address) and a personal property (the display name).
Body format: Set isHtml to true when your body contains HTML markup; leave it false (the default) for plain text.
Attachments: Add a DataSource data model to the attachments list for each file.
Set name to the attachment filename, contentType to the MIME type, and inputStream to the file bytes.
Example — sending an order confirmation with a PDF receipt:
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Expected result: The function returns a MailMetadata model.
The messageId property is most useful if you need to correlate the sent message with a later reply or audit log entry.
Replying to a Message with replyToEmail
Use replyToEmail when you already have a Message in hand — from readEmail, listEmails, or searchEmails — and want to send a threaded reply.
Threading: Automatically extracts the In-Reply-To and References headers from the original message so the reply lands in the correct conversation thread in any modern mail client.
The subject is prefixed with Re: if it isn't already.
replyAll flag: Controls who receives the reply:
false(default) — reply goes only to the original sendertrue— reply goes to all originalTO,CC, andBCCrecipients, useful for team inboxes
Example — acknowledging a vendor's invoice submission:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Expected result: The function returns a MailMetadata model describing the sent reply.
The reply appears in the correct thread in the recipient's mail client.
Forwarding a Message with forwardEmail
Use forwardEmail to re-send an existing Message to a new set of recipients.
Original content: The original headers, body, and attachments are always preserved.
Additional content: Use additionalBody to prepend a note before the original content and additionalAttachments to append extra files.
The isHtml flag applies only to additionalBody, not to the original body.
Example — escalating an unrecognized invoice to the finance manager:
1 2 3 4 5 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Expected result: The function returns a MailMetadata model describing the forwarded message.
The recipient sees the original message body below your prepended note.
Troubleshooting Sending Function Issues
| Problem | Detection | Cause | Fix |
|---|---|---|---|
| Empty recipient error | Function throws on sendEmail |
to list is empty |
Add at least one Address model to to |
| Missing original message | Function throws on replyToEmail |
originalMessage not provided |
Always pass the Message from a read function |
| Attachment not received | Recipient sees email without attachment | inputStream is null on the DataSource |
Ensure the file stream is open and non-null before calling sendEmail |
| HTML displayed as plain text | Email body shows raw HTML tags | isHtml left as false with an HTML body |
Set isHtml to true when body contains HTML markup |
Reading Email
The reading functions give you three ways to access inbound messages, plus a utility for discovering what folders are available. Choose the function that matches your workflow pattern — polling for new messages, browsing all messages with pagination, or searching by specific criteria.
Fetching New Messages with readEmail
readEmail connects to your mail server and fetches messages.
IMAP: Returns only unread (UNSEEN) messages — making it ideal for polling workflows that process only what is new.
POP3: Returns all available messages because POP3 has no read/unread concept.
delete flag: Set to true to remove messages from the server immediately after fetching.
This is a common pattern in fire-and-forget intake workflows where you want to ensure the same message is never processed twice.
Example — pulling new emails from a dedicated invoice inbox:
1 2 3 4 5 6 7 8 9 10 | |
Expected result: Returns a messages array of Message models, each carrying the sender, recipients, subject, body, attachments, and headers.
Hold on to the messageId on each Message — you will pass it to replyToEmail, moveEmails, or deleteEmails later in the same workflow.
Browsing Messages with Pagination using listEmails
listEmails returns all messages in a folder regardless of read status.
Pagination: Supports limit and offset for page-by-page access, making it well suited for inbox review interfaces, audit logs, or any workflow that needs to walk a folder incrementally.
Set limit to 0 to fetch all messages at once.
Example — building a paginated inbox view (page 2, 20 messages per page):
1 2 3 4 5 6 7 8 9 10 11 | |
Expected result: Returns a PaginatedMessages model containing messages (the current page), totalCount (total messages in the folder), and totalPages (total pages at the chosen limit).
Finding Specific Messages with searchEmails
searchEmails filters messages server-side rather than pulling the entire mailbox into memory.
Filters: All filters are optional — only the ones you provide are applied. When multiple filters are set, all conditions must be satisfied (AND logic).
IMAP only: POP3 has no server-side search capability.
This function requires imap or imaps.
Available search filters:
| Filter | Type | Description |
|---|---|---|
fromAddress |
String | Match messages from this exact sender address |
subject |
String | Match messages containing this substring in subject |
since |
Date | Match messages received on or after this date |
before |
Date | Match messages received before this date |
unreadOnly |
Boolean | When true, only return unread (UNSEEN) messages |
Example — finding all unread invoices from a specific vendor received this month:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Expected result: Returns a messages array of Message models matching all provided filters.
Discovering Available Folders with listFolders
listFolders returns all folder names visible to the authenticated IMAP account.
Usage: Use the returned strings directly as the folder property value in readEmail, listEmails, searchEmails, moveEmails, and deleteEmails.
When to call it: Call listFolders at the start of any workflow that moves or archives messages — this confirms destination folders exist before you attempt to use them.
Example — confirming destination folders exist before processing:
1 2 3 4 5 6 7 8 | |
Expected result: Returns a plain list of folder name strings (e.g., INBOX, Processed, Escalated).
Check this list to confirm your expected folders are present before the rest of the workflow runs.
Troubleshooting Reading Function Issues
| Problem | Detection | Cause | Fix |
|---|---|---|---|
No messages returned by readEmail |
Empty messages array |
No unread messages in the folder | Check the mailbox directly; IMAP only returns UNSEEN messages |
searchEmails returns no results |
Empty messages array |
Filters too restrictive | Test with fewer filters to confirm messages exist |
listFolders not available |
Function throws unsupported operation | POP3 server used instead of IMAP | Switch to imap or imaps — POP3 does not support folders |
| Pagination returns wrong page | Unexpected messages in result | offset calculated incorrectly |
Calculate offset as (pageNumber - 1) * limit |
Organizing Email
Once messages are read and processed, use the organizing functions to keep the mailbox clean and structured.
moveEmails organizes messages into categorized folders; deleteEmails permanently removes messages you no longer need.
Both functions identify messages by messageId and work exclusively on IMAP servers.
Moving Messages Between Folders with moveEmails
moveEmails transfers one or more messages from a source folder to a destination folder on the same IMAP server.
All matched messages are moved in a single server operation.
Identifying messages: Messages are identified by their messageId values — the ones returned by any read function.
Example — archiving processed invoices out of INBOX:
1 2 3 4 5 6 7 8 9 10 11 | |
Expected result: Returns a list of messageId strings that were successfully moved.
Any ID absent from the result was not found in sourceFolder.
Deleting Messages with deleteEmails
deleteEmails permanently removes messages from an IMAP folder by messageId.
When to use: Use deleteEmails when archiving is not required and you want to keep the mailbox clean.
For audit-trail requirements, prefer moveEmails to an archive folder instead.
Example — purging spam-classified messages from a monitored inbox:
1 2 3 4 5 6 7 8 9 10 | |
Expected result: Returns a DeleteEmailsResult model whose messageIds array lists every ID that was successfully removed.
IDs absent from that list were not found in the specified folder.
Troubleshooting Organizing Function Issues
| Problem | Detection | Cause | Fix |
|---|---|---|---|
moveEmails returns empty list |
No IDs in result | Messages not found in sourceFolder |
Confirm message IDs with listEmails or searchEmails; verify source folder name via listFolders |
| Destination folder not found | Server-side error on move | Folder does not exist on the server | Call listFolders first to confirm the destination folder exists |
deleteEmails permanently removes wrong messages |
Unintended messages removed | Incorrect messageId values passed |
Double-check messageId values from the read function before passing to deleteEmails |
| Organize functions unavailable | Function throws unsupported operation | Using POP3 instead of IMAP | Switch to imap or imaps — folder operations require IMAP |
Helpful Resources
- Data Models — Overview of Martini data models and how they represent structured data
- Function Step — How to invoke built-in functions from a service
- Invoke Function Node — How to invoke functions from a workflow
- Community Q&A: Martini Community Have a question? Post or search it here.