Files
cloudflare_temp_email/vitepress-docs/docs/en/guide/feature/send-mail-api.md
T
Dream Hunter 5dbb6107dd feat: add user send mail and sent box (#1122)
* feat: add user send mail client

* fix: align user mail navigation

* fix: shorten address credential action

* test: cover user mail ownership boundaries

* fix: address user mail review feedback

* fix: disambiguate user mail e2e heading

* fix: minimize shared sent box changes

* refactor: isolate user send mail page

* refactor: reuse bound address lookup

* fix: clarify user sent box naming

* refactor: decouple user send API from roles

* fix: align user send mail behavior

* fix: align user send role and rate limits

* test: isolate user send rate limits

* test: initialize rate limit worker database

* refactor: simplify user send rate limit

* refactor: inline user send rate limit path

* refactor: simplify user send limiter key

* refactor: keep existing rate limit behavior

* style: simplify user send rate limit condition

* style: group user send rate limit condition

* fix: bind user role token to account

* fix: keep user sender selection available
2026-08-25 14:14:42 +08:00

4.7 KiB

Send Email API

Send Email via HTTP API

There are three HTTP API endpoints for sending emails:

Endpoint Authentication Use Case
/api/send_mail Authorization: Bearer <address_JWT> header Internal calls, requires cookie / header auth
/external/api/send_mail token field in request body External system integration, no header auth needed
/user_api/address/:address_id/send_mail x-user-token: <user_JWT> header Signed-in users sending from one of their bound addresses

::: tip What is "Address JWT"? The Address JWT is the jwt field returned when creating an email address via /api/new_address or /admin/new_address. You can view it in the "Password" menu in the frontend UI. It is NOT the JWT_SECRET environment variable, nor the admin password. :::

Method 1: Header Authentication (/api/send_mail)

send_body = {
    "from_name": "Sender Name",
    "to_name": "Recipient Name",
    "to_mail": "Recipient Address",
    "subject": "Email Subject",
    "is_html": False,  # Set whether it's HTML based on content
    "content": "<Email content: html or text>",
}

res = requests.post(
    "https://your_worker_domain/api/send_mail",
    json=send_body, headers={
        "Authorization": f"Bearer {address_JWT}",
        # "x-custom-auth": "<your_website_password>", # If private site password is enabled
        "Content-Type": "application/json"
    }
)

Method 2: Body Token Authentication (/external/api/send_mail)

Suitable for external system calls, place the Address JWT in the token field of the request body:

send_body = {
    "token": "<address_JWT>",
    "from_name": "Sender Name",
    "to_name": "Recipient Name",
    "to_mail": "Recipient Address",
    "subject": "Email Subject",
    "is_html": False,  # Set whether it's HTML based on content
    "content": "<Email content: html or text>",
}
res = requests.post(
    "https://your_worker_domain/external/api/send_mail",
    json=send_body, headers={
        # "x-custom-auth": "<your_website_password>", # If private site password is enabled
        "Content-Type": "application/json"
    }
)

Method 3: User JWT (/user_api/address/:address_id/send_mail)

Obtain address_id from the paginated GET /user_api/bind_address response. The backend verifies that the address belongs to the current user; clients cannot choose an arbitrary sender address.

If the site grants unlimited sending to the current user's role through NO_LIMIT_SEND_ROLE, also send the access_token returned by GET /user_api/settings. The frontend handles this token automatically.

send_body = {
    "from_name": "Sender Name",
    "to_name": "Recipient Name",
    "to_mail": "Recipient Address",
    "subject": "Email Subject",
    "is_html": False,
    "content": "Email content",
}

res = requests.post(
    "https://your_worker_domain/user_api/address/123/send_mail",
    json=send_body,
    headers={
        "x-user-token": "<user_JWT>",
        # "x-user-access-token": "<user_access_token>",  # Required for role permissions
        "Content-Type": "application/json",
    },
)

The same user-address API group also provides:

Method Endpoint Description
GET /user_api/address/:address_id/settings Get the address and remaining send balance
POST /user_api/address/:address_id/request_send_mail_access Request send access for the address
GET /user_api/sendbox?limit=20&offset=0&address=optional-address List the current user's sent items, optionally filtered by a bound address
DELETE /user_api/sendbox/:mail_id Delete one sent item owned by the current user

All endpoints require a User JWT. Address-scoped endpoints verify that address_id is bound to the current user, while user-level sent-item endpoints only return or delete records for the user's bound addresses. The user access token is only used to apply optional role permissions.

Send Email via SMTP

Please first refer to Configure SMTP Proxy.

This is a python example using the smtplib library to send emails.

JWT Token Password: This is the email login password, which can be viewed in the password menu in the UI interface.

import smtplib

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart


with smtplib.SMTP('localhost', 8025) as smtp:
    smtp.login("jwt", "Enter your JWT token password here")
    message = MIMEMultipart()
    message['From'] = "Me <me@awsl.uk>"
    message['To'] = "Admin <admin@awsl.uk>"
    message['Subject'] = "Test Subject"
    message.attach(MIMEText("Test Content", 'html'))
    smtp.sendmail("me@awsl.uk", "admin@awsl.uk", message.as_string())