Send transactional email from WordPress without relying on your hosting server’s mail configuration by routing an explicit email event through Volanea’s REST API. This guide shows the honest integration pattern: WordPress or a WordPress automation tool sends data to a webhook endpoint, and that endpoint validates, normalizes, and sends the message through Volanea.

There is an important naming detail to clear up first. “Send Email From WordPress” is not one universal WordPress product with a standard webhook schema. WordPress core provides wp_mail() for preparing mail, but it does not provide a universal outbound webhook feature or a single webhook payload that every WordPress site emits. The payload depends on the plugin, form builder, ecommerce extension, or automation layer that triggers the workflow.

That does not prevent a solid integration. It means the safe design is to define a small, versioned webhook contract at the boundary, then map it into Volanea’s email API request on your own server. You avoid pretending that a native Volanea app exists, keep the Volanea API key out of WordPress browser code, and gain control over retries, duplicate prevention, logging, and message content.

What this integration does—and does not do

This is a webhook/API integration, not a native WordPress connector. You will not install a “Volanea for WordPress” app, select a Volanea action inside WordPress, or paste a secret key into public client-side JavaScript.

Instead, the flow is:

  1. A WordPress event occurs: a form submission, completed order, new user registration, membership event, or custom application action.
  2. Your WordPress automation or custom code sends an HTTPS POST request to a webhook endpoint you control.
  3. The webhook endpoint verifies that the request is legitimate and converts the event into an email request.
  4. The endpoint calls Volanea’s POST /v1/send endpoint with a server-side API key.
  5. Volanea accepts the request for processing and delivery, while your endpoint records enough metadata to troubleshoot failures or safely retry.

This separation matters. WordPress’s wp_mail() function returns success when WordPress has handed a message to the configured mail transport; it is not proof that the recipient received the message. WordPress core also delegates the actual mailing environment to the server or configured SMTP transport. A dedicated email API gives your application a more explicit sending boundary and clearer operational controls.

The design is especially useful when the event that should create the email already lives outside WordPress’s generic notification system. For example, you may want a confirmation email only after a payment is captured, a support acknowledgment only after spam screening passes, or a welcome sequence only after a member activates their account.

Choose the right trigger for the email

Start with the business event, not the email template. Transactional messages should be tied to a specific user action or account state, with a clear reason for sending.

Typical WordPress-triggered transactional emails include:

  • Contact-form receipt and internal notification after a valid submission.
  • New-account welcome or email-verification message.
  • Password-reset, security alert, or email-address-change confirmation.
  • WooCommerce order receipt, shipment update, refund notice, or failed-payment alert.
  • Membership activation, renewal, cancellation, or access-expiry notification.
  • Booking confirmation, appointment reminder, or event-registration receipt.
  • Download-ready notice after a report, export, or digital product is generated.

Avoid using this pattern to turn every content update into a promotional campaign. Transactional mail and marketing mail have different consent, content, frequency, and suppression considerations. A receipt or password reset is triggered by a customer action; a product announcement is usually a campaign. Keeping those use cases distinct protects the user experience and makes your event logic easier to reason about.

Use an event identifier from the source system

Every trigger should have a stable identifier. For an ecommerce email, that could be an order ID. For a form, it could be a submission ID. For a custom registration workflow, it could be the new WordPress user ID plus a specific event name.

That identifier becomes the basis for idempotency. If the automation platform retries a webhook because of a timeout, your endpoint must recognize that it is processing the same event rather than send a second receipt.

A useful convention is:

wordpress:<event-type>:<source-record-id>:<message-purpose>

Examples:

wordpress:form-submission:4821:confirmation
wordpress:order:10482:receipt
wordpress:user:921:welcome

Do not generate a random value for every retry. Random values make retries look like new sends and defeat duplicate protection.

Understand the WordPress payload you actually have

Because WordPress core does not emit a universal webhook payload, there is no truthful “standard Send Email From WordPress webhook body” to copy from one site to another. A form plugin may emit fields such as email, name, and message; WooCommerce has order objects; custom code can pass any JSON you choose.

What WordPress core does document is the wp_mail() call shape:

wp_mail( $to, $subject, $message, $headers, $attachments );

That is a function call inside PHP, not a webhook request. Treating it as though it were a standard JSON schema leads to brittle integrations.

The practical answer is to define a deliberately small JSON payload for your webhook. Keep the source-specific fields in a data object, and keep routing and deduplication values at the top level. Here is a recommended payload contract for a WordPress automation or custom WordPress action:

