Sending Emails via API

Mailto.wiki supports sharing Confluence pages as emails via a REST API. If you have some programming knowledge, you can automate the process of sending emails and schedule recurring emails. The API offers the same features as the graphical user interface (the Email button).

This guide will walk you through the necessary steps to set up the REST API and explain how to perform the REST requests in general.

We also provide ready-to-use code snippets for Bash, PowerShell, Python, NodeJS, PHP, and Java.

Please note that these examples are for Confluence Cloud. On Confluence Server and Data Center, the REST API functions differently.

Note: In the past, there was a typo in the REST endpoint for sending emails, which resulted in it being named /snare-as-email-btn. However, for the sake of backward compatibility, we have chosen not to alter this naming convention. Please be aware that it may differ from what you expect, but the examples provided in this document are accurate.

Step 0: Ensure the “Share by Email” button is activated

To use the API for sending emails, the “Share by Email” button must be activated, which is enabled by default. Please ensure that it is activated by going to the mailto.wiki configuration page, clicking on the “Replies/Share” tab, and scrolling down to “Enable Share by Email button.” Make sure the checkbox is checked. You can find more information about the “Share by Email” button here.

Step 1: Obtain an API token

To authenticate, you will need an API token for Confluence. Please follow the instructions provided by Atlassian at https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/. Once you have obtained the API token, make a note of the token, Confluence URL, and your username for future use:

CONFLUENCE_URL='https://<your-instance-url>/wiki/'
API_TOKEN='<The api token>'
USERNAME='<The email address of your confluence user>'

Step 2: Obtain the page ID

You will need the ID for the page or blog post that you want to share via email. In Confluence, navigate to the content you want to share and retrieve the page ID from the URL.

Now that you have your API token and the page ID, you can proceed with the code snippets for your programming language below. We currently provide ready-to-use examples for Bash, PowerShell, Python, NodeJS, PHP, and Java. Alternatively, you can follow the generic description of the REST process to implement it yourself.

Step 3A: Generic description of the REST process

Get a JWT token

First, you need to use your API token to obtain a JWT token that you can use to authenticate with the mailto.wiki API. To do this, make a POST request to the endpoint https://<yourinstance.tld>/wiki/plugins/servlet/ac/mailtowiki/snare-as-email-btn. Use your Confluence user’s email address as the username and your API token as the password for basic authentication. The response from the endpoint will contain the generated JWT token.

POST /wiki/plugins/servlet/ac/mailtowiki/snare-as-email-btn HTTP/1.1
Host: <yourinstance.tld>
Accept: application/json
Authorization: Basic <base64: USERNAME:API_TOKEN>
Content-Type: application/x-www-form-urlencoded

plugin-key=mailtowiki&product-context={}&key=key=snare-as-email-btn&classifier=json

The response will be a JSON object that contains a property called “contextJwt”. This is the JWT token that you can use to authenticate against the mailto.wiki API. Please note that the token will be valid for 15 minutes, so you will need to obtain a new token for each run.

{
    [...]

    "contextJwt": "<THE JWT TOKEN>",
    
    [...]
}

Send the email

To send an email, make a POST request to the endpoint https://connect.mailto.wiki/rest/send-email, including the JWT token in the Authorization header and the email details in the request body.

The request body is a JSON object that includes the page ID, the sender’s email address (which must be one of your registered mailto.wiki addresses), and the recipients’ email addresses. You can specify up to 25 recipients at once. Additionally, you can set other options such as including comments, including attachments, and inline images.

POST /rest/send-email HTTP/1.1
Host: connect.mailto.wiki
Authorization: JWT <THE JWT TOKEN>
Content-Type: application/json

{
    "from": "<YOUR EMAIL>@mailto.wiki",
    "to": [
        "alice@example.org",
        "bob@example.org"
    ],
    "includeComments": true,
    "includeAttachments": false,
    "inlineImages": true,
    "contentId": "106332217"
}

If everything goes smoothly, you should receive a response with a status code of 200 and the following content:

{     "message": "email sent" }

Step 3B: Bash

Here is an example of how to send emails using a Bash script. To use it, you will need to have curl and sed installed:

#!/bin/bash

# Your credentials (url, username and api key) to access confluence.
CONFLUENCE_URL='https://<your-instance-url>.atlassian.net/wiki/'
USERNAME='<The email address of your confluence user>'
API_TOKEN='<The api token>'

# Extra options for sending emails
INCLUDE_COMMENTS="true" # Include comments in emails
INCLUDE_ATTACHMENTS="true" # Include attachments in emails
INLIME_IMAGES="true" # Inline images in emails

