Send transactional email from Jira without relying on Jira’s default notification system or a native marketplace app. The reliable pattern is simple: Jira Automation sends an HTTPS webhook when an issue changes, and your small webhook receiver turns that event into a Volanea API request.

There is an important distinction before getting into the build: Volanea does not currently offer a native “Send Email From Jira” app or a one-click Jira integration. This guide therefore does not ask you to install one. Instead, it uses Jira Cloud Automation’s native Send web request action and Volanea’s POST /v1/send endpoint—the same practical webhook-to-email architecture used when an event source can make an HTTP request but should not own email-delivery credentials.

Jira Cloud Automation can send issue data in either an Automation-format payload or a Jira-format payload, and it can also send a custom JSON body composed with smart values. The custom-body option is the best fit here because it sends only the fields your email workflow needs. (support.atlassian.com)

What you are building

The completed flow has four moving parts:

  1. A Jira Automation rule watches for a business event, such as a work item being created, moved to a status, or updated with a public comment.
  2. Jira posts a small JSON document to your HTTPS endpoint using Send web request.
  3. Your endpoint authenticates the request, validates the mapped issue fields, creates an idempotency key, and formats the email.
  4. The endpoint calls Volanea’s transactional send endpoint with your server-side API key.

That boundary matters. Jira handles the event and field selection. Your endpoint owns secret storage, recipient rules, formatting, auditing, and retry behavior. Volanea handles the sending pipeline for the resulting transactional message.

The Volanea single-message endpoint is POST /v1/send on https://api.volanea.com. It accepts a secret key through Bearer authentication and supports the Idempotency-Key header for safe retry behavior. (volanea.com)

Why use a webhook receiver instead of calling the email API straight from Jira?

You can technically configure Jira Automation to make an HTTP request directly to an external REST API. Automation rules support custom headers, so it is possible to put an Authorization: Bearer ... value in the action configuration. However, that is rarely the best production design for email.

A direct request creates several operational problems:

  • The Volanea secret is stored in Jira rule configuration instead of in your application’s secret manager.
  • The email layout becomes difficult to version, review, and test.
  • Recipient policy is mixed into workflow administration rather than application logic.
  • An accidental rule edit can expose or replace delivery credentials.
  • You have less room to validate untrusted custom fields before they appear in an email.
  • It is harder to decide whether a retry represents the same email or a genuinely new notification.

A small receiver solves these problems without adding much infrastructure. A Cloudflare Worker, serverless function, container route, or existing application endpoint is enough. The endpoint can be only a few dozen lines long, but it creates a durable security boundary: Jira only knows a webhook URL and a shared secret; only the receiver knows the Volanea API key.

Jira’s native administrative webhook facility is not the right mechanism when you need a custom authentication header. Atlassian documents that Automation rules can send custom headers, whereas the native Jira webhook approach does not provide that flexibility. (support.atlassian.com)

Choose the Jira event that should send the email

Start with the recipient’s real-world expectation, not the Jira event that is easiest to configure. A transactional message should be caused by a specific action that matters to the recipient.

Examples include:

  • A customer’s support request is created and needs an acknowledgment.
  • A support ticket moves to Waiting for customer and needs a response request.
  • A bug reaches Resolved and the reporter should receive a resolution notice.
  • A high-priority incident is created and an on-call distribution address needs an alert.
  • A Jira Service Management request gets a public comment that should be delivered to an external stakeholder.

Avoid wiring a general “work item updated” trigger directly to an email without conditions. A single ticket update may result from a status change, assignee edit, automation action, label change, or metadata refresh. Without guardrails, recipients can receive irrelevant or duplicate messages.

A strong first rule is usually one of these:

  • Work item created plus a condition limiting the rule to one project or request type.
  • Work item transitioned plus a condition for a particular destination status.
  • Comment added plus a condition that selects only customer-visible comments.
  • Field value changed plus a condition for a meaningful field and an approved new value.

Jira Automation exposes smart values such as {{issue.key}}, {{issue.summary}}, {{issue.description}}, {{issue.status.name}}, and {{issue.created}} for use in automation actions. (support.atlassian.com)

The actual Jira webhook payload shapes

“Send Email From Jira” is often used as a generic description of the workflow, but Jira Cloud Automation does not emit one universal, fixed email payload. The Send web request action gives you a choice of payload mode.

Option 1: Jira’s generated issue-data payload