{
  "event": "contact_form.submitted",
  "eventId": "4821",
  "occurredAt": "2026-08-23T14:28:00Z",
  "recipient": {
    "email": "alex@example.com",
    "name": "Alex Morgan"
  },
  "data": {
    "firstName": "Alex",
    "topic": "Implementation question",
    "message": "Can you help us with our account setup?",
    "siteUrl": "https://example.com"
  }
}

This is your integration contract, not a claim about a built-in WordPress payload. Its benefits are straightforward: a form-plugin change does not force a change in your email transport layer, source data stays easy to inspect, and the webhook receiver can reject malformed requests before an email is created.

Map source fields intentionally

Do not blindly use an arbitrary form field as an email recipient. A contact form’s submitter email can be the correct recipient for an acknowledgment, but not necessarily for an internal notification. Likewise, do not use a user-controlled form field as the from address. That can create spoofing, authentication, and reply-routing problems.

Use a verified address on your own domain as the sender, such as notifications@example.com. Put the visitor’s address in replyTo only when a human should reply to that person.

A practical mapping table looks like this:

Webhook fieldUse in email requestNotes
recipient.emailrecipient addressValidate before sending.
recipient.namerecipient display nameOptional; escape when rendered in HTML.
data.firstNamegreeting or template variableUse a fallback if it is missing.
data.topicsubject text or internal contextDo not allow it to become arbitrary HTML.
data.messageescaped email body contentTreat as untrusted input.
event + eventIdidempotency keyMust remain stable across retries.

Set up Volanea before connecting WordPress

Before writing the webhook receiver, prepare the sending identity and credentials in Volanea. The email API is the final delivery step, so it should not be the first thing you test.

You need:

  1. A Volanea account and a secret API key stored only in server-side configuration.
  2. A sending domain that has been authenticated in Volanea.
  3. A verified sender address on that domain, such as notifications@example.com.
  4. A clear transactional message purpose, sender name, and reply-handling policy.
  5. A test recipient mailbox that you control.

Use a secret key with the smallest access scope that supports this integration, and never add it to a WordPress page, shortcode, browser request, public repository, or an automation field that can be viewed by untrusted users. Store it in a host-level environment variable, secret manager, or protected deployment configuration.

If you need the endpoint, authentication, request fields, or response behavior while implementing this guide, refer to the Volanea API reference and setup guides. Treat the API reference as the source of truth for the currently supported request schema.

Authenticate the sending domain

A transactional API request is only one part of deliverability. Your sender domain should have the DNS records Volanea provides for domain verification and authentication. Use the exact hostnames, record types, and values shown in your Volanea domain setup—not values copied from another email provider or guessed from an old tutorial.

Once the domain is configured, send from an address under that verified domain. For example:

WordPress Notifications <notifications@example.com>

Avoid sending important site mail from the visitor’s address, a free mailbox that you do not control, or a domain that has not been authenticated. Those choices can weaken alignment and make replies, bounces, and reputation management harder.

Build a secure webhook receiver

The receiver should be a small server-side application or serverless function. It accepts the WordPress event, verifies it, sanitizes the fields needed for the message, and calls Volanea. This is safer than giving WordPress automation direct possession of a broad email API key.

A receiver can run in many environments: a Node.js service, a PHP endpoint outside the public WordPress theme, a serverless function, or an edge-compatible worker that supports outbound HTTPS requests and secret storage. The implementation below uses Node.js with Express because the request flow is easy to inspect.

The example uses a pre-shared webhook secret. Your WordPress automation sends it as an X-Webhook-Secret header. For higher-risk use cases, prefer a signed request with a timestamp and HMAC, then reject old timestamps to reduce replay risk.

import express from "express";
import crypto from "node:crypto";

const app = express();
app.use(express.json({ limit: "100kb" }));

const {
  VOLANEA_API_KEY,
  WORDPRESS_WEBHOOK_SECRET,
  VOLANEA_FROM_EMAIL = "notifications@example.com",
  VOLANEA_FROM_NAME = "Example Site"
} = process.env;

function escapeHtml(value = "") {
  return String(value)
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#039;");
}

function isEmail(value) {
  return typeof value === "string" &&
    /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
}