set -eu # Stop on errors

# Register error handler
set -o errtrace

function handle_error() {
  echo "[ERROR] An error occurred."
  exit 1
}

trap 'handle_error' ERR


# Share a confluence page or blog post via email.
#
# Usage:
#
# Arguments:
#   [arg1] - The page id 
#   [arg2] - The email address to send from.
#            This needs to be a @mailto.wiki address registered to your confluence.
#   [arg*] - Email addresses to send the email to.
#
#
# Example:
#    share_confluence_page_as_email 106332217 mycompany@mailto.wiki alice@example.org bob@example.org
function share_confluence_page_as_email {
    page_id="$1"
    from="$2"
    shift 2

    recipients_json='['
    glue=''
    for to in "$@"; do
        recipients_json="${recipients_json}${glue}\"${to}\""
        glue=', '
    done
    recipients_json="$recipients_json]"

    # Get the jwt token
    jwt_token="$(curl -s -f \
        -u "$USERNAME:$API_TOKEN" \
        "$CONFLUENCE_URL/plugins/servlet/ac/mailtowiki/snare-as-email-btn" \
        -X POST \
        -H 'Accept: application/json' \
        -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
        --data-raw 'plugin-key=mailtowiki&product-context=%7B%7D&key=snare-as-email-btn&classifier=json' |
        tr -d '\n'  |
        sed 's/^.*"contextJwt":\s*"//' |
        sed 's/".*$//')"

    # Send the email
    curl -s -f 'https://connect.mailto.wiki/rest/send-email' \
        -X POST \
        -H 'Content-Type: application/json' \
        -H "Authorization: JWT $jwt_token" \
        -d @- >/dev/null <<EOF
{
    "contentId": "$page_id",
    "from": "$from",
    "to": $recipients_json,
    "includeComments": $INCLUDE_COMMENTS,
    "includeAttachments": $INCLUDE_ATTACHMENTS,
    "inlineImages": $INLIME_IMAGES
}
EOF
}

page_id=12345678
from_email="mycompany@mailto.wiki"
to_emails=("alice@example.org" "bob@example.org")

echo "[INFO] sending an email for page $page_id from $from_email to ${to_emails[@]}"
share_confluence_page_as_email "$page_id" "$from_email" "${to_emails[@]}"

echo "[INFO] done"

Step 3C: PowerShell

Here is an example on how to send emails using a PowerShell script:

function Send-Email {
    param(
        [string]$ApiToken,
        [string]$ConfluenceUrl,
        [string]$ConfluenceUserEmail,
        [string]$SenderEmail,
        [string[]]$RecipientEmails,
        [string]$PageId,
        [bool]$IncludeComments = $true,
        [bool]$IncludeAttachments = $false,
        [bool]$InlineImages = $true
    )

    $jwtEndpoint = "$ConfluenceUrl/plugins/servlet/ac/mailtowiki/snare-as-email-btn"
    $sendEmailEndpoint = "https://connect.mailto.wiki/rest/send-email"

    # Get JWT token
    $headers = @{
        "Accept" = "application/json"
        "Authorization" = "Basic "+[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("$($ConfluenceUserEmail):$($ApiToken)"))
        "Content-Type" = "application/x-www-form-urlencoded"
    }

    $body = @{
        "plugin-key" = "mailtowiki"
        "product-context" = "{}"
        "key" = "snare-as-email-btn"
        "classifier" = "json"
    }

    $jwtResponse = Invoke-RestMethod -Uri $jwtEndpoint -Method Post -Headers $headers -Body $body -ErrorAction Stop

    $jwtToken = $jwtResponse.contextJwt

    # Send email
    $headers = @{
        "Authorization" = "JWT $jwtToken"
        "Content-Type" = "application/json"
    }

    $body = @{
        "from" = $senderEmail
        "to" = $recipientEmails
        "includeComments" = $includeComments
        "includeAttachments" = $includeAttachments
        "inlineImages" = $inlineImages
        "contentId" = $pageId
    } | ConvertTo-Json

    $response = Invoke-RestMethod -Uri $sendEmailEndpoint -Method Post -Headers $headers -Body $body -ErrorAction Stop

    Write-Output "Email sent"
}