If you select a generated issue-data body, Jira can post a full issue object. In Jira format, the object is wrapped in an issue property. Its shape begins like this:

{
  "issue": {
    "self": "https://sample.jira-dev.com/rest/api/2/issue/11111",
    "id": 11111,
    "key": "SP-53",
    "changelog": {
      "startAt": 0,
      "maxResults": 0,
      "total": 0,
      "histories": null
    },
    "fields": {
      "summary": "Example support request",
      "description": "The customer-visible issue description",
      "project": {
        "id": 10002,
        "key": "SP",
        "name": "New ITSM Project"
      }
    }
  }
}

In Automation format, Jira posts the issue object itself at the root rather than under issue. Both generated shapes are extensive: they can contain project metadata, field values, user data, change history information, and custom-field properties. Atlassian explicitly presents these payloads as examples of the data and format sent by the action. (support.atlassian.com)

Generated payloads are useful when your receiver needs broad issue context. But they are often excessive for a transactional email trigger. Sending fewer fields reduces accidental disclosure, makes payload logs easier to inspect, and avoids binding your integration to Jira custom-field IDs you do not need.

Option 2: A custom JSON payload — recommended

For this guide, configure Jira to send a small custom body. This is the exact payload shape your rule will send because you define it in the Send web request action:

{
  "event": "jira.issue.created",
  "issue": {
    "id": "{{issue.id}}",
    "key": "{{issue.key}}",
    "summary": "{{issue.summary.jsonEncode}}",
    "descriptionHtml": "{{issue.description.html.jsonEncode}}",
    "status": "{{issue.status.name.jsonEncode}}",
    "projectKey": "{{issue.project.key}}",
    "created": "{{issue.created}}",
    "updated": "{{issue.updated}}"
  },
  "recipient": {
    "email": "{{issue.reporter.emailAddress}}",
    "name": "{{issue.reporter.displayName.jsonEncode}}"
  }
}

This example assumes the reporter’s email address is available to the automation actor and is appropriate for your notification policy. In some Jira configurations, user email visibility and privacy settings mean an email address may not be available. If that is your situation, do not guess or fall back to a display name. Add an explicit email custom field, use a controlled customer/contact field, or resolve the recipient in your server-side integration.

The .jsonEncode calls are not decoration. Smart values can contain quotes, line breaks, ampersands, and rich text. If you place raw values into JSON, one unexpected quote can make the whole request body invalid. Atlassian specifically recommends JSON encoding rich text sent through a web request; for rendered HTML, it documents the {{issue.description.html.jsonEncode}} pattern. (support.atlassian.com)

Configure the Jira Automation rule

These instructions use Jira Cloud Automation. Exact navigation can vary slightly between project types and Jira interface updates, but the core rule components are stable.

1. Create the trigger and conditions

Open the project’s Automation area, create a rule, and choose the trigger that matches your workflow. For a straightforward confirmation email, select Work item created.

Then add conditions. A practical example is:

  • Condition: project key equals SUPPORT.
  • Condition: request type or issue type equals your external-support request type.
  • Optional condition: reporter is not empty.
  • Optional condition: the recipient-email custom field is not empty.

Conditions are where you prevent engineering issues, internal tasks, or automated child work items from being emailed as though they were customer requests.

2. Add Send web request

Add the Send web request action and configure these values:

SettingValue
Web request URLhttps://your-app.example.com/webhooks/jira-email
HTTP methodPOST
HeadersContent-Type: application/json and X-Jira-Webhook-Secret: <long-random-secret>
Web request bodyCustom data
BodyThe custom JSON payload from the previous section

Use a cryptographically random shared secret, not a memorable phrase or a project key. Store the matching value as an environment variable in the receiver. The secret identifies this specific Jira-to-email path; it is not a replacement for access control or recipient validation.

For an endpoint that accepts only Jira Automation calls, reject a request if the header is absent or does not match. Also put the endpoint behind HTTPS. Jira webhooks require secure HTTPS URLs and a valid TLS certificate for registered webhook delivery. (developer.atlassian.com)

3. Name and publish the rule

Use a name that describes both the event and recipient, such as Support request created → customer acknowledgement. A specific rule name makes the automation audit log useful six months later, when someone needs to explain why a message was sent.

Publish the rule only after the receiver is deployed and secrets are configured. Then create one deliberately safe test issue with a team-controlled recipient address.

Build the webhook receiver

