MailKit Module
Send personalized emails from a workflow through your own SMTP server or email provider, with the MailKit client: one email at a time, or one email per row of a list.
The MailKit Module adds two Tasks:
- MailKitSendEmail sends one email.
- MailKitSendBulkEmail sends one email per row of a list, such as the rows of a File Query result or the records of a Query records Task. Each row fills the template.
Both build the email the same way as the Email Module: from one of your Workspace's email templates (Storage → Templates), from HTML written in the Task, or from plain text, with {variable} placeholders filled when the email is sent. Use the Email Module when you send through Azure Communication Services, and this Module for any other provider.
What you can build
- Confirmations and reminders from your own domain, through the mail account you already have (Microsoft 365, Google Workspace).
- A monthly offer to a customer list: Query file reads
customers.xlsxwith Variables get: All rows, then Send bulk email sends the offer template to every row, with{row.firstName}and{row.code}filled in per customer. - Invoices by email: each row names its own file, attached with
ref-storage:{row.invoice}. - A delivery report: after a bulk send, a Switch on
{result.failed}emails the list of rows that could not be sent to the team.
Configuration
Every Workspace connects its own SMTP account, so the sender address, sending limits and reputation stay with you. Configure it per Environment in the Module's settings.
SMTP server
Required. The host name only, such as smtp.office365.com, smtp.gmail.com or smtp.sendgrid.net: no smtp:// and no :port.
Port and Security
Port: 587 for most providers, 465 for SSL/TLS. Port 25 is usually blocked for cloud services.
Security: Automatic (default) uses SSL/TLS on port 465 and STARTTLS on any other port. You can also pick STARTTLS, SSL/TLS or None (unencrypted). Automatic and STARTTLS fail if the server can't encrypt; they never fall back to plain text.
Username and password
The account that signs in, and its password, app password or API key. Leave both empty for a server that accepts mail without signing in. A username and password are only sent over an encrypted connection, so they can't be used with Security None.
From address
Required. The sender address. Most providers only accept an address of the signed-in account or of a verified domain.
From name and default reply-to
Optional. The display name shown with the From address (for example Contoso Support), and where replies go when a Task doesn't set its own Reply-to.
Settings for common providers:
| Provider | Server | Port | Username | Password |
|---|---|---|---|---|
| Microsoft 365 | smtp.office365.com | 587 | the mailbox address | its password, or an app password with multi-factor sign-in. SMTP AUTH must be enabled for the mailbox. |
| Gmail / Google Workspace | smtp.gmail.com | 587 | the Gmail address | an app password (needs 2-step verification) |
| SendGrid | smtp.sendgrid.net | 587 | apikey | your API key |
| Mailgun | smtp.mailgun.org, or smtp.eu.mailgun.org for a domain in the EU region | 587 | the domain's SMTP login (Sending → Domain settings → SMTP credentials) | that login's SMTP password, not the API key |
| Amazon SES | email-smtp.<region>.amazonaws.com | 587 | SMTP user name | SMTP password (not your AWS keys) |
If the send fails with refused the username or password, check the login and that the server is the one your account lives on: SMTP logins exist only on their region's server (a Mailgun domain whose MX records are mxa.eu.mailgun.org uses smtp.eu.mailgun.org).
Only public mail servers can be used: a server that is localhost or resolves to a private, loopback or link-local address is refused.
MailKitSendEmailTask
| Property | Required | Notes |
|---|---|---|
| To | yes | Recipient addresses separated by commas or semicolons. Accepts {variables}. |
| Cc / Bcc | no | Same format as To. At most 50 recipients in total. Bcc recipients are never shown in the email. |
| Body | yes | Template, HTML or Text. |
| Template | with Template | File name of a template in Storage → Templates, for example appointment-confirmation.html (.html is added if missing). Accepts {variables}. |
| Subject | with HTML / Text | Overrides the template's <title>. Accepts {variables}. |
| HTML body | with HTML | Full HTML body. |
| Text body | with Text | Plain-text body. |
| Attachments | no | Files, one per line or comma-separated: file fields such as ref-session:{report} or ref-storage:terms.pdf, or workspace storage paths such as templates/documents/terms.pdf. 10 MB in total. |
| Reply-to | no | Defaults to the Module's Default reply-to. |
| OutputVariable | no | Receives the Message-Id of the sent email, such as <abc123@example.com>. |
When sending fails (the Module isn't configured, a template or attachment is missing, an address is invalid, the server can't be reached, refuses the sign-in or refuses the message) the Task sets its output to error, so an outgoing flow named error can handle it.
MailKitSendBulkEmailTask
Sends one email per row of a list, all over one connection to your server. While a row's email is built, the row is a variable, {row} by default: write {row.email} or {row.firstName} in To, Subject, the template, the HTML or text body and Attachments, next to any other flow variable such as {month}.
| Property | Required | Notes |
|---|---|---|
| Rows | yes | The {variable} holding the list, one email per row. At most 500 rows. |
| Each row as | no | The name a row takes, {row} by default. |
| To | yes | The row's recipient, {row.email} by default. One address, or several separated by commas or semicolons. |
| Body, Template, Subject, HTML body, Text body | As in MailKitSendEmailTask, filled per row. The template is read once. | |
| Attachments | no | Files attached to every email; a row's own file works too, such as ref-storage:{row.invoice}. 10 MB per email. |
| Reply-to | no | Defaults to the Module's Default reply-to. |
| Emails per minute | no | Advanced. A pace for providers with a sending limit (Microsoft 365 allows 30 a minute). 0 sends as fast as the server accepts. A list that would take longer than 15 minutes at this pace is refused. |
| OutputVariable | no | Receives the result, {result} by default. |
Where the rows come from:
- Query file with Variables get: All rows: each row has the file's columns,
{row.Email},{row.Name}(as the header row spells them). - Query records: each record keeps its values under
fields, so use{row.fields.email}. - Any list variable, or a variable holding a JSON array of objects.
The result:
| Field | Meaning |
|---|---|
{result.total} | Rows in the list. |
{result.sent} | Emails the server accepted. |
{result.failed} | Rows not sent. |
{result.failures} | The rows not sent (the first 100), each with index (its position in the list, from 0), to and error. |
A row that can't be sent (an invalid or empty address, a recipient the server refuses) is listed in the result and the next row is sent. If the server closes the connection, it is reopened once and the email retried; if that fails, the remaining rows are listed as not sent. The Task sets its output to error only when no email at all was sent; otherwise it continues normally, so check {result.failed} with a Switch when the flow should react to partial failures.
Send bulk email is for lists your contacts expect, such as their own invoices, reminders or offers they signed up for. Respect your provider's sending limits and the recipients' consent.