# Usage example
Send-Email `
    -ConfluenceUserEmail "<The email address of your confluence user>" `
    -ConfluenceUrl "https://<your-instance-url>.atlassian.net/wiki/" `
    -ApiToken "<The api token>" `
    -SenderEmail "mycompany@mailto.wiki" `
    -RecipientEmails @("alice@example.org", "bob@example.org") `
    -PageId "106332217"

Step 3D: Python

Here is an example on how to send emails using a Python 3 script:

import http.client
import base64
import json
from urllib.parse import urlencode
from urllib.parse import urlparse

class MailtoWikiClient:
    def __init__(self, username, api_token, confluence_url):
        self.username = username
        self.api_token = api_token
        self.confluence_url = confluence_url

    def _get_jwt_token(self):
        url_parts = urlparse(self.confluence_url)
        conn = http.client.HTTPSConnection(url_parts.netloc)
        auth_string = f"{self.username}:{self.api_token}"
        auth_header = base64.b64encode(auth_string.encode()).decode()

        headers = {
            "Accept": "application/json",
            "Authorization": f"Basic {auth_header}",
            "Content-Type": "application/x-www-form-urlencoded"
        }

        data = "plugin-key=mailtowiki&product-context={}&key=key=snare-as-email-btn&classifier=json"
        conn.request("POST", f"{url_parts.path}/plugins/servlet/ac/mailtowiki/snare-as-email-btn", headers=headers, body=data)

        response = conn.getresponse()

        if response.status != 200:
            raise Exception(f"Request failed with status {response.status}")

        response_data = json.loads(response.read().decode())
        conn.close()

        jwt_token = response_data["contextJwt"]
        return jwt_token

    def _send_email(self, jwt_token, from_email, to_emails, content_id, include_comments=True, include_attachments=False, inline_images=True):
        conn = http.client.HTTPSConnection("connect.mailto.wiki")

        headers = {
            "Authorization": f"JWT {jwt_token}",
            "Content-Type": "application/json"
        }

        data = {
            "from": from_email,
            "to": to_emails,
            "includeComments": include_comments,
            "includeAttachments": include_attachments,
            "inlineImages": inline_images,
            "contentId": content_id
        }

        conn.request("POST", "/rest/send-email", headers=headers, body=json.dumps(data))

        response = conn.getresponse()
        if response.status != 200:
            try:
                response_data = json.loads(response.read().decode())
                conn.close()
                raise Exception(f"Request failed with status {response.status}: {response_data.get('error', 'Unknown error')}")
            except:
                pass

            raise Exception(f"Request failed with status {response.status}")


    def send_email(self, content_id, from_email, to_emails, include_comments=True, include_attachments=False, inline_images=True):
        jwt_token = self._get_jwt_token()
        self._send_email(jwt_token, from_email, to_emails, content_id, include_comments, include_attachments, inline_images)

# Replace these values with your own
username = "<The email address of your confluence user>"
api_token = "<The api token>"
confluence_url = "https://<your-instance-url>.atlassian.net/wiki/"
from_email = "mycompany@mailto.wiki"
to_emails = ["alice@example.org", "bob@example.org"]
content_id = "12345678"

# Create MailtoWikiClient instance
client = MailtoWikiClient(username, api_token, confluence_url)

# Send email
client.send_email(content_id, from_email, to_emails)

print("email sent")

Step 3E: NodeJS

Here is an example on how to send emails using a NodeJS script:

const https = require('https');
const querystring = require('querystring');
const { Buffer } = require('buffer');

async function main() {
    const email = '<The email address of your confluence user>';
    const apiToken = '<The api token>';
    const confluenceUrl = 'https://<your-instance-url>.atlassian.net/wiki/';
    const jwtToken = await getJwtToken(confluenceUrl, email, apiToken);

    const emailDetails = {
        from: 'mycompany@mailto.wiki',
        to: ['alice@example.org', 'bob@example.org'],
        includeComments: true,
        includeAttachments: false,
        inlineImages: true,
        contentId: '123456'
    };

    const emailResponse = await sendEmail(jwtToken, emailDetails);

    console.log("Email sent");
}

main().catch(error => {
    console.error('Error:', error.message);
});

function httpRequest(options, requestData) {
    return new Promise((resolve, reject) => {
        const req = https.request(options, res => {
            let data = '';
            res.on('data', chunk => {
                data += chunk;
            });
            res.on('end', () => {
                resolve({
                    status: res.statusCode,
                    data: data
                });
            });
        });

        req.on('error', error => {
            reject(error);
        });

        if (requestData) {
            req.write(requestData);
        }

        req.end();
    });
}