The receiver below uses a standard JavaScript fetch implementation. It will run in environments with Web Fetch APIs, including many serverless runtimes. In a traditional Node.js application, expose the same logic through an Express, Fastify, Hono, or Next.js route.

The code does five important things:

  1. Checks the shared webhook secret before processing the body.
  2. Validates that Jira sent a plausible issue key and recipient address.
  3. Uses the Jira issue ID as a stable idempotency component.
  4. Escapes text values before placing them in the email’s HTML.
  5. Calls Volanea with the API key held only by the server environment.
function escapeHtml(value = "") {
  return String(value)
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#039;");
}

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

export default {
  async fetch(request, env) {
    if (request.method !== "POST") {
      return new Response("Method not allowed", { status: 405 });
    }

    const suppliedSecret = request.headers.get("X-Jira-Webhook-Secret");
    if (!suppliedSecret || suppliedSecret !== env.JIRA_WEBHOOK_SECRET) {
      return new Response("Unauthorized", { status: 401 });
    }

    let payload;
    try {
      payload = await request.json();
    } catch {
      return new Response("Invalid JSON", { status: 400 });
    }

    const issue = payload?.issue || {};
    const recipient = payload?.recipient || {};

    if (!issue.id || !issue.key || !isEmail(recipient.email)) {
      return Response.json(
        { error: "Missing issue identity or valid recipient email" },
        { status: 422 }
      );
    }

    const issueKey = escapeHtml(issue.key);
    const summary = escapeHtml(issue.summary || "Your support request");
    const status = escapeHtml(issue.status || "Created");
    const recipientName = escapeHtml(recipient.name || "there");

    // This example treats one acknowledgement per Jira issue as one send operation.
    const idempotencyKey = `jira-request-created:${issue.id}`;

    const message = {
      from: "Acme Support <support@updates.example.com>",
      to: [recipient.email],
      subject: `We received your request (${issue.key})`,
      html: `
        <h1>Thanks, ${recipientName}</h1>
        <p>We received your request and will review it shortly.</p>
        <p><strong>Reference:</strong> ${issueKey}</p>
        <p><strong>Subject:</strong> ${summary}</p>
        <p><strong>Current status:</strong> ${status}</p>
        <p>Please keep this reference in any follow-up correspondence.</p>
      `,
      text: `Thanks, ${recipient.name || "there"}.\n\n` +
        `We received your request and will review it shortly.\n` +
        `Reference: ${issue.key}\n` +
        `Subject: ${issue.summary || "Your support request"}\n` +
        `Current status: ${issue.status || "Created"}`
    };

    const volaneaResponse = await fetch("https://api.volanea.com/v1/send", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${env.VOLANEA_API_KEY}`,
        "Content-Type": "application/json",
        "Idempotency-Key": idempotencyKey
      },
      body: JSON.stringify(message)
    });

    const responseBody = await volaneaResponse.text();

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

      return new Response("Email provider request failed", {
        status: 502
      });
    }

    return Response.json({
      accepted: true,
      issueKey: issue.key,
      providerResponse: JSON.parse(responseBody)
    });
  }
};

Set JIRA_WEBHOOK_SECRET and VOLANEA_API_KEY as deployment secrets. Do not place either value in source control, an issue comment, an email template, or a Jira custom field. Volanea’s API guidance uses secret keys for authentication, and its documentation covers secure storage, rotation, and least-privilege handling for API credentials. (volanea.com)

The message object uses Volanea’s single-message API pattern: a from sender, one or more to recipients, a subject, plus HTML and text content. The endpoint can send to one address or up to 50 recipients in a single request, but a Jira event should normally send to a deliberately small, policy-approved set rather than a broad audience. (volanea.com)

For endpoint fields, templates, response formats, and supported sending options, keep the implementation aligned with the current Volanea API reference and setup guides.

Map Jira fields safely into an email

The mechanical act of inserting {{issue.summary}} into JSON is easy. The important work is deciding what should be visible outside Jira.

Treat Jira content as untrusted display data

A summary, comment, description, or custom field may contain customer input, pasted HTML-like text, personally identifiable information, credentials, internal notes, or URLs. Your receiver should assume that every field requires a policy decision.

For a customer acknowledgment, the safest fields are usually:

  • Issue key.
  • A plain-language summary.
  • A status label.
  • A link to the customer portal or support site, if the recipient is authorized to use it.
  • A controlled next-step message created by your team.

Do not automatically include every custom field. Do not include internal comments in customer email. Do not echo an entire description if it may contain diagnostics, access tokens, incident notes, employee details, or attachments.

Separate source data from presentation

The receiver should receive structured data, then create the email layout itself. That makes it possible to change the brand, footer, wording, localization, or access policy without editing every Jira rule.

At larger scale, move the inline HTML in the example to a reusable Volanea template. Store a template identifier in environment configuration or application code, pass a small set of variables, and keep Jira responsible only for event data. This prevents workflow administrators from having to edit production email markup.

Encode JSON and escape HTML are different jobs

Jira’s .jsonEncode protects the webhook body while Jira is building JSON. HTML escaping protects the email document while your receiver is building HTML. You need both when a Jira field travels from an automation rule into HTML email.

For rich text, decide whether to send plain text, rendered HTML, or a server-side sanitized subset. Rendering Jira description markup directly in an email can produce unexpected styles and links. For acknowledgment emails, plain text or a short sanitized excerpt is often the safer choice.

Idempotency: prevent duplicate emails when automation retries

An HTTP 502 or network timeout does not always mean the provider failed to accept the email. The receiver may have sent the request successfully but lost the response before it could return a success status to Jira. Retrying blindly can then produce two acknowledgments for the same ticket.

Volanea supports Idempotency-Key on transactional send requests. An idempotency key identifies one intended side effect so retries of the same operation can be handled safely instead of creating another send. (volanea.com)

The key must match the event semantics.

For one email per issue

For a single acknowledgment sent only when an issue is created, this is appropriate:

jira-request-created:<issue-id>

If Jira or your receiver retries, it retains the same key. If a separate issue is created, it has a different issue ID and therefore a different key.

For one email per transition

If an issue can enter the same status more than once, the issue ID alone is not enough. Use an event or transition identity when available, or create and persist a delivery record in your application database.

A useful pattern is:

jira-status-notice:<issue-id>:<status-name>:<issue-updated-timestamp>

Be cautious with timestamps: a later unrelated edit may change the timestamp and result in a new key. For critical workflows, persist a notification ledger keyed by issue ID, event type, recipient, and meaningful transition identifier.

Do not use recipient email alone

recipient@example.com is not an idempotency key. The same person can legitimately receive notices about many Jira issues. Likewise, do not use only issue.key if work items might be migrated or copied across environments.

Deliverability and sender-domain requirements

The email should be sent from a domain you control and have configured for Volanea. A recognizable sender identity such as Acme Support <support@updates.example.com> is better than a vague address because recipients can connect it to the support process that created the message.

Use a dedicated transactional sender identity for Jira-driven notices. It keeps operational messages distinct from promotional mail and makes inbox rules, reply handling, and reporting easier to manage. If the sender address receives replies, ensure someone—or an inbound processing workflow—actually owns that inbox.

Before going live:

  1. Authenticate the sending domain in Volanea and complete the DNS records shown for your domain.
  2. Send test messages to inboxes at more than one provider.
  3. Confirm the visible From address, subject, plain-text fallback, and links.
  4. Test a malformed recipient address and confirm your application logs the provider response without repeatedly retrying a permanent validation failure.
  5. Test a temporary provider or network failure and verify the same idempotency key is reused.

If the recipient address comes from a Jira text field, validate it before calling the sending API. For one-off checks during testing or support investigation, the email address verification tool can help catch obvious address problems before they become bounces.

Testing the integration end to end

Do not make the first production run a real customer ticket. Build a small test plan that covers event selection, payload formation, delivery, and failure behavior.

Test the custom Jira payload first

Point the Jira rule at a temporary request-inspection endpoint you control, or add safe request logging to your receiver. Create a test issue containing:

  • Quotes in the summary.
  • Newlines in the description.
  • Ampersands and angle brackets.
  • A name with punctuation or non-ASCII characters.
  • An intentionally empty optional field.

Confirm that JSON arrives validly and that descriptionHtml is a string rather than broken JSON. This is where .jsonEncode earns its place.

Test the receiver without Jira

Use a local HTTP client with a representative payload:

curl -X POST https://your-app.example.com/webhooks/jira-email \
  -H 'Content-Type: application/json' \
  -H 'X-Jira-Webhook-Secret: replace-with-test-secret' \
  --data '{
    "event":"jira.issue.created",
    "issue":{
      "id":"10001",
      "key":"SUP-42",
      "summary":"Cannot sign in",
      "status":"Open"
    },
    "recipient":{
      "email":"qa-inbox@example.com",
      "name":"QA Team"
    }
  }'

Use a separate test sender domain or a team-controlled recipient during this stage. Check that the server returns success only after Volanea accepts the request.

Test duplicate delivery deliberately

Send the exact same request twice. The receiver should produce the same Idempotency-Key both times. Then inspect Volanea delivery activity and confirm that the intended email operation is not duplicated.

Finally, test a second issue ID. It should generate a separate email because it represents a separate business event.

Common implementation mistakes

Putting the Volanea key directly in a Jira rule

This is convenient for a proof of concept but weakens secret handling. Prefer a receiver with an environment-managed key. If a direct Jira-to-API request is unavoidable for a short-lived test, rotate the key afterward and limit who can edit the automation rule.

Sending raw issue descriptions into email HTML

Issue descriptions can contain user-generated text and formatting. JSON encoding is necessary for the request body, but it does not sanitize HTML. Escape text or sanitize an allowed subset before rendering.

Triggering on every update

A broad update trigger creates noise and can become an accidental email loop. Require a particular field change, status, comment visibility, or request type.

Assuming Jira exposes every user email address

Visibility and privacy controls may prevent automation from retrieving the reporter’s address. Treat a missing address as a validation failure, not as a reason to send to an inferred or internal address.

Treating provider acceptance as inbox placement

A successful API response means the email was accepted for processing; it does not guarantee that a recipient has read it or that no downstream mailbox rule affects it. Use delivery events and message activity for operational monitoring, and keep content transactional and expected by the recipient.

Reusing one idempotency key for all messages

That suppresses legitimate sends. The key must identify one intended email operation—not your Jira project, rule name, or sender address.

When to use a direct Jira-to-Volanea request

A direct REST call from Jira Automation can be acceptable when all of the following are true:

  • The workflow is low risk.
  • Recipient addresses are hard-coded or fully controlled.
  • The message is simple and contains no sensitive issue data.
  • The team has a secure process for managing secrets in automation configuration.
  • You can use a deterministic idempotency key and inspect the automation audit log.

Even then, the webhook receiver remains the better long-term choice. It gives developers a place to enforce a recipient allowlist, map custom fields, build templates, add observability, and change providers or credentials without changing Jira automation rules.

For teams with multiple workflows, a single receiver can expose distinct routes such as /webhooks/jira/request-created, /webhooks/jira/status-changed, and /webhooks/jira/customer-comment. Each route can have its own shared secret, recipient policy, template, and idempotency strategy.

Conclusion

To send transactional email from Jira with Volanea, use Jira Cloud Automation as the event source and a secure webhook receiver as the translation layer. This is not a native app installation: Jira posts structured issue data through Send web request, your application validates and formats it, and Volanea’s REST API sends the email.

The durable version of the integration is intentionally conservative. Send only fields the recipient should see, keep the Volanea API key outside Jira, use .jsonEncode for custom webhook bodies, escape data before building HTML, and make every email-producing event idempotent. With those controls in place, Jira becomes a dependable trigger for customer acknowledgments, incident notices, resolution updates, and other transactional email workflows.

FAQ

Does Volanea have a native Send Email From Jira app?

No. This integration uses Jira Automation’s Send web request action to call your webhook receiver, which then calls Volanea’s REST API. There is no Volanea app-installation flow required or implied.

Can Jira Automation call Volanea directly?

Yes, Jira Automation can send an HTTP request with headers, but routing through your own receiver is generally safer because the Volanea API key stays in your server-side secret store and you gain validation, formatting, logging, and idempotency control.

What payload does Jira send to the webhook?

Jira Automation can send generated full issue data in Automation format or Jira format, or it can send the custom JSON body you configure. This guide recommends a compact custom body containing the issue identity, selected display fields, and recipient data.

How do I stop duplicate Jira emails?

Set an Idempotency-Key when calling Volanea. For one acknowledgment per newly created issue, use a stable value such as jira-request-created:<issue-id> and reuse it on retries.

Can I send issue attachments through this workflow?

Not automatically with the compact example in this guide. A production attachment workflow needs separate authorization, retrieval, malware scanning, size limits, and an email-provider-compatible attachment upload or link strategy. For many support messages, a secure portal link is safer than attaching Jira files directly.