app.post("/webhooks/wordpress", async (req, res) => {
  const suppliedSecret = req.get("X-Webhook-Secret");

  if (!suppliedSecret || !WORDPRESS_WEBHOOK_SECRET ||
      !crypto.timingSafeEqual(
        Buffer.from(suppliedSecret),
        Buffer.from(WORDPRESS_WEBHOOK_SECRET)
      )) {
    return res.status(401).json({ error: "Unauthorized webhook" });
  }

  const { event, eventId, recipient, data = {} } = req.body;
  const recipientEmail = recipient?.email;

  if (!event || !eventId || !isEmail(recipientEmail)) {
    return res.status(400).json({
      error: "event, eventId, and recipient.email are required"
    });
  }

  const firstName = escapeHtml(data.firstName || recipient?.name || "there");
  const topic = escapeHtml(data.topic || "your request");
  const message = escapeHtml(data.message || "We received your submission.")
    .replaceAll("\n", "<br>");

  const idempotencyKey = `wordpress:${event}:${eventId}:confirmation`;

  const volaneaResponse = await fetch("https://api.volanea.com/v1/send", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${VOLANEA_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": idempotencyKey
    },
    body: JSON.stringify({
      from: {
        email: VOLANEA_FROM_EMAIL,
        name: VOLANEA_FROM_NAME
      },
      to: [{
        email: recipientEmail,
        name: recipient?.name || undefined
      }],
      subject: `We received your message: ${data.topic || "Request"}`,
      html: `
        <p>Hi ${firstName},</p>
        <p>Thanks for contacting us about <strong>${topic}</strong>.</p>
        <p>We received the following message:</p>
        <blockquote>${message}</blockquote>
        <p>Our team will reply as soon as possible.</p>
      `,
      text: `Hi ${data.firstName || recipient?.name || "there"},\n\n` +
        `Thanks for contacting us about ${data.topic || "your request"}.\n\n` +
        `We received your message:\n${data.message || ""}\n\n` +
        "Our team will reply as soon as possible."
    })
  });

  const responseBody = await volaneaResponse.text();

  if (!volaneaResponse.ok) {
    console.error("Volanea send failed", {
      status: volaneaResponse.status,
      event,
      eventId,
      responseBody
    });

    return res.status(502).json({
      error: "Email provider request failed"
    });
  }

  return res.status(202).json({
    accepted: true,
    event,
    eventId
  });
});

app.listen(3000, () => {
  console.log("Webhook receiver listening on port 3000");
});

The Volanea request uses the documented REST base URL, the POST /v1/send endpoint, a secret key, and an Idempotency-Key header. The endpoint supports a single message to one recipient or up to 50 recipients; for a single WordPress event, sending to one specific recipient is usually simpler and safer.

Do not copy the simple email validator into a compliance system

The regular expression in the example is only a quick input guard. It catches obvious malformed input before your receiver calls the API. It does not prove that an address exists, is deliverable, belongs to the submitter, or is safe to add to a list.

For form collection, account onboarding, or imports, use layered controls: browser validation, server-side validation, confirmation flows where appropriate, abuse prevention, and address verification for workflows where it makes sense. You can use the free email address verification tool before importing or operationally reviewing suspicious addresses.

Send the webhook from WordPress

How you create the outbound request depends on the trigger source. Some automation products provide a generic HTTP request or webhook action; others expose custom-code hooks. The key is that the request goes to your endpoint, not directly to a browser-visible API key.

Configure the outbound request with these properties:

Method: POST
URL: https://your-service.example/webhooks/wordpress
Content-Type: application/json
X-Webhook-Secret: <stored secret>

Its request body should match the contract your endpoint expects:

{
  "event": "contact_form.submitted",
  "eventId": "4821",
  "occurredAt": "2026-08-23T14:28:00Z",
  "recipient": {
    "email": "alex@example.com",
    "name": "Alex Morgan"
  },
  "data": {
    "firstName": "Alex",
    "topic": "Implementation question",
    "message": "Can you help us with our account setup?"
  }
}

If your WordPress automation tool sends a different native payload, add a thin mapping step before the request or update the receiver’s parsing layer. Do not scatter source-specific field paths through the email-rendering code. Keeping one mapper at the boundary makes the system easier to migrate when a plugin changes its data model.

Send from custom WordPress code when no automation action exists

If the event comes from a custom plugin or theme, WordPress’s HTTP API can post the JSON directly to your receiver. This keeps the same security model: WordPress knows only the webhook secret, while the receiver owns the Volanea API key.

