Skip to main content

Mailtrap Send ExecModule

Overview

MailtrapSendModule submits one transactional email to Mailtrap's fixed https://send.api.mailtrap.io/api/send endpoint. Version 2.0 replaces the legacy batch sender with a narrow, verifiable contract: one recipient, one explicitly confirmed provider request, one READY IntegrationAccount, bounded content, and one validated Mailtrap message ID.

The former version ignored its declared IntegrationAccount, accepted credentials and an arbitrary endpoint from server environment, silently switched to a dry run when credentials were missing, counted dry runs as successful deliveries, retried non-idempotent sends three times, allowed unbounded batches and concurrency, and exposed recipient/provider details in logs and failures. Those behaviors are removed. Existing workflows that provide mailItems, dryRun, concurrency, retries, raw credentials, or an endpoint must migrate to the v2 single-message shape.

Mail submission is an external, non-idempotent side effect. The module never automatically retries an HTTP, timeout, or ambiguous transport failure because Mailtrap may have accepted the email before the workflow observed the failure.

Usage

  1. Verify the sending domain in Mailtrap.
  2. Create a Mailtrap API token with transactional email sending permission.
  3. Store the token only in the encrypted apiKey field of a ValkyrAI IntegrationAccount, set the account status to READY, and bind it through ExecModuleConfig.authConfig.integrationAccount.
  4. Add MailtrapSendModule to the approved outbound workflow.
  5. Supply one to address, one verified from address, subject, and at least one of text or html.
  6. Set confirmSend to true only after the workflow has resolved its recipient, content, and required approval.
  7. Persist the returned messageId for delivery-event or provider-console reconciliation.

Inputs

NameTypeRequiredDescriptionLocal constraints
tostringYesSingle transactional recipient.Valid email, at most 254 characters.
fromstringYesVerified Mailtrap sender.Valid email, at most 254 characters.
fromNamestringNoSender display name.At most 128 Unicode code points; no control characters.
replyTostringNoReply-to address.Valid email, at most 254 characters.
subjectstringYesMessage subject.Non-blank, at most 998 Unicode code points; no control characters.
textstringConditionalPlain-text body.text or html is required; at most 1,000,000 code points.
htmlstringConditionalHTML body.html or text is required; at most 1,000,000 code points.
confirmSendbooleanYesExplicit approval of the provider side effect.Must be the JSON boolean true.

Input map values override the same normalized payload fields. The complete serialized provider request is limited to 2 MB. A body may contain newlines but not a null character.

The following legacy or unsafe fields are rejected before transport:

  • mailItems
  • concurrency
  • retries
  • dryRun
  • mock
  • test
  • apiKey or api_key
  • token, secret, or password
  • endpoint or url

Outputs

NameTypeWhen presentDescription
statusstringAlwayssuccess only after verified acceptance; otherwise error.
messageIdstringSuccessOne bounded provider message ID from message_ids.
providerAcceptedbooleanAlwaystrue only for HTTP 200, success:true, and exactly one valid ID.
attemptsintegerAlways0 before transport or 1 after the single provider attempt.
errorobjectFailureSafe code, message, and retryable:false.

providerAccepted:true means Mailtrap accepted the request for processing. It does not prove final delivery, inbox placement, reading, or link interaction. The module does not return the recipient, message content, API token, or provider response body.

IntegrationAccount Requirements

SettingRequirement
ProviderMailtrap Email API transactional stream
StatusREADY
AuthenticationBearer API token with sending permission
accountNameHuman-readable Mailtrap account or verified-domain identity
apiKeyEncrypted Mailtrap API token, 20 to 4,096 non-whitespace characters
RelationshipBind through ExecModuleConfig.authConfig.integrationAccount

The module does not read MAILTRAP_SECRET_KEY, MAILTRAP_API_ENDPOINT, workflow payload credentials, or caller-supplied URLs. It can contact only send.api.mailtrap.io in production. Sender verification, domain DNS, suppression lists, unsubscribe policy, retention, and account-level compliance remain provider and tenant responsibilities.

Configuration

Illustrative normalized configuration:

