Send email (via SMTP)
The service task "Send email (via SMTP)" sends an email through any SMTP server, such as the company's own mail server or a mailbox at a provider. Sender, recipients, subject, text or HTML and attachments are specified completely in the input expression; Pantarey only opens the connection and hands over the message. This allows emails with any sender to any recipient, without a Microsoft 365 account and without a domain approval in Pantarey.
Technical name prio_sendEMailSMTP · Category in the "Select service task" dialog: Email
When is this service used?
- Confirmations to customers: Musterfirma GmbH confirms training registrations from
schulung@musterfirma-augsburg.dethrough its own mail server, with the agenda as a PDF attachment. - Sending via a provider: Quotes or invoices go out through the SMTP account of a mail provider when Microsoft 365 is not in use.
- Archive copy: Every outgoing mail is copied to an archive mailbox via
bcc. - Ready-made content: Subject and HTML were produced in a previous step and are to be sent unchanged. For templates with placeholders, see Send email (via SMTP) from template.
Which email service?
| Service | Sender | Recipients |
|---|---|---|
| Send email (via SMTP) – this page – and Send email (via SMTP) from template | own mail server, any address the server allows | any |
| Send email (Microsoft Graph) | Microsoft 365 account | any |
| Send email to external recipients (own domain) | own domain, approved for the account | any |
| Send email from template via Pantarey (internal) and Send email via Pantarey (internal) | benachrichtigung@pantarey.io |
users of the own Pantarey account only |
Prerequisites
- An SMTP server that is reachable from the internet. The connection is opened from the Pantarey cloud; a server that is reachable only inside the company network does not work.
- Credentials as secrets: user name and password are stored under Manage secrets with Create secret and inserted in the input as
{{secret:NAME}}. The placeholders are replaced only intransport.auth.userandtransport.auth.pass; anywhere else{{secret:…}}remains literal text. - The sender address has to be accepted by the SMTP server. The server checks this, not Pantarey.
Input
| Field | Type | Required | Meaning |
|---|---|---|---|
transport |
object | yes | Connection to the SMTP server |
transport.host |
string | yes (or service) |
Host name of the server, e.g. smtp.musterfirma-augsburg.de |
transport.port |
number | no | Port, e.g. 587 or 465; without it the library default applies. A text such as "587" is converted to a number |
transport.secure |
boolean | no | true for a connection that is encrypted from the start (port 465), otherwise false |
transport.service |
string | no | Short name of a well-known provider (e.g. Outlook365, Gmail); replaces host and port |
transport.auth.user, transport.auth.pass |
string | no | Credentials; the only fields in which {{secret:NAME}} is resolved |
transport.requireTLS, ignoreTLS, opportunisticTLS, authMethod, name, connectionTimeout, greetingTimeout, socketTimeout, dnsTimeout |
as in nodemailer | no | Connection options |
transport.tls.rejectUnauthorized, servername, minVersion, maxVersion, ciphers |
as in nodemailer | no | TLS options |
message |
object | yes | The email |
message.from |
string or {name, address} |
yes | Sender |
message.to, message.cc, message.bcc |
string (several separated by , or ;), array or {name, address} |
at least one | Recipients |
message.subject |
string | no | Subject; if missing, No subject is used |
message.text, message.html |
string | no | Content as text and/or HTML; if both are missing, the text No content is sent |
message.replyTo, sender, inReplyTo, references, priority, headers |
string / object | no | Reply address, threading, priority (high, normal, low), custom headers (text values only) |
message.attachments |
file object or array | no | Attachments from the Pantarey storage, each {referenceId, filename, contentType}; filename and contentType are taken over |
All other fields of the underlying library (such as sendmail, path, proxy, url, pool, raw, alternatives, icalEvent, envelope, dkim) are discarded for security reasons. For text and html only strings are accepted; objects with path or href are dropped, as are path/href on attachments. The service has no size limit for attachments; what is accepted is decided by the SMTP server.
{
"transport": {
"host": "smtp.musterfirma-augsburg.de",
"port": 587,
"secure": false,
"auth": { "user": "{{secret:SMTP_USER}}", "pass": "{{secret:SMTP_PASS}}" }
},
"message": {
"from": "schulung@musterfirma-augsburg.de",
"to": participant.email,
"bcc": "schulung-archiv@musterfirma-augsburg.de",
"subject": "Your registration for the training " & training.title,
"html": "<p>Dear " & participant.name & ",</p><p>we confirm your participation on " & training.date & " in Augsburg.</p>",
"attachments": [ training.agendaPdf ]
}
}
Output
{
"status": 200,
"response": {
"messageId": "<a1b2c3@musterfirma-augsburg.de>"
}
}
response.messageId is the identifier the server assigned to the message. response additionally contains the server's reply, such as accepted and rejected addresses. The result is stored under the result path; if it is not used further, Discard result is the appropriate setting.
Errors and behavior
- Missing required fields abort the step, for example
Missing required field: transport.host,Missing required field: message.fromorMissing recipients: at least one of message.to, message.cc, or message.bcc must be set. - Errors from the SMTP server (login rejected, sender not allowed, connection refused) are passed on unchanged as errors.
- Every error throws: With an error boundary event the process continues there; without one the instance ends in error, a resume point is saved and the process owner receives an error email. The service never returns
{status, message}without aborting. - Retries: For transient errors (SMTP 450–452, timeout, dropped connection) sending is attempted up to three times. If the server accepted the mail but did not reply in time, the mail may arrive twice. Business errors are not retried.
- Time limit: 900 seconds per call.
- The dry run does not send any mail; the step returns a sample output from the catalog.
Example
Musterfirma GmbH confirms training registrations. After the user task "Check registration", the message contains participant (name, email) and training (title, date, agenda as file object agendaPdf).
- Secrets
SMTP_USERandSMTP_PASSare created once under Manage secrets. - Input expression as above;
bccplaces the copy in the archive mailbox. - Result path
dispatch, so thatdispatch.response.messageIdcan be looked up in the Process Explorer. - Next step: A database step sets the registration status to "confirmed". An error boundary event on the service leads to the user task "Check dispatch".
Frequently asked questions
Why does {{secret:SMTP_PASS}} appear literally in the subject or body of the mail?
With this service, secrets are replaced only in transport.auth.user and transport.auth.pass. Anywhere else the placeholder stays as text.
The mail arrived twice. Why?
The server accepted the mail but replied too late or with a transient error code, and the sending was retried. This is a deliberate trade-off: a duplicate is better than a missed delivery. To rule it out, store the messageId and check before sending whether one already exists.
The server rejects the sender although the credentials are correct.
Many servers allow only sender addresses belonging to the logged-in account. message.from has to match the account in transport.auth, or the server has to know the address as an alias.
Next step
Send email (via SMTP) from template: the same delivery route, but subject and content as a Handlebars template with placeholders.