function example_send_transactional_event( $recipient_email, $recipient_name, $submission_id, $topic, $message ) {
    $payload = array(
        'event' => 'contact_form.submitted',
        'eventId' => (string) $submission_id,
        'occurredAt' => gmdate( 'c' ),
        'recipient' => array(
            'email' => sanitize_email( $recipient_email ),
            'name'  => sanitize_text_field( $recipient_name ),
        ),
        'data' => array(
            'firstName' => sanitize_text_field( $recipient_name ),
            'topic'     => sanitize_text_field( $topic ),
            'message'   => sanitize_textarea_field( $message ),
        ),
    );

    $response = wp_remote_post(
        'https://your-service.example/webhooks/wordpress',
        array(
            'timeout' => 10,
            'headers' => array(
                'Content-Type'     => 'application/json',
                'X-Webhook-Secret' => getenv( 'WORDPRESS_WEBHOOK_SECRET' ),
            ),
            'body' => wp_json_encode( $payload ),
        )
    );

    if ( is_wp_error( $response ) ) {
        error_log( 'Webhook delivery failed: ' . $response->get_error_message() );
        return false;
    }

    return wp_remote_retrieve_response_code( $response ) >= 200
        && wp_remote_retrieve_response_code( $response ) < 300;
}

Do not place the webhook secret in a public plugin settings screen if site administrators who do not need access can view it. Prefer environment configuration or a protected WordPress constant loaded outside version control.

Make retries safe with idempotency

Webhook delivery is not exactly-once. The sender may retry because it did not receive a response, your server may crash after sending the API request but before returning a response, or an automation platform may replay a failed run. These are normal distributed-system conditions.

An Idempotency-Key is the defense. The receiver derives a stable key from the event and message purpose, then sends the same value on every retry of that logical action. Volanea can recognize the repeated request as the same send rather than produce another message.

There are two rules that prevent most duplicate-email bugs:

  • Generate the key from stable source data, not the current time or a random UUID.
  • Change the key when you intentionally need a new message, such as sending a corrected receipt or a separate reminder.

For example, an order receipt and a shipment email for the same order should use different keys:

wordpress:order:10482:receipt
wordpress:order:10482:shipment

If you also maintain a database, store the source event ID, email purpose, idempotency key, Volanea response metadata, and final processing status. This makes support questions answerable: you can determine whether an event arrived, whether a send request was accepted, and whether the same event was retried.

Treat message content as untrusted input

A WordPress form submission can contain HTML, scripts, deceptive text, unusual Unicode, and values that try to manipulate your email layout. Even though email clients typically limit script execution, unescaped user content can still damage the appearance and meaning of a transactional message.

Use these content rules:

  1. Escape untrusted variables before placing them in HTML.
  2. Provide a plain-text alternative for every important transactional message.
  3. Use a fixed sender address from your verified domain.
  4. Add replyTo only when it supports a real reply workflow.
  5. Keep the subject line predictable and avoid putting untrusted long-form content in it.
  6. Never include passwords, full payment credentials, or other secrets in the email body.
  7. Use signed, expiring links for account actions instead of putting privileged tokens in visible text.

The example receiver escapes the submitted topic, name, and message before inserting them into HTML. For a production template, it is better to use a real template renderer that escapes by default, rather than concatenate many HTML fragments as the message grows.

Test the full delivery path

A successful code deployment does not guarantee a successful transactional email. Test the actual path from trigger to inbox before enabling it for every user.

Use a small test plan:

  1. Trigger a known test event from WordPress.
  2. Confirm your receiver logs the event ID without logging the full private message body.
  3. Confirm the receiver returns a 2xx result only after Volanea accepts the send request.
  4. Check that the received message has the correct sender name, sender domain, recipient, subject, HTML, and plain-text content.
  5. Trigger the same event again with the same event ID and confirm it does not create an unintended duplicate.
  6. Trigger an invalid payload and confirm the receiver rejects it with 400 rather than sending a malformed message.
  7. Use an invalid webhook secret and confirm the endpoint returns 401.
  8. Temporarily simulate a Volanea failure and confirm the WordPress automation can retry without creating multiple emails.

Keep development and production settings separate. A test key and test sender identity reduce the chance that a staging form sends real messages to real customers. When moving to production, change the environment variables and confirm the production sending domain is authenticated before enabling the workflow.

Monitor failures without exposing personal data

Email operations involve personal data, so logs should be useful without becoming a second mailbox full of sensitive content. Log event IDs, event types, recipient domains where appropriate, HTTP status codes, provider request IDs, idempotency keys, and error categories. Avoid routinely logging full email bodies, access tokens, API keys, or raw form submissions.