async function getJwtToken(confluenceUrl, email, apiToken) {
    const url = `${confluenceUrl}/plugins/servlet/ac/mailtowiki/snare-as-email-btn`;
    const authString = `${email}:${apiToken}`;
    const authHeader = `Basic ${Buffer.from(authString).toString('base64')}`;
    const data = querystring.stringify({
        'plugin-key': 'mailtowiki',
        'product-context': '{}',
        'key': 'snare-as-email-btn',
        'classifier': 'json'
    });

    const options = {
        method: 'POST',
        hostname: confluenceUrl.replace(/^https?:\/\//, '').split('/')[0],
        path: url,
        headers: {
            'Authorization': authHeader,
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': data.length
        }
    };

    const response = await httpRequest(options, data);

    if (response.status === 200) {
        return JSON.parse(response.data).contextJwt;
    } else {
        throw new Error('Failed to get jwt token');
    }
}

async function sendEmail(jwtToken, emailDetails) {
    const url = '/rest/send-email';
    const data = JSON.stringify(emailDetails);

    const options = {
        method: 'POST',
        hostname: 'connect.mailto.wiki',
        path: url,
        headers: {
            'Authorization': `JWT ${jwtToken}`,
            'Content-Type': 'application/json',
            'Content-Length': data.length
        }
    };

    const response = await httpRequest(options, data);

    if (response.status !== 200) {
        throw new Error('Failed to send email: ' + response.data);
    }

    return
}

Step 3F: PHP

Here is an example on how to send emails using a PHP script. To use it you will need to have the curl extension for PHP installed, which is the case on almost all common hosting providers:

<?php

class MailtoWikiException extends Exception
{
}

class MailtoWikiClient
{
    private $username;
    private $apiToken;
    private $confluenceUrl;

    public function __construct($username, $apiToken, $confluenceUrl)
    {
        $this->username = $username;
        $this->apiToken = $apiToken;
        $this->confluenceUrl = $confluenceUrl;
    }

    private function getJWTToken()
    {
        $url = "{$this->confluenceUrl}/plugins/servlet/ac/mailtowiki/snare-as-email-btn";
        $auth = base64_encode("{$this->username}:{$this->apiToken}");
        $headers = [
            'Accept: application/json',
            "Authorization: Basic {$auth}",
            'Content-Type: application/x-www-form-urlencoded'
        ];
        $data = 'plugin-key=mailtowiki&product-context={}&key=key=snare-as-email-btn&classifier=json';

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $result = curl_exec($ch);
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpcode != 200) {
            throw new MailtoWikiException('Failed to get JWT token. HTTP status: ' . $httpcode);
        }

        $response = json_decode($result, true);
        return $response['contextJwt'];
    }

    public function sendEmail(
        $pageContentId,
        $fromEmail,
        $recipients,
        $includeComments = true,
        $includeAttachments = false,
        $inlineImages = true
    ) {
        $jwtToken = $this->getJWTToken();

        $url = 'https://connect.mailto.wiki/rest/send-email';
        $headers = [
            'Authorization: JWT ' . $jwtToken,
            'Content-Type: application/json'
        ];
        $emailData = [
            'contentId' => $pageContentId,
            'from' => $fromEmail,
            'to' => $recipients,
            'includeComments' => $includeComments,
            'includeAttachments' => $includeAttachments,
            'inlineImages' => $inlineImages
        ];
        $jsonData = json_encode($emailData);

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $result = curl_exec($ch);
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpcode != 200) {
            throw new MailtoWikiException('Failed to send email. HTTP status: ' . $httpcode . ', body: ' . $result);
        }

        return json_decode($result, true);
    }
}

// Configuration
$username = '<The email address of your confluence user>';
$apiToken = '<The api token>';
$confluenceUrl = 'https://<your-instance-url>.atlassian.net/wiki/';
$pageContentId = '12345678';
$fromEmail = 'mycompany@mailto.wiki';
$recipients = ['alice@example.org', 'bob@example.org'];