{
"version": "2.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:mailtrap-transactional"
},
"payloadConfig": {
"parameters": "{\"to\":\"customer@example.com\",\"from\":\"billing@example.com\",\"fromName\":\"Valkyr Billing\",\"replyTo\":\"support@example.com\",\"subject\":\"Your download is ready\",\"text\":\"Your secure link is ready.\",\"confirmSend\":true}"
}
}

The account value is a symbolic secure reference. Persisted workflows use the generated IntegrationAccount relationship and never a plaintext token.

Operations

MailtrapSendModule supports one operation:

Provider requestLocal behaviorSide effect
POST https://send.api.mailtrap.io/api/sendConstruct one bounded transactional message and verify the acceptance envelope.Submits one email to one recipient.

The request uses Authorization: Bearer and Content-Type: application/json. A provider response is successful only when all of these conditions hold:

  1. HTTP status is exactly 200.
  2. The JSON body contains success:true.
  3. message_ids is an array with exactly one string.
  4. The ID contains only the module's bounded safe characters.

Bulk stream, provider batch sending, marketing campaigns, templates, attachments, scheduled delivery, contact management, sandbox inboxes, delivery webhooks, and suppression management are outside this module's contract.

Errors and Failure Modes

FailureBehaviorRecovery
Validation failureReturns VALIDATION_ERROR before transport.Correct the named field and repeat approval.
Missing accountReturns INTEGRATION_ACCOUNT_REQUIRED.Bind the intended Mailtrap account.
Non-ready accountReturns INTEGRATION_ACCOUNT_NOT_READY.Repair or reauthorize the account and set it to READY.
Invalid account tokenReturns VALIDATION_ERROR without sending.Rotate and store a bounded API token in apiKey.
HTTP 400Returns MAILTRAP_HTTP_400 after one attempt.Correct addresses, sender, body, or account-domain state.
HTTP 401 or 403Returns the matching HTTP code after one attempt.Rotate the token or repair sending permission/domain verification.
HTTP 429Returns MAILTRAP_HTTP_429 without retry.Reconcile provider activity and schedule a deliberate later attempt.
HTTP 5xx or transport failureReturns a safe ambiguous-acceptance failure without retry.Check Mailtrap logs/activity before any new send.
Oversized responseReturns MAILTRAP_RESPONSE_TOO_LARGE.Inspect provider compatibility; the body is not retained.
HTTP 200 without verified envelopeReturns MAILTRAP_UNVERIFIED_ACCEPTANCE.Treat as failure and inspect provider/API compatibility.

Provider failure bodies can contain recipient data or credential-like strings, so they are not copied into workflow output. Exceptions expose only bounded local guidance and the HTTP code when known.

Example

Submit one approved fulfillment notice:

{
"to": "customer@example.com",
"from": "billing@example.com",
"fromName": "Valkyr Billing",
"replyTo": "support@example.com",
"subject": "Your download is ready",
"text": "Your secure link is ready.",
"confirmSend": true
}

Expected result after Mailtrap returns a verified acceptance envelope:

{
"status": "success",
"messageId": "0c7fd939-02cf-11ed-88c2-0a58a9feac02",
"providerAccepted": true,
"attempts": 1
}

Notes

  • Pagination: not applicable; one execution submits one message.
  • Limits: one recipient, one request, 998 subject code points, 1,000,000 code points per body representation, and a 2 MB serialized request.
  • Rate limits: HTTP 429 is surfaced without automatic replay.
  • Idempotency: sending email is non-idempotent. confirmSend proves explicit workflow intent but is not a durable provider idempotency key.
  • API constraints: the production origin is fixed. Workflow input cannot select the transactional, bulk, batch, or sandbox endpoint.
  • Destructive behavior: the module cannot recall or compensate a message after provider acceptance.
  • Migration: replace each legacy mailItems batch with one governed task per recipient. Remove environment credentials, endpoints, concurrency, retries, and dry-run assumptions.
  • Observability: logs record only a validated message ID or failure class. Recipient addresses, subjects, bodies, tokens, and provider error bodies are omitted.
  • Unverified boundary: repository tests cover request construction, account requirements, validation, fixed routing, success-envelope verification, secret redaction, metadata discovery, and the single-attempt rule. Live sending requires separately authorized Mailtrap credentials and is not exercised in repository tests.

See Mailtrap's official Email API overview and transactional sending reference for current provider behavior.