Useful failure categories include:

  • Webhook authentication failure.
  • JSON parsing failure.
  • Missing required fields.
  • Invalid recipient address format.
  • Rate limiting or temporary upstream failure.
  • Sender-domain or sender-identity configuration failure.
  • Provider validation error.
  • Unexpected response from the email API.

For temporary failures, return a non-2xx response from the receiver so the calling automation can retry if it supports retries. For permanent validation failures, return 400 and alert your team or record the problem for review. Retrying a malformed payload will not make it valid.

This distinction is a second-order benefit of the webhook pattern: WordPress stays focused on the business event, while the receiver centralizes transport-specific diagnosis and retry behavior.

When direct SMTP or wp_mail() may be a better fit

A webhook relay is not automatically the right answer for every WordPress email. If your only goal is to make all native WordPress notices—including password resets, comment moderation alerts, and plugin-generated messages—use a properly configured SMTP or API mailer that integrates at the wp_mail() layer.

Choose the webhook-to-API pattern when you need one or more of the following:

  • The event requires custom business rules before sending.
  • You want one centralized email service for WordPress and other applications.
  • You need stable idempotency across automation retries.
  • You need to transform source data into a consistent transactional template.
  • You want to avoid tying email API credentials to a collection of WordPress plugins.
  • You need a clean audit trail for event receipt, API submission, and downstream delivery handling.

Use a native mailer configuration when the message is generated by WordPress core or a plugin that simply calls wp_mail() and no event-specific transformation is required. The two patterns can coexist: configure reliable delivery for general WordPress system email, then use the webhook relay for high-value workflows with explicit business logic.

Common implementation mistakes

The most damaging mistakes are usually architectural rather than syntactic.

Calling the email API from browser JavaScript

Never expose a Volanea secret key in a page source, frontend bundle, WordPress block, or browser network request. Anyone who obtains the key could use it to send mail under your account. API keys belong in server-side secrets.

Sending from the form submitter’s address

A visitor’s address should normally be the recipient of an acknowledgment or the reply target for an internal notification—not the sender identity. Send from a verified address you control, then use replyTo when needed.

Returning success before the provider request completes

If the receiver returns 202 before it calls Volanea, a downstream failure can disappear unless you have a durable queue and a worker to process it. For a simple synchronous receiver, wait for the Volanea API response before confirming acceptance to the caller.

Using a fresh idempotency key on each retry

This turns a retry into a new email. Base the key on the original event ID and message purpose, and retain it through the retry path.

Trusting raw form input in email HTML

Escape input, enforce size limits, and keep templates under your control. A support inquiry should not be able to rewrite your confirmation email’s layout or insert misleading content.

Conclusion

To send transactional email from WordPress using Volanea, do not look for a non-existent native connector or assume there is one canonical WordPress webhook payload. Build around the real boundary: WordPress produces a business event, your server validates a small JSON contract, and your server calls Volanea’s REST API with protected credentials.

That approach is more transparent than a fragile plugin-to-plugin promise. It lets you control sender identity, template safety, retry behavior, observability, and duplicate prevention while keeping the WordPress side simple. Start with one high-value event, such as a contact-form confirmation or order receipt, test it end to end, then reuse the same receiver pattern for additional transactional workflows.

FAQ

Is there a native Volanea integration for Send Email From WordPress?

No. This guide uses a webhook/API pattern rather than claiming a native integration exists. WordPress core and WordPress plugins vary in how they create events, so the integration sends data to a receiver you control and the receiver calls Volanea.

What webhook payload does WordPress send by default?

WordPress core does not send one standard outbound webhook payload. It provides the wp_mail() PHP function for mail preparation. Form, ecommerce, membership, and automation plugins each define their own data structures, so create or map to a small JSON contract at your webhook boundary.

Why should I use an idempotency key for transactional email?

Webhook deliveries can be retried after timeouts or temporary failures. A stable Idempotency-Key lets the receiving email API identify a repeated request for the same event, helping prevent duplicate confirmations, receipts, and alerts.

Can I send every WordPress email through this webhook receiver?

You can, but it is not always necessary. Use the receiver for event-driven messages that need custom rules, mapping, or centralized controls. For general WordPress system mail generated through wp_mail(), an SMTP or API mailer at the WordPress mail layer may be simpler.

Where should I store the Volanea API key?

Store it only in a server-side environment variable, secret manager, or protected deployment configuration for the webhook receiver. Do not put it in browser code, public WordPress settings, theme files committed to source control, or a generic form field.