try {
    $mailtoWikiClient = new MailtoWikiClient($username, $apiToken, $confluenceUrl);
    $response = $mailtoWikiClient->sendEmail($pageContentId, $fromEmail, $recipients);

    if ($response['message'] == 'email sent') {
        echo "Email sent successfully\n";
    } else {
        echo "Error: " . $response['message'] . "\n";
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

Step 3G: Java

Here is an example of how to send emails using a Java program. The code will work with Java 11 or newer without any additional dependencies. If you intend to use it in a production environment, it is recommended to refactor the buildJsonRequestBody and extractContextJwtPropertyFromJson methods to use a proper JSON library.

import java.io.StringReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;

public class MailtoWikiApi {
    private static final boolean DEFAULT_INCLUDE_COMMENTS = true;
    private static final boolean DEFAULT_INCLUDE_ATTACHMENTS = false;
    private static final boolean DEFAULT_INLINE_IMAGES = true;

    private static final String SEND_EMAIL_ENDPOINT = "https://connect.mailto.wiki/rest/send-email";

    private final HttpClient httpClient;
    private final String jwtEndpoint;
    private final String apiKey;
    private final String username;

    public MailtoWikiApi(String confluenceUrl, String apiKey, String username) {
        httpClient = HttpClient.newHttpClient();
        this.jwtEndpoint = confluenceUrl + "/plugins/servlet/ac/mailtowiki/snare-as-email-btn";
        this.apiKey = apiKey;
        this.username = username;
    }

    public static void main(String[] args) {
        String confluenceUrl = "https://<your-instance-url>.atlassian.net/wiki/";
        String username = "<The email address of your confluence user>";
        String apiKey = "<The api token>";
        MailtoWikiApi api = new MailtoWikiApi(confluenceUrl, apiKey, username);

        String from = "mycompany@mailto.wiki";
        List<String> to = List.of("alice@example.org", "bob@example.org");

        try {
            api.sendEmail("12345678", from, to);
            System.out.println("Sent email");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendEmail (String contentId, String from, List<String> to) throws Exception {
        sendEmail(contentId, from, to, DEFAULT_INCLUDE_COMMENTS, DEFAULT_INCLUDE_ATTACHMENTS, DEFAULT_INLINE_IMAGES);
    }

    private String buildJsonRequestBody(String contentId, String from, List<String> to, boolean includeComments, boolean includeAttachments,
                            boolean inlineImages) {
        // @todo
        // If you use this in a production product you propably want to replace this with a proper json library like org.json or jackson.

        String toJsonString = "[";
        String glue = "";
        for (String sender: to) {
            toJsonString += glue + "\"" + sender.replace("\"", "") + "\"";
            glue = ",";
        }
        toJsonString += "]";

        return "{" + 
            "\"from\":\"" + from.replace("\"", "") + "\"" +
            ",\"to\":" + toJsonString +
            ",\"includeComments\":" + (includeComments ? "true" : "false") +
            ",\"includeAttachments\":" + (includeAttachments ? "true" : "false") +
            ",\"contentId\":\"" + contentId.replace("\"", "") + "\"" +
        "}";
    }

    private String extractContextJwtPropertyFromJson(String json) {
        // extract the contextJwT property using a regex,
        // @todo if you use this in a production environment you propably want to use a json library for this: org.json, jackson or something else.
        return json.replace("\n", " ").replace("\r", " ").replaceFirst(".*\"contextJwt\"\s*:\s*\"", "").replaceFirst("\".*", "");
    }

    public void sendEmail(String contentId, String from, List<String> to, boolean includeComments, boolean includeAttachments,
                            boolean inlineImages) throws Exception {
        String jwtToken = getJwtToken();

        String requestBody = buildJsonRequestBody(contentId, from, to, includeComments, includeAttachments, inlineImages);

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(SEND_EMAIL_ENDPOINT))
            .header("Authorization", "JWT " + jwtToken)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(requestBody))
            .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() == 200) {

        } else {
            throw new Exception("Error sending email, status Code: " + response.statusCode() + ", body: " + response.body());
        }
    }

    private String getJwtToken() throws Exception {
        String auth = username + ":" + apiKey;
        String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(jwtEndpoint))
            .header("Authorization", "Basic " + encodedAuth)
            .header("Accept", "application/json")
            .header("Content-Type", "application/x-www-form-urlencoded")
            .POST(HttpRequest.BodyPublishers.ofString("plugin-key=mailtowiki&product-context={}&key=key=snare-as-email-btn&classifier=json"))
            .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() != 200) {
            throw new Exception("Failed to get a JWT token, status Code: " + response.statusCode() + ", body: " + response.body());
        }

        return extractContextJwtPropertyFromJson(response.body());
    }
}

Conclusion

By utilizing these code snippets, you can seamlessly integrate the functionality of sharing Confluence pages via email into your applications, build systems, and cron jobs.

If you encounter any difficulties while implementing these solutions or if you have any suggestions or questions, please don’t hesitate to reach out to our support team at support@mailto.wiki or through our Help Desk. We are always here to assist you.