mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-11-11 02:41:33 +00:00
15166 lines
511 KiB
YAML
15166 lines
511 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
description: >-
|
|
mailcow is complete e-mailing solution with advanced antispam, antivirus,
|
|
nice UI and API.
|
|
|
|
|
|
In order to use this API you have to create a API key and add your IP
|
|
address to the whitelist of allowed IPs this can be done by logging into the
|
|
Mailcow UI using your admin account, then go to Configuration > Access >
|
|
Edit administrator details > API. There you will find a collapsed API menu.
|
|
|
|
|
|
There are two types of API keys
|
|
- The read only key can only be used for all get endpoints
|
|
- The read write key can be used for all endpoints
|
|
|
|
You can create as many keys of both types as you need. Service keys
|
|
defined in mailcow.conf (API_KEY, API_KEY_READ_ONLY, API_ALLOW_FROM) are
|
|
shown in the UI, but can only be changed in mailcow.conf.
|
|
|
|
|
|
**Requests**
|
|
|
|
- `get` routes use `GET`, all other routes use `POST` (else `405`).
|
|
- `add` routes take the new object as the JSON body.
|
|
- `edit` routes take `{"items": [...], "attr": {...}}`: `items` names the
|
|
objects to change, `attr` holds the values to set.
|
|
- `delete` routes take the JSON array of the objects to delete.
|
|
- Send `Content-Type: application/json`. A body that is no valid JSON
|
|
is answered with `400`.
|
|
|
|
**Answers**
|
|
|
|
- Write routes answer with the list of messages of the call (`type`
|
|
`success`, `danger`, `warning` or `info`; `msg` is a key of the mailcow
|
|
language files, alone or with its values). A call without messages
|
|
answers `{"type": "success", "msg": "Task completed"}` or
|
|
`{"type": "error", "msg": "Cannot add item"}`. The HTTP status is 200
|
|
in both cases: check `type`.
|
|
- Read routes answer with the object or list, `{}` or `[]` when there is
|
|
nothing.
|
|
- Unknown routes answer `404` with `{"type": "error", "msg": "route not found"}`.
|
|
|
|
title: mailcow API
|
|
version: "1.0.0"
|
|
|
|
servers:
|
|
- url: /
|
|
|
|
components:
|
|
securitySchemes:
|
|
ApiKeyAuth:
|
|
type: apiKey
|
|
in: header
|
|
name: X-API-Key
|
|
schemas:
|
|
Message:
|
|
type: object
|
|
description: >-
|
|
One message of a write call, as the mailcow UI shows it. `msg` is a key
|
|
of the mailcow language files, alone or as a list with the values of its
|
|
placeholders.
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum:
|
|
- success
|
|
- danger
|
|
- warning
|
|
- info
|
|
log:
|
|
type: array
|
|
description: >-
|
|
The call that produced the message (function, action, object,
|
|
data), secrets replaced by `*`
|
|
items: {}
|
|
msg:
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items: {}
|
|
required:
|
|
- type
|
|
- msg
|
|
Messages:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Message"
|
|
TaskResult:
|
|
type: object
|
|
description: Answer of a write call that produced no message
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum:
|
|
- success
|
|
- error
|
|
msg:
|
|
type: string
|
|
examples:
|
|
- Task completed
|
|
- Cannot add item
|
|
required:
|
|
- type
|
|
- msg
|
|
Error:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
const: error
|
|
msg:
|
|
type: string
|
|
required:
|
|
- type
|
|
- msg
|
|
Domain:
|
|
type: object
|
|
description: >-
|
|
A domain. Quotas and sizes are in bytes; the `*_int` fields repeat the
|
|
value before them.
|
|
properties:
|
|
domain_name:
|
|
type: string
|
|
description: Domain name (IDN as punycode)
|
|
domain_h_name:
|
|
type: string
|
|
description: Domain name in Unicode
|
|
description:
|
|
type: string
|
|
description: Description
|
|
max_new_mailbox_quota:
|
|
type: integer
|
|
description: >-
|
|
Largest quota a new mailbox can get: the free domain quota, at most
|
|
the max. mailbox quota
|
|
def_new_mailbox_quota:
|
|
type: integer
|
|
description: Quota a new mailbox gets by default
|
|
quota_used_in_domain:
|
|
type: [string, integer]
|
|
description: Sum of the quotas of the mailboxes
|
|
bytes_total:
|
|
type: [string, integer]
|
|
description: Storage used by the mailboxes
|
|
msgs_total:
|
|
type: [string, integer]
|
|
description: Number of messages in the mailboxes
|
|
mboxes_in_domain:
|
|
type: integer
|
|
description: Number of mailboxes
|
|
mboxes_left:
|
|
type: integer
|
|
description: Mailboxes that can still be added
|
|
max_num_aliases_for_domain:
|
|
type: integer
|
|
description: Max. number of aliases
|
|
max_num_mboxes_for_domain:
|
|
type: integer
|
|
description: Max. number of mailboxes
|
|
def_quota_for_mbox:
|
|
type: integer
|
|
description: Default quota of new mailboxes
|
|
max_quota_for_mbox:
|
|
type: integer
|
|
description: Max. quota per mailbox
|
|
max_quota_for_domain:
|
|
type: integer
|
|
description: Quota of the whole domain
|
|
relayhost:
|
|
type: [string, integer]
|
|
description: ID of the sender-dependent transport, "0" = none
|
|
backupmx:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Relay domain (backup MX)
|
|
backupmx_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
gal:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Global address list in SOGo
|
|
gal_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
rl:
|
|
description: Rate limit, `false` if none
|
|
oneOf:
|
|
- $ref: "#/components/schemas/DomainRatelimit"
|
|
- type: boolean
|
|
const: false
|
|
active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Domain active
|
|
active_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
relay_all_recipients:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Relay all recipients
|
|
relay_all_recipients_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
relay_unknown_only:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Relay non-existing mailboxes only
|
|
relay_unknown_only_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
created:
|
|
type: string
|
|
description: Creation time (`YYYY-MM-DD hh:mm:ss`)
|
|
modified:
|
|
type: [string, "null"]
|
|
description: Time of the last change
|
|
aliases_in_domain:
|
|
type: [integer, string]
|
|
description: Number of aliases, including those of its alias domains
|
|
aliases_left:
|
|
type: integer
|
|
description: Aliases that can still be added
|
|
domain_admins:
|
|
type: string
|
|
description: >-
|
|
Comma-separated domain admins, `-` if none; only for admins (and
|
|
API keys)
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Tags; missing when the domain has none
|
|
DomainRatelimit:
|
|
type: object
|
|
description: Rate limit of a domain or alias domain
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: Messages per time frame
|
|
frame:
|
|
type: string
|
|
enum: [s, m, h, d]
|
|
description: Time frame (second, minute, hour, day)
|
|
DomainTemplate:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
description: Template ID
|
|
template:
|
|
type: string
|
|
description: Template name
|
|
type:
|
|
type: string
|
|
const: domain
|
|
attributes:
|
|
$ref: "#/components/schemas/DomainTemplateAttributes"
|
|
created:
|
|
type: string
|
|
description: Creation time
|
|
modified:
|
|
type: [string, "null"]
|
|
description: Time of the last change
|
|
DomainTemplateAttributes:
|
|
type: object
|
|
description: Values of a domain template as stored; quotas in bytes
|
|
properties:
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
max_num_aliases_for_domain:
|
|
type: integer
|
|
max_num_mboxes_for_domain:
|
|
type: integer
|
|
def_quota_for_mbox:
|
|
type: integer
|
|
max_quota_for_mbox:
|
|
type: integer
|
|
max_quota_for_domain:
|
|
type: integer
|
|
rl_frame:
|
|
type: string
|
|
enum: [s, m, h, d]
|
|
rl_value:
|
|
type: [string, integer]
|
|
description: Rate limit, "" = none
|
|
active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
gal:
|
|
type: integer
|
|
enum: [0, 1]
|
|
backupmx:
|
|
type: integer
|
|
enum: [0, 1]
|
|
relay_all_recipients:
|
|
type: integer
|
|
enum: [0, 1]
|
|
relay_unknown_only:
|
|
type: integer
|
|
enum: [0, 1]
|
|
dkim_selector:
|
|
type: string
|
|
key_size:
|
|
type: integer
|
|
DomainTemplateInput:
|
|
type: object
|
|
description: >-
|
|
Values of a domain template, quotas in MiB. The defaults apply when a
|
|
template is added; for edit/domain/template see there.
|
|
properties:
|
|
template:
|
|
type: string
|
|
description: Template name, unique
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
default: []
|
|
description: Tags of new domains
|
|
max_num_aliases_for_domain:
|
|
type: [integer, string]
|
|
default: 400
|
|
description: Max. number of aliases
|
|
max_num_mboxes_for_domain:
|
|
type: [integer, string]
|
|
default: 10
|
|
description: Max. number of mailboxes
|
|
def_quota_for_mbox:
|
|
type: [integer, string]
|
|
default: 3072
|
|
description: Default quota of new mailboxes in MiB
|
|
max_quota_for_mbox:
|
|
type: [integer, string]
|
|
default: 10240
|
|
description: Max. quota per mailbox in MiB
|
|
max_quota_for_domain:
|
|
type: [integer, string]
|
|
default: 10240
|
|
description: Quota of the whole domain in MiB
|
|
rl_value:
|
|
type: [integer, string]
|
|
default: ""
|
|
description: Rate limit, messages per `rl_frame`; empty = none
|
|
rl_frame:
|
|
type: string
|
|
enum: [s, m, h, d]
|
|
default: s
|
|
description: Rate limit time frame
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 1
|
|
gal:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 1
|
|
description: Global address list in SOGo
|
|
backupmx:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: Relay domain (backup MX)
|
|
relay_all_recipients:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
relay_unknown_only:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
dkim_selector:
|
|
type: string
|
|
default: dkim
|
|
description: Selector of the DKIM key of new domains
|
|
key_size:
|
|
type: [integer, string]
|
|
default: 2048
|
|
description: DKIM key size in bits of new domains
|
|
AliasDomain:
|
|
type: object
|
|
properties:
|
|
alias_domain:
|
|
type: string
|
|
description: Alias domain name
|
|
target_domain:
|
|
type: string
|
|
description: Domain the alias domain points to
|
|
parent_is_backupmx:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: The target domain is a relay domain
|
|
active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Alias domain active
|
|
active_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
rl:
|
|
description: Rate limit, `false` if none
|
|
oneOf:
|
|
- $ref: "#/components/schemas/DomainRatelimit"
|
|
- type: boolean
|
|
const: false
|
|
created:
|
|
type: string
|
|
description: Creation time
|
|
modified:
|
|
type: [string, "null"]
|
|
description: Time of the last change
|
|
DomainPolicyEntry:
|
|
type: object
|
|
properties:
|
|
object:
|
|
type: string
|
|
description: The domain or mailbox the entry belongs to
|
|
value:
|
|
type: string
|
|
description: Sender address or pattern
|
|
prefid:
|
|
type: integer
|
|
description: Entry ID (for delete/domain-policy)
|
|
DkimKey:
|
|
type: object
|
|
properties:
|
|
pubkey:
|
|
type: string
|
|
description: Public key (base64, without PEM lines)
|
|
length:
|
|
type: string
|
|
enum: ["1024", "2048", "3072", "4096", ">= 8192"]
|
|
description: Key size in bits, estimated from the public key
|
|
dkim_txt:
|
|
type: string
|
|
description: >-
|
|
Content of the DNS TXT record; split into quoted strings of 255
|
|
characters when `SPLIT_DKIM_255` is enabled
|
|
dkim_selector:
|
|
type: string
|
|
description: Selector
|
|
privkey:
|
|
type: string
|
|
description: >-
|
|
Private key in PEM format, base64-encoded, when
|
|
`SHOW_DKIM_PRIV_KEYS` is enabled, else empty
|
|
DomainSearchRequest:
|
|
type: object
|
|
description: >-
|
|
Server-side processing parameters of DataTables
|
|
(https://datatables.net/manual/server-side). Without `start` and
|
|
`length` all matching domains are answered.
|
|
properties:
|
|
draw:
|
|
type: integer
|
|
description: Request counter, answered as it is
|
|
start:
|
|
type: integer
|
|
description: Offset of the first domain
|
|
length:
|
|
type: integer
|
|
description: Number of domains, -1 = all
|
|
search:
|
|
type: object
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: Searched in all columns with `searchable` true
|
|
order:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
column:
|
|
type: integer
|
|
description: Position in `columns` (see the description of the route)
|
|
dir:
|
|
type: string
|
|
enum: [asc, desc]
|
|
columns:
|
|
type: array
|
|
description: >-
|
|
The columns of the table; the position gives the database column
|
|
(see the description of the route)
|
|
items:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: [string, integer]
|
|
description: >-
|
|
Column name of the UI; a column position makes
|
|
`search.value` of this entry filter that column
|
|
searchable:
|
|
type: [boolean, string]
|
|
description: Column takes part in the global search
|
|
orderable:
|
|
type: [boolean, string]
|
|
description: Column may be sorted by
|
|
search:
|
|
type: object
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: Filter of this column
|
|
DomainSearchResult:
|
|
type: object
|
|
properties:
|
|
draw:
|
|
type: integer
|
|
description: "`draw` of the request"
|
|
recordsTotal:
|
|
type: integer
|
|
description: Number of domains the caller can see
|
|
recordsFiltered:
|
|
type: integer
|
|
description: Number of domains that match the search
|
|
data:
|
|
type: array
|
|
description: The domains of the page
|
|
items:
|
|
$ref: "#/components/schemas/Domain"
|
|
MailboxItems:
|
|
description: One mailbox address or a list of them
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
UserAclName:
|
|
type: string
|
|
description: >-
|
|
A user ACL: what the mailbox user may do in the UI (time-limited
|
|
aliases, TLS policy, spam score, allow/deny lists, tagged mail, sync
|
|
jobs, ActiveSync and SOGo reset, Pushover, quarantine actions,
|
|
attachments, notification interval and category, app passwords,
|
|
password reset)
|
|
enum:
|
|
- spam_alias
|
|
- tls_policy
|
|
- spam_score
|
|
- spam_policy
|
|
- delimiter_action
|
|
- syncjobs
|
|
- eas_reset
|
|
- sogo_profile_reset
|
|
- pushover
|
|
- quarantine
|
|
- quarantine_attachments
|
|
- quarantine_notification
|
|
- quarantine_category
|
|
- app_passwds
|
|
- pw_reset
|
|
ProtocolAccessName:
|
|
type: string
|
|
enum:
|
|
- imap
|
|
- pop3
|
|
- smtp
|
|
- sieve
|
|
- eas
|
|
- dav
|
|
MailboxAttributes:
|
|
type: object
|
|
description: Settings of a mailbox; flags are "0" or "1"
|
|
properties:
|
|
force_pw_update:
|
|
type: [string, integer]
|
|
description: The user must change the password at the next login
|
|
force_tfa:
|
|
type: [string, integer]
|
|
description: The user must set up two-factor authentication at the next login
|
|
tls_enforce_in:
|
|
type: [string, integer]
|
|
tls_enforce_out:
|
|
type: [string, integer]
|
|
sogo_access:
|
|
type: [string, integer]
|
|
description: Login to SOGo from the UI
|
|
imap_access:
|
|
type: [string, integer]
|
|
pop3_access:
|
|
type: [string, integer]
|
|
smtp_access:
|
|
type: [string, integer]
|
|
sieve_access:
|
|
type: [string, integer]
|
|
eas_access:
|
|
type: [string, integer]
|
|
dav_access:
|
|
type: [string, integer]
|
|
relayhost:
|
|
type: [string, integer]
|
|
description: ID of the sender-dependent transport, "0" for none
|
|
shared:
|
|
type: [string, integer]
|
|
description: Shared mailbox without a login of its own
|
|
passwd_update:
|
|
type: [string, integer]
|
|
description: Time of the last password change
|
|
mailbox_format:
|
|
type: string
|
|
quarantine_notification:
|
|
type: string
|
|
enum:
|
|
- never
|
|
- hourly
|
|
- daily
|
|
- weekly
|
|
quarantine_category:
|
|
type: string
|
|
enum:
|
|
- reject
|
|
- add_header
|
|
- all
|
|
attribute_hash:
|
|
type: string
|
|
description: Hash of the template the settings came from, cleared by manual changes
|
|
recovery_email:
|
|
type: string
|
|
description: Address for password reset mails (present after it was set)
|
|
template:
|
|
type: string
|
|
description: Name of the template the mailbox was created from (if any)
|
|
Mailbox:
|
|
type: object
|
|
description: >-
|
|
Details of a mailbox. `max_new_quota`, `spam_aliases`,
|
|
`pushover_active`, `rl`, `rl_scope`, `is_relayed` and `sender_acl` are
|
|
missing in the reduced form; `tags` is missing when the mailbox has no
|
|
tags.
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Address of the mailbox
|
|
active:
|
|
type: integer
|
|
description: 1 active, 0 inactive, 2 login disabled (mail is still accepted)
|
|
active_int:
|
|
type: integer
|
|
description: Same as `active`
|
|
domain:
|
|
type: string
|
|
name:
|
|
type: string
|
|
description: Full name
|
|
local_part:
|
|
type: string
|
|
quota:
|
|
type: integer
|
|
description: Quota in bytes, 0 = unlimited
|
|
messages:
|
|
type: integer
|
|
description: Number of messages
|
|
attributes:
|
|
$ref: "#/components/schemas/MailboxAttributes"
|
|
custom_attributes:
|
|
type: [object, array]
|
|
description: Custom attributes (an empty list when there are none)
|
|
additionalProperties:
|
|
type: string
|
|
quota_used:
|
|
type: integer
|
|
description: Used bytes
|
|
percent_in_use:
|
|
type: [integer, string]
|
|
description: Used part of the quota in percent, "- " for unlimited quota
|
|
created:
|
|
type: string
|
|
modified:
|
|
type: [string, "null"]
|
|
authsource:
|
|
type: string
|
|
enum:
|
|
- mailcow
|
|
- keycloak
|
|
- generic-oidc
|
|
- ldap
|
|
percent_class:
|
|
type: string
|
|
enum:
|
|
- info
|
|
- success
|
|
- warning
|
|
- danger
|
|
description: info (unlimited), success, warning (≥ 75 %), danger (≥ 90 %)
|
|
last_imap_login:
|
|
type: integer
|
|
description: Unix time of the last IMAP login, 0 = none
|
|
last_smtp_login:
|
|
type: integer
|
|
last_pop3_login:
|
|
type: integer
|
|
last_sso_login:
|
|
type: integer
|
|
last_sogo_login:
|
|
type: integer
|
|
max_new_quota:
|
|
type: integer
|
|
description: Largest quota in bytes the mailbox may get (domain limits)
|
|
spam_aliases:
|
|
type: integer
|
|
description: Number of valid time-limited aliases
|
|
pushover_active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
rl:
|
|
description: Effective rate limit, `false` if there is none
|
|
oneOf:
|
|
- $ref: "#/components/schemas/MailboxRatelimit"
|
|
- type: boolean
|
|
const: false
|
|
rl_scope:
|
|
type: string
|
|
enum:
|
|
- mailbox
|
|
- domain
|
|
description: Whether `rl` is the mailbox's own limit or the domain limit
|
|
is_relayed:
|
|
type: integer
|
|
description: 1 if the domain is relayed (backup MX)
|
|
sender_acl:
|
|
type: array
|
|
description: Addresses and @domains the mailbox may send as (internal, set by `sender_acl`)
|
|
items:
|
|
type: string
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
MailboxAdd:
|
|
type: object
|
|
required:
|
|
- local_part
|
|
- domain
|
|
properties:
|
|
local_part:
|
|
type: string
|
|
description: Part before the @
|
|
domain:
|
|
type: string
|
|
description: Domain of the mailbox
|
|
name:
|
|
type: string
|
|
description: Full name (`<` and `>` at the ends are removed)
|
|
authsource:
|
|
type: string
|
|
enum:
|
|
- mailcow
|
|
- keycloak
|
|
- generic-oidc
|
|
- ldap
|
|
default: mailcow
|
|
description: >-
|
|
Where the user logs in; an external source is accepted only if it is
|
|
the configured identity provider, else mailcow is used
|
|
password:
|
|
type: string
|
|
format: password
|
|
description: >-
|
|
Password (authsource mailcow), checked against the password policy;
|
|
may be left empty together with `password2` for a shared mailbox
|
|
password2:
|
|
type: string
|
|
format: password
|
|
description: The password again
|
|
template:
|
|
type: [integer, string]
|
|
description: ID of the mailbox template that provides the defaults (default the first template)
|
|
quota:
|
|
type: [integer, string]
|
|
description: Quota in MiB, 0 = unlimited
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, 2, "0", "1", "2"]
|
|
description: 1 active, 0 inactive, 2 login disabled (mail is accepted)
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Tags (the first 26 are saved)
|
|
protocol_access:
|
|
type: array
|
|
description: Allowed protocols; when sent it replaces the single `*_access` fields
|
|
items:
|
|
$ref: "#/components/schemas/ProtocolAccessName"
|
|
imap_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
pop3_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
smtp_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
sieve_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
eas_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
dav_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
sogo_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Login to SOGo from the UI
|
|
force_pw_update:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Password change at the first login (always 0 for external sources)
|
|
force_tfa:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Two-factor setup at the first login (always 0 for generic-oidc)
|
|
tls_enforce_in:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
tls_enforce_out:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
relayhost:
|
|
type: [integer, string]
|
|
default: 0
|
|
description: ID of a sender-dependent transport, 0 = none
|
|
shared:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: Shared mailbox without a login of its own; members of groups open it
|
|
quarantine_notification:
|
|
type: string
|
|
enum:
|
|
- never
|
|
- hourly
|
|
- daily
|
|
- weekly
|
|
quarantine_category:
|
|
type: string
|
|
enum:
|
|
- reject
|
|
- add_header
|
|
- all
|
|
tagged_mail_handler:
|
|
type: string
|
|
enum:
|
|
- subfolder
|
|
- subject
|
|
- none
|
|
description: Handling of mail to address+tag, see `edit/delimiter_action`
|
|
acl:
|
|
type: array
|
|
description: User ACLs to grant; when sent, all others are off
|
|
items:
|
|
$ref: "#/components/schemas/UserAclName"
|
|
rl_value:
|
|
type: [integer, string]
|
|
description: Rate limit, messages per `rl_frame` (0 or empty = none)
|
|
rl_frame:
|
|
type: string
|
|
enum:
|
|
- s
|
|
- m
|
|
- h
|
|
- d
|
|
attribute_hash:
|
|
type: string
|
|
description: Internal, the hash of the template the values come from
|
|
MailboxEdit:
|
|
type: object
|
|
properties:
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, 2, "0", "1", "2"]
|
|
description: 1 active, 0 inactive, 2 login disabled (mail is accepted)
|
|
name:
|
|
type: string
|
|
description: Full name; empty keeps the current name
|
|
quota:
|
|
type: [integer, string]
|
|
description: Quota in MiB, 0 = unlimited; empty keeps the current quota
|
|
password:
|
|
type: string
|
|
format: password
|
|
description: New password (authsource mailcow only), checked against the password policy
|
|
password2:
|
|
type: string
|
|
format: password
|
|
authsource:
|
|
type: string
|
|
enum:
|
|
- mailcow
|
|
- keycloak
|
|
- generic-oidc
|
|
- ldap
|
|
description: An external source is accepted only if it is the configured identity provider
|
|
pw_recovery_email:
|
|
type: string
|
|
description: Address for password reset mails (authsource mailcow only)
|
|
force_pw_update:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
force_tfa:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
sogo_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
protocol_access:
|
|
type: array
|
|
description: Allowed protocols; when sent it replaces the single `*_access` fields
|
|
items:
|
|
$ref: "#/components/schemas/ProtocolAccessName"
|
|
imap_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
pop3_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
smtp_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
sieve_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
eas_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
dav_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
relayhost:
|
|
type: [integer, string]
|
|
description: ID of a sender-dependent transport, 0 = none
|
|
shared:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Tags to add (existing tags stay; remove them with `delete/mailbox/tag/{mailbox}`)
|
|
tagged_mail_handler:
|
|
type: string
|
|
enum:
|
|
- subfolder
|
|
- subject
|
|
- none
|
|
sender_acl:
|
|
description: >-
|
|
Replaces the internal addresses and @domains the mailbox may send
|
|
as; `*` (admins only) allows every address, `["default"]` removes
|
|
all
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
extended_sender_acl:
|
|
type: string
|
|
description: >-
|
|
Replaces the external sender addresses or domains (not hosted on
|
|
this server), separated by space, comma or semicolon
|
|
attribute_hash:
|
|
type: string
|
|
description: Internal; cleared when not sent
|
|
MailboxTemplateInput:
|
|
type: object
|
|
properties:
|
|
quota:
|
|
type: [integer, string]
|
|
default: 0
|
|
description: Quota in MiB, 0 = unlimited
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
tagged_mail_handler:
|
|
type: string
|
|
enum:
|
|
- subfolder
|
|
- subject
|
|
- none
|
|
default: none
|
|
quarantine_notification:
|
|
type: string
|
|
enum:
|
|
- never
|
|
- hourly
|
|
- daily
|
|
- weekly
|
|
default: hourly
|
|
quarantine_category:
|
|
type: string
|
|
enum:
|
|
- reject
|
|
- add_header
|
|
- all
|
|
default: reject
|
|
rl_value:
|
|
type: [integer, string]
|
|
description: Rate limit, messages per `rl_frame`
|
|
rl_frame:
|
|
type: string
|
|
enum:
|
|
- s
|
|
- m
|
|
- h
|
|
- d
|
|
default: s
|
|
force_pw_update:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
force_tfa:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
sogo_access:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, 2, "0", "1", "2"]
|
|
default: 1
|
|
tls_enforce_in:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
tls_enforce_out:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
protocol_access:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ProtocolAccessName"
|
|
description: Allowed protocols (default all)
|
|
acl:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/UserAclName"
|
|
description: User ACLs granted to new mailboxes
|
|
MailboxTemplate:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
template:
|
|
type: string
|
|
description: Name
|
|
type:
|
|
type: string
|
|
const: mailbox
|
|
attributes:
|
|
type: object
|
|
description: >-
|
|
The settings: quota in bytes, tags, tagged_mail_handler,
|
|
quarantine_notification, quarantine_category, rl_value, rl_frame,
|
|
the flags force_pw_update, force_tfa, sogo_access, active,
|
|
tls_enforce_in, tls_enforce_out, imap_access ... dav_access and one
|
|
acl_<name> flag per user ACL
|
|
additionalProperties: true
|
|
created:
|
|
type: string
|
|
modified:
|
|
type: [string, "null"]
|
|
Resource:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: Address of the resource
|
|
kind:
|
|
type: string
|
|
enum:
|
|
- location
|
|
- group
|
|
- thing
|
|
multiple_bookings:
|
|
type: integer
|
|
description: 0 always free, -1 unlimited but busy when booked, n ≥ 1 at most n bookings
|
|
description:
|
|
type: string
|
|
active:
|
|
type: integer
|
|
active_int:
|
|
type: integer
|
|
domain:
|
|
type: string
|
|
local_part:
|
|
type: string
|
|
AppPassword:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
mailbox:
|
|
type: string
|
|
domain:
|
|
type: string
|
|
password:
|
|
type: string
|
|
description: Hash of the app password
|
|
created:
|
|
type: string
|
|
modified:
|
|
type: [string, "null"]
|
|
imap_access:
|
|
type: integer
|
|
smtp_access:
|
|
type: integer
|
|
dav_access:
|
|
type: integer
|
|
eas_access:
|
|
type: integer
|
|
pop3_access:
|
|
type: integer
|
|
sieve_access:
|
|
type: integer
|
|
active:
|
|
type: integer
|
|
SieveFilter:
|
|
type: object
|
|
properties:
|
|
active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
id:
|
|
type: integer
|
|
username:
|
|
type: string
|
|
description: Mailbox
|
|
filter_type:
|
|
type: string
|
|
enum:
|
|
- prefilter
|
|
- postfilter
|
|
script_data:
|
|
type: string
|
|
description: The Sieve script
|
|
script_desc:
|
|
type: string
|
|
TimeLimitedAlias:
|
|
type: object
|
|
properties:
|
|
address:
|
|
type: string
|
|
goto:
|
|
type: string
|
|
description: Mailbox the alias delivers to
|
|
description:
|
|
type: string
|
|
validity:
|
|
type: integer
|
|
description: Unix time of expiry (0 for permanent aliases set by an edit)
|
|
created:
|
|
type: string
|
|
modified:
|
|
type: [string, "null"]
|
|
permanent:
|
|
type: integer
|
|
enum: [0, 1]
|
|
SpamPolicyEntry:
|
|
type: object
|
|
properties:
|
|
object:
|
|
type: string
|
|
description: Mailbox or domain the entry belongs to
|
|
value:
|
|
type: string
|
|
description: Sender address, domain or pattern
|
|
prefid:
|
|
type: integer
|
|
description: ID for `delete/mailbox-policy`
|
|
MailboxRatelimit:
|
|
type: object
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: Number of messages
|
|
frame:
|
|
type: string
|
|
enum:
|
|
- s
|
|
- m
|
|
- h
|
|
- d
|
|
description: Per second, minute, hour or day
|
|
SpamScore:
|
|
type: object
|
|
properties:
|
|
score:
|
|
type: string
|
|
description: '"low,high": junk folder from low, rejected from high'
|
|
LastLogin:
|
|
type: object
|
|
properties:
|
|
ui:
|
|
description: Previous successful UI login, `false` if there is none, `[]` for domain admins
|
|
oneOf:
|
|
- type: object
|
|
properties:
|
|
remote:
|
|
type: string
|
|
description: IP address
|
|
time:
|
|
type: integer
|
|
description: Unix time
|
|
- type: boolean
|
|
const: false
|
|
- type: array
|
|
maxItems: 0
|
|
sasl:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
real_rip:
|
|
type: string
|
|
description: Client IP; private and internal addresses as "Web/EAS/Internal (address)"
|
|
datetime:
|
|
type: string
|
|
service:
|
|
type: string
|
|
description: e.g. imap, smtp, pop3, SOGO, SSO, MAILCOWUI
|
|
app_password:
|
|
type: integer
|
|
description: ID of the app password used, 0 = none
|
|
app_password_name:
|
|
type: [string, "null"]
|
|
location:
|
|
type: string
|
|
description: Country code of public addresses (if known)
|
|
MailboxSearchRequest:
|
|
type: object
|
|
description: DataTables server-side request
|
|
properties:
|
|
draw:
|
|
type: integer
|
|
description: Counter, returned unchanged
|
|
start:
|
|
type: integer
|
|
description: Offset of the first row; without it all rows are returned
|
|
length:
|
|
type: integer
|
|
description: Rows per page, -1 = all
|
|
search:
|
|
type: object
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: Searched in all searchable columns (substring)
|
|
order:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
column:
|
|
type: integer
|
|
description: Column number (index in `columns`)
|
|
dir:
|
|
type: string
|
|
enum:
|
|
- asc
|
|
- desc
|
|
columns:
|
|
type: array
|
|
description: Column n of the table is `columns[n]`
|
|
items:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: [string, integer]
|
|
description: >-
|
|
Name of the column in the UI; for a filter by
|
|
`search.value` of this column only a column number selects
|
|
the column, other values filter the address
|
|
searchable:
|
|
type: [boolean, string]
|
|
description: true or "true" includes the column in the search
|
|
orderable:
|
|
type: [boolean, string]
|
|
description: true or "true" allows sorting by the column
|
|
search:
|
|
type: object
|
|
properties:
|
|
value:
|
|
type: string
|
|
description: Filter for this column only (substring)
|
|
MailboxSearchResult:
|
|
type: object
|
|
properties:
|
|
draw:
|
|
type: integer
|
|
recordsTotal:
|
|
type: integer
|
|
recordsFiltered:
|
|
type: integer
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Mailbox"
|
|
Alias:
|
|
type: object
|
|
properties:
|
|
in_primary_domain:
|
|
type: string
|
|
description: Target domain if `domain` is an alias domain, else empty
|
|
id:
|
|
type: integer
|
|
domain:
|
|
type: string
|
|
description: Domain of the address, a domain or alias domain
|
|
public_comment:
|
|
type: [string, "null"]
|
|
description: Comment shown to the users
|
|
private_comment:
|
|
type: [string, "null"]
|
|
description: Comment for administrators
|
|
goto:
|
|
type: string
|
|
description: >-
|
|
Comma-separated destination addresses, or `null@localhost`
|
|
(discard), `spam@localhost` (learn as spam), `ham@localhost` (learn
|
|
as ham)
|
|
address:
|
|
type: string
|
|
description: Alias address, `@example.org` for a catch-all
|
|
is_catch_all:
|
|
type: integer
|
|
description: 1 = catch-all of the domain
|
|
internal:
|
|
type: integer
|
|
description: 1 = only reachable from its own domain and its alias domains
|
|
active:
|
|
type: integer
|
|
description: 1 = active, 0 = inactive
|
|
active_int:
|
|
type: integer
|
|
description: Same as `active`
|
|
sogo_visible:
|
|
type: integer
|
|
description: 1 = selectable sender in SOGo
|
|
sogo_visible_int:
|
|
type: integer
|
|
description: Same as `sogo_visible`
|
|
sender_allowed:
|
|
type: integer
|
|
description: 1 = the destination mailboxes may send as this alias
|
|
group_id:
|
|
type: [integer, "null"]
|
|
description: >-
|
|
Mailbox group whose distribution address this is; such aliases can
|
|
only be changed in the group
|
|
group_name:
|
|
type: [string, "null"]
|
|
description: Name of that mailbox group
|
|
created:
|
|
type: string
|
|
description: Creation time, `YYYY-MM-DD hh:mm:ss`
|
|
modified:
|
|
type: [string, "null"]
|
|
description: Time of the last change
|
|
BccMap:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
local_dest:
|
|
type: string
|
|
description: Domain as `@example.org` or the address of a mailbox or alias
|
|
bcc_dest:
|
|
type: string
|
|
description: Address that gets the copies
|
|
active:
|
|
type: integer
|
|
description: 1 = active, 0 = inactive
|
|
type:
|
|
type: string
|
|
enum:
|
|
- sender
|
|
- rcpt
|
|
description: "`sender`: mail sent by `local_dest`; `rcpt`: mail sent to it"
|
|
created:
|
|
type: string
|
|
domain:
|
|
type: string
|
|
description: Domain of `local_dest`
|
|
modified:
|
|
type: [string, "null"]
|
|
RecipientMap:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
recipient_map_old:
|
|
type: string
|
|
description: Original recipient, an address or `@domain`
|
|
recipient_map_new:
|
|
type: string
|
|
description: New recipient, an address or `@domain`
|
|
active:
|
|
type: integer
|
|
description: 1 = active, 0 = inactive
|
|
created:
|
|
type: string
|
|
modified:
|
|
type: [string, "null"]
|
|
TlsPolicyMap:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
dest:
|
|
type: string
|
|
description: Destination
|
|
policy:
|
|
type: string
|
|
enum:
|
|
- none
|
|
- may
|
|
- encrypt
|
|
- dane
|
|
- dane-only
|
|
- fingerprint
|
|
- verify
|
|
- secure
|
|
parameters:
|
|
type: [string, "null"]
|
|
description: Space-separated `name=value` attributes, may be empty
|
|
active:
|
|
type: integer
|
|
description: 1 = active, 0 = inactive
|
|
created:
|
|
type: string
|
|
modified:
|
|
type: [string, "null"]
|
|
Relayhost:
|
|
type: object
|
|
description: A sender-dependent transport
|
|
properties:
|
|
id:
|
|
type: integer
|
|
description: The value domains and mailboxes use as `relayhost`
|
|
hostname:
|
|
type: string
|
|
description: Next hop
|
|
username:
|
|
type: string
|
|
description: SMTP user name, empty without authentication
|
|
password:
|
|
type: string
|
|
description: SMTP password in clear text
|
|
active:
|
|
type: integer
|
|
description: 1 = active, 0 = inactive
|
|
password_short:
|
|
type: string
|
|
description: First three characters of the password and `...`
|
|
used_by_domains:
|
|
type: string
|
|
description: Comma-separated domains that use the transport, may be empty
|
|
used_by_mailboxes:
|
|
type: string
|
|
description: Comma-separated mailboxes that use the transport, may be empty
|
|
Transport:
|
|
type: object
|
|
description: A transport map entry
|
|
properties:
|
|
id:
|
|
type: integer
|
|
is_mx_based:
|
|
type: integer
|
|
description: 1 = `destination` is a regular expression for MX names
|
|
destination:
|
|
type: string
|
|
nexthop:
|
|
type: string
|
|
username:
|
|
type: string
|
|
description: SMTP user name, empty without authentication
|
|
password:
|
|
type: string
|
|
description: SMTP password in clear text
|
|
active:
|
|
type: integer
|
|
description: 1 = active, 0 = inactive
|
|
password_short:
|
|
type: string
|
|
description: First three characters of the password and `...`
|
|
ForwardingHost:
|
|
type: object
|
|
properties:
|
|
host:
|
|
type: string
|
|
description: IP address or network
|
|
source:
|
|
type: string
|
|
description: What was added (host name, domain or the address itself)
|
|
keep_spam:
|
|
type: string
|
|
enum:
|
|
- "yes"
|
|
- "no"
|
|
description: "`yes` = the mail of the host is not scanned for spam"
|
|
RspamdSettingAttributes:
|
|
type: object
|
|
properties:
|
|
desc:
|
|
type: string
|
|
description: Short description
|
|
content:
|
|
type: string
|
|
description: Rule content in Rspamd settings syntax
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = the rule is handed to Rspamd
|
|
default: 0
|
|
required:
|
|
- desc
|
|
- content
|
|
RspamdSetting:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
desc:
|
|
type: string
|
|
description: Short description
|
|
content:
|
|
type: string
|
|
description: Rule content in Rspamd settings syntax
|
|
active:
|
|
type: integer
|
|
enum:
|
|
- 0
|
|
- 1
|
|
RspamdRegexMap:
|
|
type: string
|
|
description: File name of a global Rspamd regex map
|
|
enum:
|
|
- global_mime_from_blacklist.map
|
|
- global_mime_from_whitelist.map
|
|
- global_smtp_from_blacklist.map
|
|
- global_smtp_from_whitelist.map
|
|
- global_rcpt_blacklist.map
|
|
- global_rcpt_whitelist.map
|
|
- fishy_tlds.map
|
|
- bad_words.map
|
|
- bad_words_de.map
|
|
- bad_languages.map
|
|
- bulk_header.map
|
|
- bad_header.map
|
|
- monitoring_nolog.map
|
|
Preset:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: File name of the preset without `.yml`
|
|
headline:
|
|
type: string
|
|
description: Title, translated
|
|
content:
|
|
type: string
|
|
description: Rspamd settings rule or Sieve script
|
|
GlobalFilters:
|
|
type: object
|
|
properties:
|
|
prefilter:
|
|
type: string
|
|
description: Sieve script that runs before the filters of the mailboxes
|
|
postfilter:
|
|
type: string
|
|
description: Sieve script that runs after the filters of the mailboxes
|
|
MailQueueItem:
|
|
type: object
|
|
description: One message of `postqueue -j`
|
|
properties:
|
|
queue_name:
|
|
type: string
|
|
description: Queue, e.g. `active`, `deferred`, `hold`, `incoming`
|
|
queue_id:
|
|
type: string
|
|
arrival_time:
|
|
type: integer
|
|
description: Unix time
|
|
message_size:
|
|
type: integer
|
|
description: Size in bytes
|
|
forced_expire:
|
|
type: boolean
|
|
sender:
|
|
type: string
|
|
recipients:
|
|
type: array
|
|
description: Recipient addresses, with the reason of the delay in brackets if there is one
|
|
items:
|
|
type: string
|
|
QuarantineItem:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
qid:
|
|
type: string
|
|
description: Postfix queue ID of the message
|
|
subject:
|
|
type: string
|
|
virus_flag:
|
|
type: integer
|
|
description: Greater than 0 when Rspamd found a virus (`VIRUS_FOUND`)
|
|
score:
|
|
type: number
|
|
description: Rspamd score
|
|
rcpt:
|
|
type: string
|
|
description: Mailbox the item belongs to
|
|
sender:
|
|
type: string
|
|
action:
|
|
type: string
|
|
description: Rspamd action, e.g. `reject` or `add header`
|
|
created:
|
|
type: integer
|
|
description: Unix time
|
|
notified:
|
|
type: integer
|
|
description: 1 when the recipient got a notification
|
|
QuarantineItemDetails:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
qid:
|
|
type: string
|
|
description: Postfix queue ID of the message
|
|
subject:
|
|
type: string
|
|
score:
|
|
type: number
|
|
description: Rspamd score
|
|
ip:
|
|
type: string
|
|
description: IP of the sending server
|
|
action:
|
|
type: string
|
|
description: Rspamd action
|
|
symbols:
|
|
type: string
|
|
description: Rspamd symbols as JSON text
|
|
fuzzy_hashes:
|
|
type: string
|
|
description: Fuzzy hashes as JSON text
|
|
sender:
|
|
type: string
|
|
rcpt:
|
|
type: string
|
|
description: Mailbox the item belongs to
|
|
msg:
|
|
type: string
|
|
description: The raw message
|
|
domain:
|
|
type: [string, "null"]
|
|
notified:
|
|
type: integer
|
|
description: 1 when the recipient got a notification
|
|
created:
|
|
type: string
|
|
description: Time of quarantining (`YYYY-MM-DD HH:MM:SS`)
|
|
user:
|
|
type: string
|
|
description: Authenticated sender, `unknown` if none
|
|
qhash:
|
|
type: string
|
|
description: Secret of the release and delete links in the notification mails
|
|
Fail2Ban:
|
|
type: object
|
|
properties:
|
|
ban_time:
|
|
type: integer
|
|
description: Ban time in seconds
|
|
ban_time_increment:
|
|
type: boolean
|
|
description: The ban time grows with every ban of a network
|
|
max_ban_time:
|
|
type: integer
|
|
description: Maximum ban time in seconds
|
|
netban_ipv4:
|
|
type: integer
|
|
description: IPv4 prefix length that is banned
|
|
netban_ipv6:
|
|
type: integer
|
|
description: IPv6 prefix length that is banned
|
|
max_attempts:
|
|
type: integer
|
|
description: Failed logins within `retry_window` that lead to a ban
|
|
retry_window:
|
|
type: integer
|
|
description: Window in seconds for `max_attempts`
|
|
banlist_id:
|
|
type: string
|
|
description: ID of the banlist URL `/f2b-banlist?id=<banlist_id>`
|
|
manage_external:
|
|
type: integer
|
|
description: 1 = netfilter sets no rules, the banlist is for an external firewall
|
|
regex:
|
|
type: object
|
|
description: Regex filters by number
|
|
additionalProperties:
|
|
type: string
|
|
whitelist:
|
|
type: string
|
|
description: Allowlisted networks and hosts, one per line
|
|
blacklist:
|
|
type: string
|
|
description: Denylisted networks, one per line
|
|
perm_bans:
|
|
type: array
|
|
description: Permanent bans (only present when there are any)
|
|
items:
|
|
type: object
|
|
properties:
|
|
network:
|
|
type: string
|
|
ip:
|
|
type: string
|
|
active_bans:
|
|
type: array
|
|
description: Active bans (only present when there are any)
|
|
items:
|
|
type: object
|
|
properties:
|
|
queued_for_unban:
|
|
type: integer
|
|
description: 1 when the ban is about to be lifted
|
|
network:
|
|
type: string
|
|
ip:
|
|
type: string
|
|
banned_until:
|
|
type: string
|
|
description: Remaining ban time, e.g. `00h 27m 08s`
|
|
Admin:
|
|
type: object
|
|
description: An administrator account
|
|
properties:
|
|
username:
|
|
type: string
|
|
tfa_active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: 1 = two-factor authentication is active
|
|
tfa_active_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Same as `tfa_active`
|
|
active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: 1 = the account can log in
|
|
active_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Same as `active`
|
|
created:
|
|
type: string
|
|
description: Creation time (`YYYY-MM-DD hh:mm:ss`)
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
force_tfa:
|
|
type: string
|
|
enum: ["0", "1"]
|
|
description: "\"1\" = two-factor authentication must be set up at the next login"
|
|
force_pw_update:
|
|
type: string
|
|
enum: ["0", "1"]
|
|
description: "\"1\" = the password must be changed at the next login"
|
|
DomainAdmin:
|
|
type: object
|
|
description: A domain administrator account
|
|
properties:
|
|
username:
|
|
type: string
|
|
tfa_active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: 1 = two-factor authentication is active
|
|
tfa_active_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Same as `tfa_active`
|
|
active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: 1 = the account can log in
|
|
active_int:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: Same as `active`
|
|
created:
|
|
type: string
|
|
description: Creation time (`YYYY-MM-DD hh:mm:ss`)
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
force_tfa:
|
|
type: string
|
|
enum: ["0", "1"]
|
|
description: "\"1\" = two-factor authentication must be set up at the next login"
|
|
force_pw_update:
|
|
type: string
|
|
enum: ["0", "1"]
|
|
description: "\"1\" = the password must be changed at the next login"
|
|
selected_domains:
|
|
type: array
|
|
description: The domains the account administers
|
|
items:
|
|
type: string
|
|
unselected_domains:
|
|
description: All other domains, `""` if there are none
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: string
|
|
- type: string
|
|
const: ""
|
|
DomainAdminAcl:
|
|
type: string
|
|
description: >-
|
|
ACL of a domain administrator (default in brackets): `syncjobs` sync
|
|
jobs (on), `quarantine` quarantine (on), `login_as` log in as mailbox
|
|
user (on), `sogo_access` direct SOGo access of users (on),
|
|
`app_passwds` app passwords (on), `bcc_maps` BCC maps (on), `pushover`
|
|
Pushover (off), `filters` filters (on), `ratelimit` rate limits (on),
|
|
`spam_policy` spam policy (on), `extend_sender_acl` sender ACL with
|
|
external addresses (off), `unlimited_quota` unlimited mailbox quota
|
|
(off), `protocol_access` protocol access of mailboxes (on),
|
|
`smtp_ip_access` SMTP IP restrictions (on), `alias_domains` alias
|
|
domains (off), `mailbox_relayhost` relay host of mailboxes (on),
|
|
`domain_relayhost` relay host of domains (on), `domain_desc` domain
|
|
description (off), `alias_external_goto` aliases with external
|
|
destinations (on), `mailbox_groups` mailbox groups (on)
|
|
enum:
|
|
- syncjobs
|
|
- quarantine
|
|
- login_as
|
|
- sogo_access
|
|
- app_passwds
|
|
- bcc_maps
|
|
- pushover
|
|
- filters
|
|
- ratelimit
|
|
- spam_policy
|
|
- extend_sender_acl
|
|
- unlimited_quota
|
|
- protocol_access
|
|
- smtp_ip_access
|
|
- alias_domains
|
|
- mailbox_relayhost
|
|
- domain_relayhost
|
|
- domain_desc
|
|
- alias_external_goto
|
|
- mailbox_groups
|
|
ApiKey:
|
|
type: object
|
|
description: An API key
|
|
properties:
|
|
id:
|
|
type: integer
|
|
description:
|
|
type: string
|
|
description: Free text; `API_KEY` or `API_KEY_READ_ONLY` for the service keys
|
|
access:
|
|
type: string
|
|
enum:
|
|
- ro
|
|
- rw
|
|
description: "`ro`: read-only (get routes only), `rw`: read/write"
|
|
api_key:
|
|
type: string
|
|
description: The key value, sent in the `X-API-Key` header
|
|
allow_from:
|
|
type: array
|
|
description: IP addresses and networks the key may be used from
|
|
items:
|
|
type: string
|
|
skip_ip_check:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: 1 = the key may be used from any address
|
|
service:
|
|
type: integer
|
|
enum: [0, 1]
|
|
description: 1 = service key from mailcow.conf, can only be changed there
|
|
active:
|
|
type: integer
|
|
enum: [0, 1]
|
|
created:
|
|
type: [string, "null"]
|
|
modified:
|
|
type: [string, "null"]
|
|
ApiKeyAttributes:
|
|
type: object
|
|
description: Attributes of an API key for add and edit
|
|
properties:
|
|
description:
|
|
type: string
|
|
description: Free text, at most 255 characters
|
|
default: ""
|
|
access:
|
|
type: string
|
|
enum:
|
|
- ro
|
|
- rw
|
|
description: "`ro`: read-only (get routes only), `rw`: read/write. Required for a new key."
|
|
allow_from:
|
|
description: >-
|
|
IP addresses and CIDR networks the key may be used from: a list or
|
|
a string separated by spaces, commas, semicolons or newlines. An
|
|
edit replaces the list.
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
skip_ip_check:
|
|
type: [integer, string, boolean]
|
|
description: 1/true = allow the key from any address
|
|
default: 0
|
|
active:
|
|
type: [integer, string, boolean]
|
|
description: 1/true = active
|
|
default: 1
|
|
OAuth2Client:
|
|
type: object
|
|
description: An OAuth2 client of the mailcow OAuth2 server
|
|
properties:
|
|
id:
|
|
type: integer
|
|
description: ID used by the API
|
|
client_id:
|
|
type: string
|
|
description: OAuth2 client ID
|
|
client_secret:
|
|
type: string
|
|
description: OAuth2 client secret
|
|
redirect_uri:
|
|
type: string
|
|
description: Redirect (callback) URL
|
|
grant_types:
|
|
type: [string, "null"]
|
|
description: Not used
|
|
scope:
|
|
type: string
|
|
description: Always `profile`
|
|
user_id:
|
|
type: [string, "null"]
|
|
description: Not used
|
|
SyslogLogEntry:
|
|
type: object
|
|
description: A log line of a container
|
|
properties:
|
|
time:
|
|
type: string
|
|
description: Unix time
|
|
program:
|
|
type: string
|
|
description: Process that wrote the line
|
|
priority:
|
|
type: string
|
|
description: Syslog priority (`info`, `warning`, `err`, ...)
|
|
message:
|
|
type: string
|
|
AcmeLogEntry:
|
|
type: object
|
|
properties:
|
|
time:
|
|
type: string
|
|
description: Unix time
|
|
message:
|
|
type: string
|
|
ApiLogEntry:
|
|
type: object
|
|
properties:
|
|
time:
|
|
type: integer
|
|
description: Unix time
|
|
uri:
|
|
type: string
|
|
description: Request URI
|
|
method:
|
|
type: string
|
|
description: HTTP method
|
|
remote:
|
|
type: string
|
|
description: Client address
|
|
data:
|
|
type: string
|
|
description: Form data of the request (`attr`, `items`), secrets replaced by `*`
|
|
AutodiscoverLogEntry:
|
|
type: object
|
|
properties:
|
|
time:
|
|
type: integer
|
|
description: Unix time
|
|
ua:
|
|
type: string
|
|
description: User agent of the client
|
|
user:
|
|
type: string
|
|
description: Requested e-mail address
|
|
ip:
|
|
type: string
|
|
description: Client address
|
|
service:
|
|
type: string
|
|
description: Offered service (`activesync`, `imap`) or an error
|
|
CronLogEntry:
|
|
type: object
|
|
properties:
|
|
time:
|
|
type: integer
|
|
description: Unix time
|
|
priority:
|
|
type: string
|
|
task:
|
|
type: string
|
|
description: Name of the task
|
|
message:
|
|
type: string
|
|
NetfilterLogEntry:
|
|
type: object
|
|
properties:
|
|
time:
|
|
type: integer
|
|
description: Unix time
|
|
priority:
|
|
type: string
|
|
description: "`info`, `warn` or `crit` (bans)"
|
|
message:
|
|
type: string
|
|
RatelimitLogEntry:
|
|
type: object
|
|
properties:
|
|
time:
|
|
type: integer
|
|
description: Unix time
|
|
rcpt:
|
|
type: string
|
|
description: Recipients, comma separated
|
|
from:
|
|
type: string
|
|
description: Envelope sender
|
|
user:
|
|
type: string
|
|
description: Authenticated user
|
|
rl_info:
|
|
type: string
|
|
description: Rate limit that was hit, `name(hash)`
|
|
rl_name:
|
|
type: string
|
|
description: Name of the rate limit (mailbox or domain)
|
|
rl_hash:
|
|
type: string
|
|
description: Hash of the rate limit bucket (see `delete/rlhash`)
|
|
qid:
|
|
type: string
|
|
description: Postfix queue ID
|
|
ip:
|
|
type: string
|
|
description: Client address
|
|
message_id:
|
|
type: string
|
|
header_subject:
|
|
type: string
|
|
header_from:
|
|
type: string
|
|
RspamdHistoryEntry:
|
|
type: object
|
|
description: A message scanned by Rspamd (fields of Rspamd's history)
|
|
properties:
|
|
unix_time:
|
|
type: integer
|
|
time_real:
|
|
type: number
|
|
description: Scan time in seconds
|
|
score:
|
|
type: number
|
|
required_score:
|
|
type: number
|
|
action:
|
|
type: string
|
|
description: "`no action`, `greylist`, `add header`, `rewrite subject`, `soft reject` or `reject`"
|
|
thresholds:
|
|
type: object
|
|
additionalProperties:
|
|
type: number
|
|
ip:
|
|
type: string
|
|
user:
|
|
type: string
|
|
description: Authenticated user, `unknown` for incoming mail
|
|
sender_smtp:
|
|
type: string
|
|
sender_mime:
|
|
type: string
|
|
rcpt_smtp:
|
|
type: array
|
|
items:
|
|
type: string
|
|
rcpt_mime:
|
|
type: array
|
|
items:
|
|
type: string
|
|
subject:
|
|
type: string
|
|
message-id:
|
|
type: string
|
|
size:
|
|
type: integer
|
|
is_skipped:
|
|
type: boolean
|
|
symbols:
|
|
type: object
|
|
description: Matched symbols by name
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
score:
|
|
type: number
|
|
metric_score:
|
|
type: number
|
|
description:
|
|
type: string
|
|
options:
|
|
type: array
|
|
items:
|
|
type: string
|
|
additionalProperties: true
|
|
RspamdStats:
|
|
type: object
|
|
description: Statistics of Rspamd's controller (`/stat`)
|
|
properties:
|
|
version:
|
|
type: string
|
|
config_id:
|
|
type: string
|
|
uptime:
|
|
type: integer
|
|
description: Seconds
|
|
read_only:
|
|
type: boolean
|
|
scanned:
|
|
type: integer
|
|
learned:
|
|
type: integer
|
|
actions:
|
|
type: object
|
|
description: Number of messages per action
|
|
additionalProperties:
|
|
type: integer
|
|
scan_times:
|
|
type: array
|
|
items:
|
|
type: [number, "null"]
|
|
spam_count:
|
|
type: integer
|
|
ham_count:
|
|
type: integer
|
|
connections:
|
|
type: integer
|
|
control_connections:
|
|
type: integer
|
|
total_learns:
|
|
type: integer
|
|
statfiles:
|
|
type: array
|
|
description: Bayes statistics
|
|
items:
|
|
type: object
|
|
fuzzy_hashes:
|
|
type: object
|
|
additionalProperties:
|
|
type: integer
|
|
additionalProperties: true
|
|
SaslLogEntry:
|
|
type: object
|
|
properties:
|
|
service:
|
|
type: string
|
|
description: "`imap`, `pop3`, `smtp`, `sieve`, `SSO` (SOGo), ..."
|
|
app_password:
|
|
type: integer
|
|
description: ID of the app password used, 0 = the mailbox password
|
|
username:
|
|
type: string
|
|
real_rip:
|
|
type: string
|
|
description: Client address
|
|
datetime:
|
|
type: string
|
|
description: Time of the last login (`YYYY-MM-DD hh:mm:ss`)
|
|
UiLogEntry:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
task:
|
|
type: string
|
|
description: ID of the request
|
|
type:
|
|
type: string
|
|
description: "`success`, `danger`, `warning` or `info`"
|
|
msg:
|
|
type: string
|
|
description: The message (JSON)
|
|
call:
|
|
type: string
|
|
description: The call that produced it (JSON)
|
|
user:
|
|
type: string
|
|
description: Account (`API` for API keys)
|
|
role:
|
|
type: string
|
|
remote:
|
|
type: string
|
|
description: Client address
|
|
time:
|
|
type: integer
|
|
description: Unix time
|
|
WatchdogLogEntry:
|
|
type: object
|
|
properties:
|
|
time:
|
|
type: string
|
|
description: Unix time
|
|
service:
|
|
type: string
|
|
description: Checked service
|
|
lvl:
|
|
type: string
|
|
description: Health in percent
|
|
hpnow:
|
|
type: string
|
|
description: Current health points
|
|
hptotal:
|
|
type: string
|
|
description: Maximum health points
|
|
hpdiff:
|
|
type: string
|
|
description: Change since the last check
|
|
ContainerStatus:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
const: info
|
|
container:
|
|
type: string
|
|
description: Service name
|
|
state:
|
|
type: string
|
|
description: Docker state (`running`, `exited`, `restarting`, ...)
|
|
started_at:
|
|
type: string
|
|
description: Start time (RFC 3339)
|
|
image:
|
|
type: string
|
|
HostStats:
|
|
type: object
|
|
properties:
|
|
cpu:
|
|
type: object
|
|
properties:
|
|
cores:
|
|
type: integer
|
|
usage:
|
|
type: number
|
|
description: CPU usage in percent
|
|
memory:
|
|
type: object
|
|
properties:
|
|
total:
|
|
type: integer
|
|
description: Bytes
|
|
usage:
|
|
type: number
|
|
description: Memory usage in percent
|
|
swap:
|
|
type: array
|
|
description: Swap total, used, free (bytes), used percent, swapped in, swapped out (bytes)
|
|
items:
|
|
type: number
|
|
uptime:
|
|
type: number
|
|
description: Seconds since boot
|
|
system_time:
|
|
type: string
|
|
description: Host time (`DD.MM.YYYY hh:mm:ss`)
|
|
architecture:
|
|
type: string
|
|
PasswordPolicy:
|
|
type: object
|
|
description: Password policy; the values are strings, `false` if never saved
|
|
properties:
|
|
length:
|
|
type: [string, boolean]
|
|
description: Minimum length
|
|
chars:
|
|
type: [string, boolean]
|
|
description: "\"1\": at least one letter"
|
|
special_chars:
|
|
type: [string, boolean]
|
|
description: "\"1\": at least one character that is no letter or digit"
|
|
lowerupper:
|
|
type: [string, boolean]
|
|
description: "\"1\": lowercase and uppercase letters"
|
|
numbers:
|
|
type: [string, boolean]
|
|
description: "\"1\": at least one digit"
|
|
MailboxGroupAttributes:
|
|
type: object
|
|
description: >-
|
|
Attributes of a mailbox group. Flags take `1`, `true`, `on` or `yes`
|
|
for on, anything else is off. Lists take a JSON array or a string
|
|
separated by spaces, commas, semicolons or newlines; entries are
|
|
lowercased.
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: 1-100 characters, unique in the domain
|
|
description:
|
|
type: string
|
|
description: Max. 255 characters
|
|
default: ""
|
|
address:
|
|
type: string
|
|
description: >-
|
|
Distribution address in the domain of the group (must not be used
|
|
by a mailbox, alias or spam alias); empty = no address. Wins over
|
|
`local_part`.
|
|
local_part:
|
|
type: string
|
|
description: Local part of the address in the domain of the group; empty = no address
|
|
members:
|
|
type:
|
|
- array
|
|
- string
|
|
items:
|
|
type: string
|
|
description: >-
|
|
Mailboxes (regular mailboxes, any domain the caller manages);
|
|
replaces the manual members the caller may access
|
|
add_members:
|
|
type:
|
|
- array
|
|
- string
|
|
items:
|
|
type: string
|
|
description: Mailboxes to add
|
|
remove_members:
|
|
type:
|
|
- array
|
|
- string
|
|
items:
|
|
type: string
|
|
description: Manual members to remove
|
|
send_as:
|
|
type:
|
|
- array
|
|
- string
|
|
items:
|
|
type: string
|
|
description: >-
|
|
Replaces the addresses the members may send as: existing mailbox or
|
|
alias addresses (not the group address, see `sender_allowed`) or
|
|
`@domain` for a domain or alias domain
|
|
sender_allowed:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: Members may send as the group address
|
|
default: 0
|
|
sogo_visible:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: Offer the group address as identity in SOGo (only with `sender_allowed`)
|
|
default: 0
|
|
internal:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: Only senders of the domain may write to the group address
|
|
default: 0
|
|
active:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
default: 1
|
|
imap_grants:
|
|
description: >-
|
|
Replaces the mailboxes the members may open (Dovecot ACL on every
|
|
folder, shown as Shared/<mailbox>); the caller needs access to every
|
|
owner. `subscribe` = a cron subscribes the folders for every member
|
|
once (within 15 minutes). A JSON string of the list is accepted too.
|
|
type:
|
|
- array
|
|
- string
|
|
items:
|
|
type: object
|
|
required:
|
|
- owner
|
|
properties:
|
|
owner:
|
|
type: string
|
|
description: Mailbox to share
|
|
rights:
|
|
type: string
|
|
description: >-
|
|
read = lookup, read, write-seen; write = also write,
|
|
write-deleted, insert, post, expunge, create; full = also delete
|
|
enum:
|
|
- read
|
|
- write
|
|
- full
|
|
default: read
|
|
subscribe:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
default: 0
|
|
sogo_grants:
|
|
description: >-
|
|
Replaces the SOGo folders shared with the members; the caller needs
|
|
access to every owner. Pending until the owner opened SOGo once.
|
|
`subscribe` = a cron subscribes every member once. A JSON string of
|
|
the list is accepted too.
|
|
type:
|
|
- array
|
|
- string
|
|
items:
|
|
type: object
|
|
required:
|
|
- owner
|
|
properties:
|
|
owner:
|
|
type: string
|
|
description: Mailbox whose folder is shared
|
|
type:
|
|
type: string
|
|
enum:
|
|
- Calendar
|
|
- Contacts
|
|
default: Calendar
|
|
folder:
|
|
type: string
|
|
description: SOGo folder id (`A-Za-z0-9._-`, max. 100 characters)
|
|
default: personal
|
|
access:
|
|
type: string
|
|
enum:
|
|
- read
|
|
- write
|
|
default: read
|
|
subscribe:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
default: 0
|
|
template_id:
|
|
type:
|
|
- integer
|
|
- string
|
|
- "null"
|
|
description: >-
|
|
Admins only: id of a mailbox template applied to the members;
|
|
null, empty or 0 = none
|
|
priority:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: >-
|
|
Admins only: -1000000 to 1000000; of several groups with a
|
|
template the one with the highest priority wins
|
|
default: 0
|
|
idp_ref:
|
|
type: string
|
|
description: >-
|
|
Admins only: id of the Identity Provider group whose members the
|
|
identity sync keeps in the group (max. 255 characters); empty =
|
|
none
|
|
MailboxGroup:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
domain:
|
|
type: string
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
address:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: Distribution address, null = none
|
|
sender_allowed:
|
|
type: integer
|
|
enum:
|
|
- 0
|
|
- 1
|
|
sogo_visible:
|
|
type: integer
|
|
enum:
|
|
- 0
|
|
- 1
|
|
internal:
|
|
type: integer
|
|
enum:
|
|
- 0
|
|
- 1
|
|
template_id:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
template:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: Name of the template
|
|
priority:
|
|
type: integer
|
|
idp_ref:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: Identity Provider group id, set = members are synced
|
|
members:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
source:
|
|
type: string
|
|
description: manual = added in mailcow, idp = added by the identity sync
|
|
enum:
|
|
- manual
|
|
- idp
|
|
send_as:
|
|
type: array
|
|
description: Addresses and `@domain` entries the members may send as
|
|
items:
|
|
type: string
|
|
imap_grants:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
owner:
|
|
type: string
|
|
rights:
|
|
type: string
|
|
enum:
|
|
- read
|
|
- write
|
|
- full
|
|
subscribe:
|
|
type: integer
|
|
enum:
|
|
- 0
|
|
- 1
|
|
state:
|
|
type: string
|
|
description: pending until Dovecot has the ACL, failed when setting it failed (retried by a cron)
|
|
enum:
|
|
- pending
|
|
- applied
|
|
- failed
|
|
last_error:
|
|
type:
|
|
- string
|
|
- "null"
|
|
sogo_grants:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
owner:
|
|
type: string
|
|
type:
|
|
type: string
|
|
enum:
|
|
- Calendar
|
|
- Contacts
|
|
folder:
|
|
type: string
|
|
access:
|
|
type: string
|
|
enum:
|
|
- read
|
|
- write
|
|
subscribe:
|
|
type: integer
|
|
enum:
|
|
- 0
|
|
- 1
|
|
state:
|
|
type: string
|
|
description: pending (`last_error` folder_missing) until the SOGo folder of the owner exists
|
|
enum:
|
|
- pending
|
|
- applied
|
|
- failed
|
|
last_error:
|
|
type:
|
|
- string
|
|
- "null"
|
|
active:
|
|
type: integer
|
|
enum:
|
|
- 0
|
|
- 1
|
|
created:
|
|
type:
|
|
- string
|
|
- "null"
|
|
modified:
|
|
type:
|
|
- string
|
|
- "null"
|
|
can_edit:
|
|
type: boolean
|
|
description: The caller may change the group (false for read-only API keys)
|
|
MailboxGroupMemberships:
|
|
type: object
|
|
properties:
|
|
groups:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
domain:
|
|
type: string
|
|
name:
|
|
type: string
|
|
address:
|
|
type:
|
|
- string
|
|
- "null"
|
|
sender_allowed:
|
|
type: integer
|
|
active:
|
|
type: integer
|
|
priority:
|
|
type: integer
|
|
template:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source:
|
|
type: string
|
|
enum:
|
|
- manual
|
|
- idp
|
|
template:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: Effective group template of the mailbox
|
|
send_as:
|
|
type: array
|
|
description: Addresses the mailbox may send as through its active groups
|
|
items:
|
|
type: string
|
|
SyncJobAttributes:
|
|
type: object
|
|
description: >-
|
|
Attributes of a sync job. Flags are cast to integers: `1`, `"1"` and
|
|
`true` are on, `0`, `"0"`, `false` (and the string `"true"`) are off;
|
|
on add they default to off. The former connection attributes `host1`,
|
|
`port1`, `enc1` and `authmech1` are ignored (see `source_id`).
|
|
properties:
|
|
source_id:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: >-
|
|
Id of an active sync source the caller may see
|
|
(`GET /api/v1/get/syncjob_source/all`)
|
|
user1:
|
|
type: string
|
|
description: Remote username at the source, max. 255 characters
|
|
password1:
|
|
type: string
|
|
format: password
|
|
description: >-
|
|
Remote password; required unless the source uses XOAUTH2 (ignored
|
|
then); empty on edit = keep
|
|
mins_interval:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: Minutes between runs, 1-43800
|
|
subfolder2:
|
|
type: string
|
|
description: Folder in the local mailbox to sync into, empty = none
|
|
default: ""
|
|
exclude:
|
|
type: string
|
|
description: Regular expression of remote folders to skip
|
|
default: ""
|
|
maxage:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: Only sync messages up to this age in days (1-32000), 0 = all
|
|
default: 0
|
|
maxbytespersecond:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: >-
|
|
Bandwidth limit in bytes/s (1-125000000), 0 = unlimited; the global
|
|
limit of `edit/imapsync_settings` caps it
|
|
default: 0
|
|
timeout1:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: Timeout of the remote connection in seconds (1-32000)
|
|
default: 600
|
|
timeout2:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: Timeout of the local connection in seconds (1-32000)
|
|
default: 600
|
|
custom_params:
|
|
type: array
|
|
description: >-
|
|
Extra imapsync options, replaces the stored list; empty list, empty
|
|
string or null = none. Each option must be allowed by
|
|
`GET /api/v1/get/syncjob_options`: `true` needs a value, `false`
|
|
must have none, a string is the regular expression the value must
|
|
match. Max. 100 options, values max. 1000 characters, each value is
|
|
passed as one argument.
|
|
items:
|
|
$ref: "#/components/schemas/SyncJobCustomParam"
|
|
delete2duplicates:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: Delete duplicates in the local mailbox (--delete2duplicates)
|
|
delete1:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: Delete messages at the source after they were synced (--delete1)
|
|
delete2:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: Delete local messages that are not at the source (--delete2)
|
|
automap:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: Map special folders like "Sent Items" to their local counterparts (--automap)
|
|
skipcrossduplicates:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: Skip duplicates across folders, first come first served (--skipcrossduplicates)
|
|
subscribeall:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: Subscribe all folders (--subscribeall)
|
|
dry:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: Dry run, change nothing (--dry)
|
|
active:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: The job runs; a new job without `active` is inactive
|
|
default: 0
|
|
SyncJobCustomParam:
|
|
type: object
|
|
required:
|
|
- o
|
|
properties:
|
|
o:
|
|
type: string
|
|
description: Option name, case-insensitive, leading dashes are removed
|
|
example: folder
|
|
v:
|
|
type: string
|
|
description: Value, empty for flags
|
|
default: ""
|
|
example: INBOX
|
|
SyncJob:
|
|
type: object
|
|
description: A sync job; the remote password is never returned.
|
|
properties:
|
|
id:
|
|
type: integer
|
|
user2:
|
|
type: string
|
|
description: Local mailbox
|
|
user1:
|
|
type: string
|
|
description: Remote username
|
|
source_id:
|
|
type: integer
|
|
subfolder2:
|
|
type: string
|
|
exclude:
|
|
type: string
|
|
maxage:
|
|
type: integer
|
|
mins_interval:
|
|
type: integer
|
|
maxbytespersecond:
|
|
type: string
|
|
description: Bytes/s as text, "0" = unlimited
|
|
timeout1:
|
|
type: integer
|
|
timeout2:
|
|
type: integer
|
|
custom_params:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: 'JSON text of the option list, e.g. `[{"o":"folder","v":"INBOX"}]`'
|
|
custom_params_legacy:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: Free-text options of jobs from before the allowlist, not used by the runner
|
|
delete2duplicates:
|
|
type: integer
|
|
delete1:
|
|
type: integer
|
|
delete2:
|
|
type: integer
|
|
automap:
|
|
type: integer
|
|
skipcrossduplicates:
|
|
type: integer
|
|
subscribeall:
|
|
type: integer
|
|
dry:
|
|
type: integer
|
|
active:
|
|
type: integer
|
|
regextrans2:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: Legacy column, read-only
|
|
authmd51:
|
|
type: integer
|
|
description: Legacy column, read-only
|
|
domain2:
|
|
type: string
|
|
description: Legacy column, read-only
|
|
is_running:
|
|
type: integer
|
|
last_run:
|
|
type:
|
|
- string
|
|
- "null"
|
|
success:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
description: Result of the last run (1 = imapsync exited with 0), null = not run yet
|
|
exit_status:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: Exit status name of imapsync, e.g. EX_OK
|
|
prio:
|
|
type: integer
|
|
description: Queue priority, higher runs first
|
|
created:
|
|
type:
|
|
- string
|
|
- "null"
|
|
modified:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source_name:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source_description:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source_host:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source_port:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
source_enc:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source_auth_type:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source_created_by:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source_scope:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source_oauth_flow:
|
|
type:
|
|
- string
|
|
- "null"
|
|
source_active:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
source_oauth_token_expires:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
description: Expiry (Unix time) of the token of a client_credentials source
|
|
source_oauth_last_refresh_error:
|
|
type:
|
|
- string
|
|
- "null"
|
|
user_token_expires:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
description: Expiry (Unix time) of the sign-in token of an authorization_code source
|
|
user_token_error:
|
|
type:
|
|
- string
|
|
- "null"
|
|
user_token_exists:
|
|
type: integer
|
|
description: 1 = a sign-in token exists for (source, local mailbox, user1)
|
|
log:
|
|
type: string
|
|
description: Output of the last run; empty with `no_log`
|
|
SyncJobSourceAttributes:
|
|
type: object
|
|
description: >-
|
|
Attributes of a sync source; on edit, attributes that are not sent keep
|
|
their value.
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: 1-100 characters, unique per creator
|
|
description:
|
|
type: string
|
|
description: Max. 255 characters
|
|
default: ""
|
|
host:
|
|
type: string
|
|
description: IMAP server, host name or IP address (`host1` is accepted too)
|
|
port:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: 1-65535 (`port1` is accepted too)
|
|
enc:
|
|
type: string
|
|
description: TLS = STARTTLS (`enc1` is accepted too)
|
|
enum:
|
|
- TLS
|
|
- SSL
|
|
- PLAIN
|
|
default: TLS
|
|
verify_cert:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: Verify the server certificate; `0`, `"0"`, `false` or empty = no
|
|
default: 1
|
|
auth_type:
|
|
type: string
|
|
description: >-
|
|
PLAIN, LOGIN and CRAM-MD5 use the password of each job, XOAUTH2 an
|
|
OAuth2 token. Users cannot create or edit XOAUTH2 sources, but may
|
|
use the ones they see.
|
|
enum:
|
|
- PLAIN
|
|
- LOGIN
|
|
- CRAM-MD5
|
|
- XOAUTH2
|
|
default: PLAIN
|
|
active:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: 1 = usable for jobs (cast to integer)
|
|
default: 1
|
|
scope:
|
|
type: string
|
|
description: >-
|
|
Who may use the source: `all` (admins only), `domain` (the
|
|
`domains`), `user` (the `users`; none = only the creator). Sources
|
|
of users and client_credentials sources are always `user` without
|
|
targets. On edit the targets only change when `scope` is sent.
|
|
enum:
|
|
- all
|
|
- domain
|
|
- user
|
|
default: user
|
|
domains:
|
|
type: array
|
|
description: Domains for scope `domain` (at least one), the caller must manage them
|
|
items:
|
|
type: string
|
|
users:
|
|
type: array
|
|
description: Mailboxes for scope `user`, the caller must have access to them
|
|
items:
|
|
type: string
|
|
oauth_flow:
|
|
type: string
|
|
description: >-
|
|
XOAUTH2 grant: client_credentials = one token of the source for all
|
|
mailboxes of the tenant; authorization_code = every mailbox owner
|
|
signs in once in the mailcow UI (redirect URI
|
|
`https://<MAILCOW_HOSTNAME>/syncjob-oauth`)
|
|
enum:
|
|
- client_credentials
|
|
- authorization_code
|
|
default: client_credentials
|
|
oauth_token_endpoint:
|
|
type: string
|
|
description: XOAUTH2, required; https:// URL
|
|
oauth_authorize_endpoint:
|
|
type: string
|
|
description: XOAUTH2 authorization_code, required; https:// URL
|
|
oauth_userinfo_endpoint:
|
|
type: string
|
|
description: >-
|
|
XOAUTH2 authorization_code, optional: identity endpoint used when
|
|
the token response has no usable id_token; https:// URL
|
|
oauth_client_id:
|
|
type: string
|
|
description: XOAUTH2, required, max. 500 characters
|
|
oauth_client_secret:
|
|
type: string
|
|
format: password
|
|
description: >-
|
|
XOAUTH2, required, max. 500 characters; empty on edit = keep. Never
|
|
returned.
|
|
oauth_scope:
|
|
type: string
|
|
description: XOAUTH2, required, max. 500 characters
|
|
oauth_extra_params:
|
|
description: >-
|
|
XOAUTH2, optional: extra OAuth2 parameters as JSON object with
|
|
scalar values, or as JSON text (max. 4000 characters); empty =
|
|
none. `prompt`, `access_type`, `login_hint`, `domain_hint` and `hd`
|
|
go to the sign-in URL, all others to the token request; they never
|
|
replace client id, secret, scope or grant fields.
|
|
type:
|
|
- object
|
|
- string
|
|
- "null"
|
|
additionalProperties:
|
|
type:
|
|
- string
|
|
- number
|
|
- boolean
|
|
- "null"
|
|
SyncJobSource:
|
|
type: object
|
|
description: A sync source; secrets are never returned.
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
created_by:
|
|
type: string
|
|
description: Creator; `API` for API keys, empty = handed over to the admins (creator deleted)
|
|
scope:
|
|
type: string
|
|
enum:
|
|
- all
|
|
- domain
|
|
- user
|
|
domains:
|
|
type: array
|
|
items:
|
|
type: string
|
|
users:
|
|
type: array
|
|
items:
|
|
type: string
|
|
host:
|
|
type: string
|
|
port:
|
|
type: integer
|
|
enc:
|
|
type:
|
|
- string
|
|
- "null"
|
|
host1:
|
|
type: string
|
|
description: Same as `host`
|
|
port1:
|
|
type: integer
|
|
description: Same as `port`
|
|
enc1:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: Same as `enc`
|
|
verify_cert:
|
|
type: integer
|
|
auth_type:
|
|
type:
|
|
- string
|
|
- "null"
|
|
active:
|
|
type: integer
|
|
oauth_flow:
|
|
type: string
|
|
oauth_token_endpoint:
|
|
type:
|
|
- string
|
|
- "null"
|
|
oauth_authorize_endpoint:
|
|
type:
|
|
- string
|
|
- "null"
|
|
oauth_userinfo_endpoint:
|
|
type:
|
|
- string
|
|
- "null"
|
|
oauth_client_id:
|
|
type:
|
|
- string
|
|
- "null"
|
|
oauth_scope:
|
|
type:
|
|
- string
|
|
- "null"
|
|
oauth_extra_params:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: JSON text, null for callers who may not edit the source
|
|
oauth_token_expires:
|
|
type:
|
|
- integer
|
|
- "null"
|
|
description: Expiry (Unix time) of the token of a client_credentials source
|
|
oauth_last_refresh_error:
|
|
type:
|
|
- string
|
|
- "null"
|
|
oauth_last_refresh_attempt:
|
|
type:
|
|
- string
|
|
- "null"
|
|
oauth_redirect_uri:
|
|
type: string
|
|
description: Only for authorization_code sources, register it at the provider
|
|
has_client_secret:
|
|
type: boolean
|
|
has_access_token:
|
|
type: boolean
|
|
can_edit:
|
|
type: boolean
|
|
description: The caller may change the source (false for read-only API keys)
|
|
created:
|
|
type:
|
|
- string
|
|
- "null"
|
|
modified:
|
|
type:
|
|
- string
|
|
- "null"
|
|
SyncJobSettings:
|
|
type: object
|
|
properties:
|
|
max_parallel:
|
|
type: integer
|
|
description: Sync jobs running at the same time
|
|
max_bytes_per_second:
|
|
type: integer
|
|
description: Bandwidth limit per sync job process in bytes/s, 0 = unlimited
|
|
max_kb_per_second:
|
|
type: integer
|
|
description: The same in KB/s
|
|
IdentityProviderAttributes:
|
|
type: object
|
|
required:
|
|
- authsource
|
|
description: >-
|
|
Configuration of the Identity Provider. Flags marked (boolean) are on
|
|
for any non-empty value except `0`/`"0"`/`false`; flags marked (0/1) are
|
|
cast to integers (the string `"true"` is 0).
|
|
properties:
|
|
authsource:
|
|
type: string
|
|
description: Provider type (case-insensitive)
|
|
enum:
|
|
- keycloak
|
|
- generic-oidc
|
|
- ldap
|
|
client_id:
|
|
type: string
|
|
description: Keycloak, generic-oidc
|
|
client_secret:
|
|
type: string
|
|
format: password
|
|
description: Keycloak, generic-oidc
|
|
redirect_url:
|
|
type: string
|
|
description: Keycloak, generic-oidc; URL of mailcow the provider redirects to after the login
|
|
redirect_url_extra:
|
|
type:
|
|
- array
|
|
- string
|
|
items:
|
|
type: string
|
|
description: Keycloak, generic-oidc; more allowed redirect URLs, only changed when sent
|
|
server_url:
|
|
type: string
|
|
description: Keycloak base URL
|
|
realm:
|
|
type: string
|
|
description: Keycloak realm
|
|
version:
|
|
type: string
|
|
description: Keycloak version
|
|
mailpassword_flow:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: (0/1) Keycloak; check mail client passwords through the Keycloak admin API
|
|
default: 0
|
|
group_paths:
|
|
type: string
|
|
description: >-
|
|
Keycloak group sync: comma-separated group paths, e.g. `/Sales` or
|
|
`/mailcow/*` (all groups below /mailcow); needs the `query-groups`
|
|
permission
|
|
default: ""
|
|
authorize_url:
|
|
type: string
|
|
description: generic-oidc authorization endpoint
|
|
token_url:
|
|
type: string
|
|
description: generic-oidc token endpoint
|
|
userinfo_url:
|
|
type: string
|
|
description: generic-oidc userinfo endpoint
|
|
client_scopes:
|
|
type: string
|
|
description: generic-oidc scopes
|
|
default: openid profile email mailcow_template
|
|
host:
|
|
type: string
|
|
description: LDAP server, several separated by commas (spaces are removed)
|
|
default: ""
|
|
port:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: LDAP port
|
|
default: 389
|
|
use_ssl:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: (boolean) LDAP over SSL
|
|
default: false
|
|
use_tls:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: (boolean) LDAP StartTLS, ignored with `use_ssl`
|
|
default: false
|
|
basedn:
|
|
type: string
|
|
description: LDAP base DN of the user search
|
|
binddn:
|
|
type: string
|
|
description: LDAP bind DN
|
|
bindpass:
|
|
type: string
|
|
format: password
|
|
description: LDAP bind password
|
|
username_field:
|
|
type: string
|
|
description: LDAP attribute with the mail address of the user
|
|
default: mail
|
|
filter:
|
|
type: string
|
|
description: LDAP filter of the users that may log in
|
|
default: ""
|
|
attribute_field:
|
|
type: string
|
|
description: LDAP attribute whose value is matched against `mappers`
|
|
default: ""
|
|
id_attribute:
|
|
type: string
|
|
description: >-
|
|
LDAP attribute with a stable user id; empty = objectGUID, entryUUID,
|
|
nsUniqueId or ipaUniqueID, else the DN
|
|
default: ""
|
|
disabled_filter:
|
|
type: string
|
|
description: >-
|
|
LDAP filter of disabled users (Active Directory accounts with
|
|
ACCOUNTDISABLE are always disabled)
|
|
default: ""
|
|
group_basedn:
|
|
type: string
|
|
description: LDAP base DN of the group search, empty = `basedn`
|
|
default: ""
|
|
group_filter:
|
|
type: string
|
|
description: LDAP filter of the synced groups, required for the group sync
|
|
default: ""
|
|
group_name_attribute:
|
|
type: string
|
|
default: cn
|
|
group_member_mode:
|
|
type: string
|
|
description: >-
|
|
LDAP source of the memberships: memberOf of the users, member
|
|
attribute of the groups, or Active Directory incl. nested groups
|
|
enum:
|
|
- memberof
|
|
- member
|
|
- ad_chain
|
|
default: memberof
|
|
group_member_attribute:
|
|
type: string
|
|
description: LDAP member attribute for `group_member_mode` member
|
|
default: member
|
|
ignore_ssl_error:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: (boolean) Do not verify TLS certificates
|
|
default: false
|
|
login_provisioning:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: (boolean) Create mailboxes at their first login
|
|
default: false
|
|
periodic_sync:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: (0/1) Keycloak, LDAP; update mailboxes from the provider every `sync_interval`
|
|
default: 0
|
|
import_users:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: (0/1) Keycloak, LDAP; create mailboxes for new users of the provider
|
|
default: 0
|
|
sync_interval:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: Keycloak, LDAP; minutes between sync runs (at least 1)
|
|
default: 15
|
|
offboarding:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: >-
|
|
(0/1) Keycloak, LDAP; users disabled at the provider, or missing in
|
|
two complete sync runs, get login disabled (mailbox active = 2, mail
|
|
is still received); only mailboxes disabled by the sync are enabled
|
|
again
|
|
default: 0
|
|
offboarding_limit:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: >-
|
|
Keycloak, LDAP; runs that would disable more mailboxes or remove
|
|
more group memberships than this share in percent (0-100, at least
|
|
5 mailboxes) are blocked
|
|
default: 10
|
|
group_sync:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: >-
|
|
(0/1) Keycloak, LDAP; sync the members of provider groups to mailbox
|
|
groups (members added in mailcow stay)
|
|
default: 0
|
|
group_autocreate:
|
|
type:
|
|
- integer
|
|
- string
|
|
- boolean
|
|
description: >-
|
|
(0/1) Keycloak, LDAP; create a mailbox group for every provider
|
|
group without one
|
|
default: 0
|
|
group_default_domain:
|
|
type: string
|
|
description: Keycloak, LDAP; domain of new groups whose mail is not in a mailcow domain
|
|
default: ""
|
|
default_template:
|
|
type: string
|
|
description: >-
|
|
Mailbox template for new mailboxes without a matching mapping (not
|
|
used for updates); only changed when sent
|
|
mappers:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: >-
|
|
Attribute values, each mapped to the template at the same position
|
|
in `templates`; only changed when both lists are sent, pairs with an
|
|
empty value are dropped
|
|
templates:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Mailbox templates for `mappers`
|
|
IdentityProviderSettings:
|
|
type: object
|
|
description: >-
|
|
Stored settings (see `IdentityProviderAttributes`). Values are strings
|
|
as stored, except `redirect_url_extra`, `mappers` and `templates`
|
|
(lists) and `use_ssl`, `use_tls`, `login_provisioning`,
|
|
`ignore_ssl_error` (booleans; `login_provisioning` is `1` when never
|
|
stored). Secrets are `*` for read-only API keys.
|
|
properties:
|
|
authsource:
|
|
type: string
|
|
client_secret:
|
|
type: string
|
|
bindpass:
|
|
type: string
|
|
access_token:
|
|
type: string
|
|
description: Cached admin API token of Keycloak
|
|
redirect_url_extra:
|
|
type: array
|
|
items:
|
|
type: string
|
|
mappers:
|
|
type: array
|
|
items:
|
|
type: string
|
|
templates:
|
|
type: array
|
|
items:
|
|
type: string
|
|
use_ssl:
|
|
type: boolean
|
|
use_tls:
|
|
type: boolean
|
|
ignore_ssl_error:
|
|
type: boolean
|
|
login_provisioning:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
additionalProperties:
|
|
type: string
|
|
IdentitySyncStatus:
|
|
type: object
|
|
properties:
|
|
provider:
|
|
type: string
|
|
description: Configured provider, empty = none
|
|
can_sync:
|
|
type: boolean
|
|
description: The provider can be synced (Keycloak, LDAP)
|
|
sync_enabled:
|
|
type: boolean
|
|
description: Scheduled runs are on (periodic sync, import, offboarding or group sync)
|
|
counts:
|
|
type: object
|
|
description: Mailboxes of the provider (no resources)
|
|
properties:
|
|
accounts:
|
|
type: integer
|
|
linked:
|
|
type: integer
|
|
description: Linked to a user of the provider
|
|
idp_disabled:
|
|
type: integer
|
|
description: Login disabled by the sync
|
|
missing:
|
|
type: integer
|
|
description: Not found at the provider by the last runs
|
|
runs:
|
|
type: array
|
|
description: The last 10 runs, newest first
|
|
items:
|
|
$ref: "#/components/schemas/IdentitySyncRun"
|
|
IdentitySyncRun:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
provider:
|
|
type: string
|
|
mode:
|
|
type: string
|
|
enum:
|
|
- run
|
|
- preview
|
|
- force
|
|
status:
|
|
type: string
|
|
enum:
|
|
- pending
|
|
- running
|
|
- ok
|
|
- blocked
|
|
- error
|
|
requested_by:
|
|
type: string
|
|
description: Who requested the run, empty for scheduled runs
|
|
created:
|
|
type: string
|
|
started:
|
|
type:
|
|
- string
|
|
- "null"
|
|
finished:
|
|
type:
|
|
- string
|
|
- "null"
|
|
summary:
|
|
type:
|
|
- object
|
|
- "null"
|
|
description: >-
|
|
Result, null while pending: `counts` per kind of change, `details`
|
|
(up to 50 entries per list), `blocked`, `errors` (up to 50), `mode`;
|
|
failed runs only `error` and `mode`
|
|
properties:
|
|
counts:
|
|
type: object
|
|
additionalProperties:
|
|
type: integer
|
|
details:
|
|
type: object
|
|
additionalProperties:
|
|
type: array
|
|
items:
|
|
type: string
|
|
blocked:
|
|
type: boolean
|
|
errors:
|
|
type: array
|
|
items:
|
|
type: string
|
|
error:
|
|
type: string
|
|
mode:
|
|
type: string
|
|
IdentityLink:
|
|
type: object
|
|
properties:
|
|
provider:
|
|
type: string
|
|
external_id:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: User id at the provider
|
|
idp_disabled:
|
|
type: integer
|
|
description: 1 = login disabled by the identity sync
|
|
missing_since:
|
|
type:
|
|
- string
|
|
- "null"
|
|
description: Since when the sync does not find the user at the provider
|
|
responses:
|
|
Unauthorized:
|
|
description: >-
|
|
The API key is unknown or inactive (`authentication failed`), or the
|
|
request comes from an address the key does not allow
|
|
(`api access denied for ip <address>`)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Error"
|
|
example:
|
|
type: error
|
|
msg: authentication failed
|
|
Forbidden:
|
|
description: The API key is read-only
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Error"
|
|
example:
|
|
type: error
|
|
msg: API read/write access denied
|
|
WriteResult:
|
|
description: >-
|
|
The messages of the call; `{"type": "success", "msg": "Task completed"}`
|
|
or `{"type": "error", "msg": "Cannot ... item"}` if it produced none.
|
|
Check `type`: the status is 200 for failures too.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- $ref: "#/components/schemas/Messages"
|
|
- $ref: "#/components/schemas/TaskResult"
|
|
examples:
|
|
messages:
|
|
summary: Messages of the call
|
|
value:
|
|
- type: success
|
|
log:
|
|
- mailbox
|
|
- add
|
|
- alias
|
|
- address: alias@example.org
|
|
goto: user@example.org
|
|
msg:
|
|
- alias_added
|
|
- alias@example.org
|
|
failed:
|
|
summary: Failed without a message
|
|
value:
|
|
type: error
|
|
msg: Cannot add item
|
|
AcmeLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/AcmeLogEntry"
|
|
example:
|
|
- time: "1794308452"
|
|
message: mail.example.org - Certificates were successfully validated, no changes or renewals required, sleeping for another day.
|
|
ApiLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ApiLogEntry"
|
|
example:
|
|
- time: 1794334338
|
|
uri: /api/v1/edit/domain-admin
|
|
method: POST
|
|
remote: 192.0.2.10
|
|
data: "attr='{\"active\":\"1\",\"password\":\"*\",\"password2\":\"*\"}', items='[\"domainadmin1\"]'"
|
|
- time: 1794334330
|
|
uri: /api/v1/get/status/version
|
|
method: GET
|
|
remote: 192.0.2.10
|
|
data: ""
|
|
AutodiscoverLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/AutodiscoverLogEntry"
|
|
example:
|
|
- time: 1794311051
|
|
ua: Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.17928; Pro)
|
|
user: john.doe@example.org
|
|
ip: 198.51.100.7
|
|
service: activesync
|
|
CronLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/CronLogEntry"
|
|
example:
|
|
- time: 1794096901
|
|
priority: warning
|
|
task: Group Shares
|
|
message: "group_imap_grant_failed: info@example.org"
|
|
DovecotLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SyslogLogEntry"
|
|
example:
|
|
- time: "1794334332"
|
|
program: dovecot
|
|
priority: info
|
|
message: "imap-login: Login: user=<john.doe@example.org>, method=PLAIN, rip=198.51.100.7, lip=172.22.1.250, mpid=310, TLS, session=<c0kD4l8L2N7GZGMH>"
|
|
NetfilterLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/NetfilterLogEntry"
|
|
example:
|
|
- time: 1794334242
|
|
priority: crit
|
|
message: Banning 203.0.113.5/32 for 30 minutes
|
|
- time: 1794334242
|
|
priority: warn
|
|
message: "203.0.113.5 matched rule id 3 (warning: unknown[203.0.113.5]: SASL LOGIN authentication failed: ...)"
|
|
PostfixLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SyslogLogEntry"
|
|
example:
|
|
- time: "1794334301"
|
|
program: postfix/smtpd
|
|
priority: info
|
|
message: "connect from mail.example.com[198.51.100.20]"
|
|
RatelimitLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/RatelimitLogEntry"
|
|
example:
|
|
- time: 1794334001
|
|
rcpt: jane@example.com
|
|
from: john.doe@example.org
|
|
user: john.doe@example.org
|
|
rl_info: john.doe@example.org(RLsdz3tuabozgd4oacbdh8kc78)
|
|
rl_name: john.doe@example.org
|
|
rl_hash: RLsdz3tuabozgd4oacbdh8kc78
|
|
qid: E3CF91500458
|
|
ip: 172.22.1.248
|
|
message_id: 6a-5d892500-7-240abd80@example.org
|
|
header_subject: Newsletter
|
|
header_from: "\"John Doe\" <john.doe@example.org>"
|
|
RspamdHistory:
|
|
description: The scanned messages, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/RspamdHistoryEntry"
|
|
example:
|
|
- unix_time: 1794333685
|
|
time_real: 0.510136
|
|
score: -1.229459
|
|
required_score: 15
|
|
action: no action
|
|
thresholds:
|
|
reject: 15
|
|
add header: 8
|
|
greylist: 7
|
|
ip: 198.51.100.20
|
|
user: unknown
|
|
sender_smtp: jane@example.com
|
|
sender_mime: jane@example.com
|
|
rcpt_smtp:
|
|
- john.doe@example.org
|
|
rcpt_mime:
|
|
- john.doe@example.org
|
|
subject: Meeting tomorrow
|
|
message-id: 20261110190100.428319@mail.example.com
|
|
size: 1015
|
|
is_skipped: false
|
|
symbols:
|
|
DMARC_POLICY_ALLOW:
|
|
name: DMARC_POLICY_ALLOW
|
|
score: -0.5
|
|
metric_score: -0.5
|
|
description: DMARC permit policy
|
|
options:
|
|
- example.com
|
|
- none
|
|
SaslLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SaslLogEntry"
|
|
example:
|
|
- service: imap
|
|
app_password: 0
|
|
username: john.doe@example.org
|
|
real_rip: 198.51.100.7
|
|
datetime: "2026-11-10 19:07:01"
|
|
SogoLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SyslogLogEntry"
|
|
example:
|
|
- time: "1794334303"
|
|
program: sogod
|
|
priority: notice
|
|
message: "[52]: 198.51.100.7 \"GET /SOGo/so/john.doe@example.org/Mail/view HTTP/1.1\" 200 2578/0 0.002 - - 0 - 12"
|
|
UiLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/UiLogEntry"
|
|
example:
|
|
- id: 1819
|
|
task: 97D254
|
|
type: success
|
|
msg: "[\"domain_admin_modified\",\"domainadmin1\"]"
|
|
call: "[\"domain_admin\",\"edit\",{\"username\":[\"domainadmin1\"],\"active\":\"1\"}]"
|
|
user: API
|
|
role: admin
|
|
remote: 192.0.2.10
|
|
time: 1794319670
|
|
WatchdogLogs:
|
|
description: The log entries, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/WatchdogLogEntry"
|
|
example:
|
|
- time: "1794334334"
|
|
service: Dovecot
|
|
lvl: "100"
|
|
hpnow: "12"
|
|
hptotal: "12"
|
|
hpdiff: "0"
|
|
parameters:
|
|
MailboxTagsQuery:
|
|
name: tags
|
|
in: query
|
|
required: false
|
|
description: >-
|
|
Comma-separated tags: only mailboxes with a tag that contains one of
|
|
them (substring match)
|
|
schema:
|
|
type: string
|
|
example: sales,support
|
|
examples:
|
|
MailboxDetails:
|
|
summary: A mailbox
|
|
value:
|
|
username: john.doe@example.org
|
|
active: 1
|
|
active_int: 1
|
|
domain: example.org
|
|
name: John Doe
|
|
local_part: john.doe
|
|
quota: 3221225472
|
|
messages: 1207
|
|
attributes:
|
|
force_pw_update: "0"
|
|
force_tfa: "0"
|
|
tls_enforce_in: "0"
|
|
tls_enforce_out: "0"
|
|
sogo_access: "1"
|
|
imap_access: "1"
|
|
pop3_access: "0"
|
|
smtp_access: "1"
|
|
sieve_access: "1"
|
|
eas_access: "1"
|
|
dav_access: "1"
|
|
relayhost: "0"
|
|
shared: "0"
|
|
passwd_update: "2026-11-03 09:37:37"
|
|
mailbox_format: "maildir:"
|
|
quarantine_notification: hourly
|
|
quarantine_category: reject
|
|
attribute_hash: ""
|
|
recovery_email: ""
|
|
custom_attributes:
|
|
department: Sales
|
|
quota_used: 418219315
|
|
percent_in_use: 13
|
|
created: "2026-11-03 09:37:37"
|
|
modified: "2026-11-06 20:20:46"
|
|
authsource: mailcow
|
|
percent_class: success
|
|
last_imap_login: 1794052021
|
|
last_smtp_login: 1793788402
|
|
last_pop3_login: 0
|
|
last_sso_login: 1794005152
|
|
last_sogo_login: 1794005160
|
|
max_new_quota: 10737418240
|
|
spam_aliases: 1
|
|
pushover_active: 0
|
|
rl:
|
|
value: "100"
|
|
frame: h
|
|
rl_scope: mailbox
|
|
is_relayed: 0
|
|
sender_acl:
|
|
- sales@example.org
|
|
tags:
|
|
- sales
|
|
MailboxList:
|
|
summary: Mailboxes
|
|
value:
|
|
- username: john.doe@example.org
|
|
active: 1
|
|
active_int: 1
|
|
domain: example.org
|
|
name: John Doe
|
|
local_part: john.doe
|
|
quota: 3221225472
|
|
messages: 1207
|
|
attributes:
|
|
force_pw_update: "0"
|
|
force_tfa: "0"
|
|
tls_enforce_in: "0"
|
|
tls_enforce_out: "0"
|
|
sogo_access: "1"
|
|
imap_access: "1"
|
|
pop3_access: "0"
|
|
smtp_access: "1"
|
|
sieve_access: "1"
|
|
eas_access: "1"
|
|
dav_access: "1"
|
|
relayhost: "0"
|
|
shared: "0"
|
|
passwd_update: "2026-11-03 09:37:37"
|
|
mailbox_format: "maildir:"
|
|
quarantine_notification: hourly
|
|
quarantine_category: reject
|
|
attribute_hash: ""
|
|
custom_attributes: []
|
|
quota_used: 418219315
|
|
percent_in_use: 13
|
|
created: "2026-11-03 09:37:37"
|
|
modified: "2026-11-06 20:20:46"
|
|
authsource: mailcow
|
|
percent_class: success
|
|
last_imap_login: 1794052021
|
|
last_smtp_login: 1793788402
|
|
last_pop3_login: 0
|
|
last_sso_login: 0
|
|
last_sogo_login: 1794005160
|
|
max_new_quota: 10737418240
|
|
spam_aliases: 0
|
|
pushover_active: 0
|
|
rl: false
|
|
rl_scope: domain
|
|
is_relayed: 0
|
|
sender_acl: []
|
|
MailboxSearchPage:
|
|
summary: One page of mailboxes
|
|
value:
|
|
draw: 1
|
|
recordsTotal: 1
|
|
recordsFiltered: 1
|
|
data:
|
|
- username: john.doe@example.org
|
|
active: 1
|
|
active_int: 1
|
|
domain: example.org
|
|
name: John Doe
|
|
local_part: john.doe
|
|
quota: 3221225472
|
|
messages: 1207
|
|
attributes:
|
|
force_pw_update: "0"
|
|
force_tfa: "0"
|
|
tls_enforce_in: "0"
|
|
tls_enforce_out: "0"
|
|
sogo_access: "1"
|
|
imap_access: "1"
|
|
pop3_access: "0"
|
|
smtp_access: "1"
|
|
sieve_access: "1"
|
|
eas_access: "1"
|
|
dav_access: "1"
|
|
relayhost: "0"
|
|
shared: "0"
|
|
passwd_update: "2026-11-03 09:37:37"
|
|
mailbox_format: "maildir:"
|
|
quarantine_notification: hourly
|
|
quarantine_category: reject
|
|
attribute_hash: ""
|
|
custom_attributes: []
|
|
quota_used: 418219315
|
|
percent_in_use: 13
|
|
created: "2026-11-03 09:37:37"
|
|
modified: "2026-11-06 20:20:46"
|
|
authsource: mailcow
|
|
percent_class: success
|
|
last_imap_login: 1794052021
|
|
last_smtp_login: 1793788402
|
|
last_pop3_login: 0
|
|
last_sso_login: 0
|
|
last_sogo_login: 1794005160
|
|
max_new_quota: 10737418240
|
|
spam_aliases: 0
|
|
pushover_active: 0
|
|
rl: false
|
|
rl_scope: domain
|
|
is_relayed: 0
|
|
sender_acl: []
|
|
tags:
|
|
- sales
|
|
|
|
security:
|
|
- ApiKeyAuth: []
|
|
|
|
paths:
|
|
/api/v1/add/alias:
|
|
post:
|
|
tags:
|
|
- Aliases
|
|
summary: Create aliases
|
|
operationId: addAlias
|
|
description: >-
|
|
Creates an alias for every address in `address`, all with the same
|
|
destinations. Administrators and API keys may use every domain, domain
|
|
administrators their own domains.
|
|
|
|
|
|
Every address is checked on its own and gets its own message:
|
|
`alias_added` (address, new ID) on success, else `is_alias_or_mailbox`,
|
|
`domain_not_found`, `is_spam_alias`, `alias_invalid` or
|
|
`access_denied`. An address that is also one of the destinations is
|
|
skipped without message. `max_alias_exceeded` (the domain has no
|
|
aliases left) stops the call at that address. Nothing is created with
|
|
`comment_too_long`, `alias_empty`, `goto_empty` or when no destination
|
|
is valid (`goto_invalid`: no e-mail address or a resource;
|
|
`external_goto_denied`: not a mailcow domain while external
|
|
destinations are disabled by `ALIAS_DISABLE_EXTERNAL_DOMAINS` or by the
|
|
ACL of the domain administrator).
|
|
|
|
|
|
Flags that are left out are 0: send `active`, `sogo_visible` and
|
|
`sender_allowed` as 1 to get an alias like the UI creates it.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
address:
|
|
type: string
|
|
description: >-
|
|
Alias address, `@example.org` for a catch-all of the
|
|
domain. Several addresses can be separated by spaces,
|
|
commas, semicolons or line breaks. The domain must be a
|
|
mailcow domain or alias domain (IDN domains are stored in
|
|
punycode).
|
|
goto:
|
|
type: string
|
|
description: >-
|
|
Destination addresses, separated by spaces, commas,
|
|
semicolons or line breaks. Required unless `goto_null`,
|
|
`goto_spam` or `goto_ham` is 1; ignored then.
|
|
goto_null:
|
|
type: [boolean, integer, string]
|
|
description: >-
|
|
1 = discard the mail silently (destination
|
|
`null@localhost`). Wins over `goto_spam` and `goto_ham`.
|
|
default: 0
|
|
goto_spam:
|
|
type: [boolean, integer, string]
|
|
description: >-
|
|
1 = learn the mail as spam (destination `spam@localhost`).
|
|
Wins over `goto_ham`.
|
|
default: 0
|
|
goto_ham:
|
|
type: [boolean, integer, string]
|
|
description: 1 = learn the mail as ham (destination `ham@localhost`)
|
|
default: 0
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
default: 0
|
|
sogo_visible:
|
|
type: [boolean, integer, string]
|
|
description: >-
|
|
1 = the alias is a selectable sender in SOGo (aliases that
|
|
point to at least one local mailbox)
|
|
default: 0
|
|
internal:
|
|
type: [boolean, integer, string]
|
|
description: >-
|
|
1 = internal alias: only reachable from its own domain and
|
|
the alias domains of it
|
|
default: 0
|
|
sender_allowed:
|
|
type: [boolean, integer, string]
|
|
description: 1 = the destination mailboxes may send as this alias
|
|
default: 0
|
|
public_comment:
|
|
type: string
|
|
description: Comment shown to the users, at most 160 characters
|
|
maxLength: 160
|
|
private_comment:
|
|
type: string
|
|
description: Comment for administrators, at most 160 characters
|
|
maxLength: 160
|
|
required:
|
|
- address
|
|
example:
|
|
address: sales@example.org
|
|
goto: anna@example.org,ben@example.org
|
|
active: "1"
|
|
sogo_visible: "1"
|
|
sender_allowed: "1"
|
|
internal: "0"
|
|
public_comment: Sales team
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/time_limited_alias:
|
|
post:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Create a time-limited alias
|
|
operationId: addTimeLimitedAlias
|
|
description: >-
|
|
Creates a random alias (e.g. `kahd.osuwe@example.org`) that delivers to
|
|
the mailbox until it expires. Needs the user ACL `spam_alias`. API keys
|
|
must send `username` (without it the session user "API" is used and
|
|
the call fails with `domain_invalid`); a mailbox user may leave it out
|
|
(own mailbox) and gets `access_denied` for other mailboxes. `domain`
|
|
must be the domain of the mailbox or one of its alias domains
|
|
(`domain_invalid`). Errors: `validity_missing` (validity out of range).
|
|
Success: `mailbox_modified`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- domain
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Mailbox the alias delivers to (required for API keys)
|
|
domain:
|
|
type: string
|
|
description: Domain of the alias
|
|
description:
|
|
type: string
|
|
default: ""
|
|
description: Note for the alias
|
|
validity:
|
|
type: [integer, string]
|
|
minimum: 1
|
|
maximum: 87600
|
|
default: 8760
|
|
description: Hours until the alias expires
|
|
permanent:
|
|
type: [boolean, integer, string]
|
|
default: false
|
|
description: true keeps the alias after it expired
|
|
example:
|
|
username: john.doe@example.org
|
|
domain: example.org
|
|
description: Online shop registration
|
|
validity: 720
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/api-key:
|
|
post:
|
|
summary: Create API key
|
|
description: >-
|
|
Creates an API key with a random value. The answer does not contain the
|
|
value: read it with `get/api-key/all`. Without `skip_ip_check` the key
|
|
needs at least one IP address or network in `allow_from`.
|
|
|
|
|
|
Success: `api_key_added` (with the description, else the ID). Errors:
|
|
`api_key_access_invalid`, `api_key_description_invalid`,
|
|
`api_key_network_invalid`, `ip_list_empty`.
|
|
operationId: addApiKey
|
|
tags:
|
|
- API Keys
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ApiKeyAttributes"
|
|
- required:
|
|
- access
|
|
example:
|
|
description: provisioning
|
|
access: rw
|
|
allow_from: "192.0.2.10, 2001:db8::/64"
|
|
skip_ip_check: 0
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/app-passwd:
|
|
post:
|
|
tags:
|
|
- App Passwords
|
|
summary: Create an app password
|
|
operationId: addAppPassword
|
|
description: >-
|
|
Adds an app password to a mailbox: a separate password for a client,
|
|
valid only for the protocols listed. Needs the user ACL `app_passwds`.
|
|
API keys must send `username` (without it the session user "API" is
|
|
used and the call fails with `access_denied`); a mailbox user may leave
|
|
it out (own mailbox). Errors: `access_denied`, `password_complexity`,
|
|
`password_mismatch`, `app_name_empty`. Success: `app_passwd_added`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- app_name
|
|
- app_passwd
|
|
- app_passwd2
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Mailbox the app password belongs to (required for API keys)
|
|
app_name:
|
|
type: string
|
|
description: Name of the app password
|
|
app_passwd:
|
|
type: string
|
|
format: password
|
|
description: The password, checked against the password policy
|
|
app_passwd2:
|
|
type: string
|
|
format: password
|
|
description: The password again
|
|
protocols:
|
|
description: Protocols the password is valid for; not listed = not allowed
|
|
type: array
|
|
items:
|
|
type: string
|
|
enum:
|
|
- imap_access
|
|
- smtp_access
|
|
- pop3_access
|
|
- sieve_access
|
|
- dav_access
|
|
- eas_access
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: 1 active, 0 inactive
|
|
example:
|
|
username: john.doe@example.org
|
|
app_name: Thunderbird
|
|
app_passwd: eiQu4ahz8iePh
|
|
app_passwd2: eiQu4ahz8iePh
|
|
protocols:
|
|
- imap_access
|
|
- smtp_access
|
|
- sieve_access
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/bcc:
|
|
post:
|
|
tags:
|
|
- Address Rewriting
|
|
summary: Create a BCC map
|
|
operationId: addBccMap
|
|
description: >-
|
|
Sends a hidden copy of the mail of a domain or address to `bcc_dest`.
|
|
Administrators, API keys and domain administrators with the BCC maps
|
|
ACL may call it (domain administrators for their domains). The local
|
|
destination is not informed when the copy cannot be delivered.
|
|
|
|
|
|
Messages: `bcc_saved`; `invalid_bcc_map_type`, `bcc_empty`,
|
|
`bcc_must_be_email`, `bcc_exists` (same `local_dest` and `type`),
|
|
`access_denied` (no ACL, a domain or address the caller does not
|
|
manage, or an address that is no mailbox or alias). A `local_dest` that
|
|
is neither a domain nor an e-mail address answers `Cannot add item`.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
local_dest:
|
|
type: string
|
|
description: >-
|
|
A mailcow domain (stored as `@example.org`, IDN in
|
|
punycode) or the address of a mailbox or alias
|
|
bcc_dest:
|
|
type: string
|
|
description: >-
|
|
One e-mail address that gets the copies (use an alias for
|
|
several)
|
|
type:
|
|
type: string
|
|
enum:
|
|
- sender
|
|
- rcpt
|
|
description: >-
|
|
`sender`: copy the mail sent by `local_dest`; `rcpt`: copy
|
|
the mail sent to it
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
default: 0
|
|
required:
|
|
- local_dest
|
|
- bcc_dest
|
|
- type
|
|
example:
|
|
local_dest: example.org
|
|
bcc_dest: archive@example.com
|
|
type: rcpt
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/dkim:
|
|
post:
|
|
summary: Generate DKIM keys
|
|
description: >-
|
|
Generates an RSA DKIM key for each domain. Every domain must be a
|
|
domain or alias domain the caller has access to and must not have a
|
|
key yet. Success `dkim_added`, errors `dkim_domain_or_sel_invalid`
|
|
(invalid domain or selector, key exists, key generation failed),
|
|
`access_denied`.
|
|
operationId: addDkimKey
|
|
tags:
|
|
- DKIM
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- domains
|
|
- key_size
|
|
properties:
|
|
domains:
|
|
type: string
|
|
description: >-
|
|
Domain names, separated by spaces, commas, semicolons or
|
|
line breaks
|
|
dkim_selector:
|
|
type: string
|
|
default: dkim
|
|
description: Selector (letters, digits, `-`, `_`, `.`)
|
|
key_size:
|
|
type: [integer, string]
|
|
description: RSA key size in bits (the UI offers 1024, 2048, 3072, 4096)
|
|
example:
|
|
domains: example.org, example.net
|
|
dkim_selector: dkim
|
|
key_size: 2048
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/dkim_duplicate:
|
|
post:
|
|
summary: Copy a DKIM key to other domains
|
|
description: >-
|
|
Copies the DKIM key and selector of `from_domain` to the domains in
|
|
`to_domain`, replacing their keys. Admins only. The target names are
|
|
not checked. Success `dkim_duplicated` per target, errors
|
|
`access_denied`, `dkim_domain_or_sel_invalid` (`from_domain` has no
|
|
key).
|
|
operationId: duplicateDkimKey
|
|
tags:
|
|
- DKIM
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- from_domain
|
|
- to_domain
|
|
properties:
|
|
from_domain:
|
|
type: string
|
|
description: Domain whose key is copied
|
|
to_domain:
|
|
description: Domain name or list of domain names that get the key
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
example:
|
|
from_domain: example.org
|
|
to_domain:
|
|
- example.net
|
|
- example.com
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/domain:
|
|
post:
|
|
summary: Add a domain
|
|
description: >-
|
|
Adds a domain. Admins only (API keys are admins). Quotas are in MiB.
|
|
Values that are not sent come from the domain template given in
|
|
`template`, else from the first domain template (`Default`).
|
|
`relay_all_recipients` = 1 sets `backupmx`, `relay_unknown_only` = 1
|
|
sets both. Besides the domain this sets the rate limit (`rl_value`,
|
|
`rl_frame`) and creates a DKIM key (`key_size`, `dkim_selector`; the
|
|
Default template creates a 2048 bit key with selector `dkim`), so the
|
|
answer can hold `rl_saved` and `dkim_added` (or
|
|
`domain_add_dkim_available` when a key exists already) before
|
|
`domain_added`. Errors: `access_denied`,
|
|
`mailbox_defquota_exceeds_mailbox_maxquota`,
|
|
`mailbox_quota_exceeds_domain_quota`, `defquota_empty`,
|
|
`maxquota_empty`, `domain_invalid`, `object_is_not_numeric`,
|
|
`domain_exists` (also for an alias domain of that name),
|
|
`domain_cannot_match_hostname`. SOGo knows the domain only after a
|
|
restart (`restart_sogo`); a failed restart answers
|
|
`domain_added_sogo_failed` (warning) although the domain was added.
|
|
operationId: addDomain
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- domain
|
|
properties:
|
|
domain:
|
|
type: string
|
|
description: Domain name (stored lowercase, IDN as punycode)
|
|
description:
|
|
type: string
|
|
description: Description, default the domain name
|
|
template:
|
|
type: [integer, string]
|
|
description: >-
|
|
ID of the domain template that gives the values not sent
|
|
(see get/domain/template/all); default the first template
|
|
aliases:
|
|
type: [integer, string]
|
|
description: Max. number of aliases
|
|
mailboxes:
|
|
type: [integer, string]
|
|
description: Max. number of mailboxes
|
|
defquota:
|
|
type: [integer, string]
|
|
description: Default quota of new mailboxes in MiB, must not be 0
|
|
maxquota:
|
|
type: [integer, string]
|
|
description: Max. quota per mailbox in MiB, must not be 0
|
|
quota:
|
|
type: [integer, string]
|
|
description: Quota of the whole domain in MiB
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Domain active
|
|
gal:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: >-
|
|
Global address list in SOGo (all objects of the domain)
|
|
backupmx:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Relay this domain (backup MX)
|
|
relay_all_recipients:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: >-
|
|
Relay all recipients; else a mailbox is needed for every
|
|
recipient to relay. 1 sets `backupmx`.
|
|
relay_unknown_only:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: >-
|
|
Relay non-existing mailboxes only, existing mailboxes are
|
|
delivered locally. 1 sets `backupmx` and
|
|
`relay_all_recipients`.
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: >-
|
|
Tags of the domain; tags beyond the tagging limit
|
|
(`TAGGING_LIMIT`, 25) are dropped with the warning
|
|
`tag_limit_exceeded`
|
|
rl_value:
|
|
type: [integer, string]
|
|
description: Rate limit, messages per `rl_frame`; empty or 0 = none
|
|
rl_frame:
|
|
type: string
|
|
enum: [s, m, h, d]
|
|
description: Rate limit time frame
|
|
dkim_selector:
|
|
type: string
|
|
description: Selector of the DKIM key that is created
|
|
key_size:
|
|
type: [integer, string]
|
|
description: >-
|
|
RSA key size in bits of the DKIM key that is created (the
|
|
UI offers 1024, 2048, 3072, 4096); empty or 0 = no key
|
|
restart_sogo:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: Restart SOGo afterwards
|
|
example:
|
|
domain: example.org
|
|
description: Example Org
|
|
aliases: 400
|
|
mailboxes: 10
|
|
defquota: 3072
|
|
maxquota: 10240
|
|
quota: 10240
|
|
active: 1
|
|
gal: 1
|
|
backupmx: 0
|
|
relay_all_recipients: 0
|
|
relay_unknown_only: 0
|
|
tags:
|
|
- customer
|
|
rl_value: 100
|
|
rl_frame: h
|
|
dkim_selector: dkim
|
|
key_size: 2048
|
|
restart_sogo: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/domain-admin:
|
|
post:
|
|
summary: Create domain administrator
|
|
description: >-
|
|
Creates a domain administrator, who manages mailboxes, aliases and
|
|
the other objects of the given domains. The username is converted to
|
|
lowercase; it may only contain letters, digits, `_`, `.` and `-` and
|
|
must not be used by a mailbox, an administrator or a domain
|
|
administrator. The new account gets the default ACLs (see
|
|
`edit/da-acl`).
|
|
|
|
|
|
Success: `domain_admin_added`. Errors: `domain_invalid` (no domain or an
|
|
unknown domain), `username_invalid`, `object_exists`,
|
|
`password_complexity`, `password_mismatch`. Unknown domains are skipped
|
|
with `domain_invalid`; if none of the domains exists, the account is not
|
|
created although `domain_admin_added` is reported too.
|
|
operationId: addDomainAdmin
|
|
tags:
|
|
- Domain admin
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Username (letters, digits, `_`, `.`, `-`; stored in lowercase)
|
|
password:
|
|
type: string
|
|
description: Password, must match the password policy
|
|
password2:
|
|
type: string
|
|
description: The password again
|
|
domains:
|
|
description: Domain or list of domains the account administers
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
active:
|
|
type: [integer, string, boolean]
|
|
description: >-
|
|
1 = the account can log in, 0 = disabled. Missing counts as
|
|
0: send `1` for a usable account.
|
|
default: 0
|
|
required:
|
|
- username
|
|
- password
|
|
- password2
|
|
- domains
|
|
example:
|
|
username: domainadmin1
|
|
password: "Rand0m-Passw0rd!"
|
|
password2: "Rand0m-Passw0rd!"
|
|
domains:
|
|
- example.org
|
|
- example.com
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/sso/domain-admin:
|
|
post:
|
|
summary: Issue domain administrator login token
|
|
description: >-
|
|
Issues a one-time login token for a domain administrator. Opening
|
|
`https://<mailcow host>/domainadmin/mailbox?sso_token=<token>` in a
|
|
browser logs in as this domain administrator without password or
|
|
two-factor authentication. The token is valid for 30 seconds, can be
|
|
used once and only works for an active domain administrator.
|
|
|
|
|
|
Errors: `access_denied`, `object_doesnt_exist` (no domain
|
|
administrator of this name).
|
|
operationId: issueDomainAdminSsoToken
|
|
tags:
|
|
- Single Sign-On
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Username of the domain administrator
|
|
required:
|
|
- username
|
|
example:
|
|
username: domainadmin1
|
|
responses:
|
|
"200":
|
|
description: The token, or the error messages
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- type: object
|
|
properties:
|
|
token:
|
|
type: string
|
|
description: Login token (five groups of six hex digits)
|
|
required:
|
|
- token
|
|
- $ref: "#/components/schemas/Messages"
|
|
example:
|
|
token: 591F6D-5C3DD2-7455CD-DAF1C1-AA4FCC
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/da-acl:
|
|
post:
|
|
summary: Edit domain administrator ACLs
|
|
description: >-
|
|
Sets the ACLs (permissions) of domain administrators: the ACLs in
|
|
`da_acl` are granted, all others are revoked. An empty or missing
|
|
`da_acl` revokes every ACL.
|
|
|
|
|
|
One message per account. Success: `acl_saved`. Error: `Cannot
|
|
determine current ACL` (no domain administrator of this name).
|
|
operationId: editDomainAdminAcl
|
|
tags:
|
|
- Domain admin
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: Username of the domain administrator, or a list of usernames
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
da_acl:
|
|
description: The ACLs to grant (a single name or a list)
|
|
oneOf:
|
|
- $ref: "#/components/schemas/DomainAdminAcl"
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/DomainAdminAcl"
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- domainadmin1
|
|
attr:
|
|
da_acl:
|
|
- syncjobs
|
|
- quarantine
|
|
- login_as
|
|
- sogo_access
|
|
- app_passwds
|
|
- bcc_maps
|
|
- filters
|
|
- ratelimit
|
|
- spam_policy
|
|
- protocol_access
|
|
- smtp_ip_access
|
|
- mailbox_relayhost
|
|
- domain_relayhost
|
|
- alias_external_goto
|
|
- mailbox_groups
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/domain-admin:
|
|
post:
|
|
summary: Edit domain administrators
|
|
description: >-
|
|
Changes domain administrators. Attributes that are not sent keep their
|
|
value, except `force_tfa` and `force_pw_update`, which are set to 0 when
|
|
they are missing. `domains` replaces the list of domains; an empty or
|
|
missing list keeps it. The password is only changed when `password` is
|
|
not empty. Renaming an account moves its ACLs, two-factor
|
|
authentication and the sync job sources it created to the new name
|
|
(FIDO2 keys stay with the old name).
|
|
|
|
|
|
One message per account. Success: `domain_admin_modified`. Errors:
|
|
`access_denied` (no domain administrator of this name),
|
|
`domain_invalid`, `username_invalid` (invalid `username_new` or the
|
|
name of another domain administrator). A password that does not match
|
|
`password2` or the policy (`password_mismatch`, `password_complexity`)
|
|
stops the call, after the domains were already saved.
|
|
operationId: editDomainAdmin
|
|
tags:
|
|
- Domain admin
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: Username of the domain administrator, or a list of usernames
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
active:
|
|
type: [integer, string, boolean]
|
|
description: 1 = active, 0 = disabled
|
|
username_new:
|
|
type: string
|
|
description: New username (letters, digits, `_`, `.`, `-`)
|
|
domains:
|
|
description: The domains the account administers from now on
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
password:
|
|
type: string
|
|
description: New password; empty or missing keeps the password
|
|
password2:
|
|
type: string
|
|
description: The new password again
|
|
force_tfa:
|
|
type: [integer, string, boolean]
|
|
description: 1 = two-factor authentication must be set up at the next login
|
|
default: 0
|
|
force_pw_update:
|
|
type: [integer, string, boolean]
|
|
description: 1 = the password must be changed at the next login
|
|
default: 0
|
|
disable_tfa:
|
|
type: [integer, string, boolean]
|
|
description: >-
|
|
Present (with any value) = deactivate the two-factor
|
|
authentication of the account
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- domainadmin1
|
|
attr:
|
|
active: 1
|
|
domains:
|
|
- example.org
|
|
password: "N3w-Passw0rd!"
|
|
password2: "N3w-Passw0rd!"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/domain-policy:
|
|
post:
|
|
summary: Add a sender to a domain allow or deny list
|
|
description: >-
|
|
Adds an entry to the allow list (`wl`) or deny list (`bl`) of a domain.
|
|
Needs the ACL `spam_policy` (API keys have it). Success
|
|
`domain_modified`, errors `access_denied` (also for an invalid domain or
|
|
list), `policy_list_from_invalid`, `policy_list_from_exists` (the sender
|
|
is on one of the lists already).
|
|
operationId: addDomainPolicy
|
|
tags:
|
|
- Domain antispam policies
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- domain
|
|
- object_list
|
|
- object_from
|
|
properties:
|
|
domain:
|
|
type: string
|
|
description: Domain the entry belongs to
|
|
object_list:
|
|
type: string
|
|
enum: [wl, bl]
|
|
description: "`wl` allow list (whitelist), `bl` deny list (blacklist)"
|
|
object_from:
|
|
type: string
|
|
description: >-
|
|
Sender address or pattern, `*` as wildcard (e.g.
|
|
`*@example.com`); letters, digits and `@ _ . - *`
|
|
example:
|
|
domain: example.org
|
|
object_list: wl
|
|
object_from: "*@partner.example.com"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/fwdhost:
|
|
post:
|
|
tags:
|
|
- Forwarding Hosts
|
|
summary: Add forwarding hosts
|
|
operationId: addForwardingHost
|
|
description: >-
|
|
Adds hosts whose incoming mail is accepted unconditionally: no DNSBL
|
|
checks, no greylisting, spam is never rejected. A host or domain name
|
|
is resolved to the addresses of its SPF record, else its MX hosts, else
|
|
its A/AAAA records; every address becomes an entry with the name as
|
|
`source`. Administrators and API keys only.
|
|
|
|
|
|
Messages: `forwarding_host_added` (the addresses), `invalid_host`
|
|
(nothing resolved), `access_denied`, `redis_error`.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
description: >-
|
|
IPv4 or IPv6 address, network in CIDR notation, host name
|
|
or domain name
|
|
filter_spam:
|
|
type: [boolean, integer, string]
|
|
description: >-
|
|
1 = scan the mail of the hosts for spam (it can be filed
|
|
into the junk folder, never rejected); anything else = do
|
|
not scan it
|
|
default: 0
|
|
required:
|
|
- hostname
|
|
example:
|
|
hostname: relay.example.com
|
|
filter_spam: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/fwdhost:
|
|
post:
|
|
tags:
|
|
- Forwarding Hosts
|
|
summary: Update forwarding hosts
|
|
operationId: editForwardingHost
|
|
description: >-
|
|
Turns the spam filter of forwarding hosts on or off. Administrators and
|
|
API keys only. Per host: `object_modified`, `access_denied` (unknown
|
|
host), `redis_error`. Without `keep_spam` the spam filter is turned on.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: >-
|
|
Hosts as get/fwdhost lists them (`host`), a single value or
|
|
a list
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: string
|
|
- type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
keep_spam:
|
|
type: [boolean, integer, string]
|
|
description: >-
|
|
1 = do not scan the mail of the host for spam; anything
|
|
else = scan it
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 192.0.2.25
|
|
- "2001:db8::25"
|
|
attr:
|
|
keep_spam: "0"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/mailbox:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Create a mailbox
|
|
operationId: addMailbox
|
|
description: >-
|
|
Creates the mailbox `local_part@domain` with its alias entry, quota
|
|
record and user ACL. Fields that are not sent take the values of the
|
|
mailbox template given in `template` (by default the first template,
|
|
"Default").
|
|
|
|
|
|
Admins and domain admins (for their domains) may call it, mailbox users
|
|
get `access_denied`. Checks: valid address (`mailbox_invalid`), domain
|
|
exists (`domain_not_found`), address not in use by a mailbox, alias or
|
|
time-limited alias (`object_exists`, `is_alias`, `is_spam_alias`),
|
|
password policy (`password_complexity`, `password_mismatch`), mailbox
|
|
count and quota limits of the domain (`max_mailbox_exceeded`,
|
|
`mailbox_quota_exceeded`, `mailbox_quota_left_exceeded`), quota 0
|
|
(unlimited) needs the `unlimited_quota` ACL (`unlimited_quota_acl`).
|
|
Success: `mailbox_added`. Tags after the 26th are dropped with the
|
|
warning `tag_limit_exceeded`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MailboxAdd"
|
|
example:
|
|
local_part: john.doe
|
|
domain: example.org
|
|
name: John Doe
|
|
password: Moo2Shoh5aiXu
|
|
password2: Moo2Shoh5aiXu
|
|
quota: 3072
|
|
active: 1
|
|
force_pw_update: 1
|
|
tags:
|
|
- sales
|
|
acl:
|
|
- spam_alias
|
|
- spam_score
|
|
- delimiter_action
|
|
- app_passwds
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/mailbox-group:
|
|
post:
|
|
summary: Create mailbox group
|
|
description: >-
|
|
Creates a mailbox group in a domain. With an address the group is a
|
|
distribution list: mail to the address goes to all members (the group
|
|
keeps an alias row for it that the alias API shows read-only, and it
|
|
counts against the alias limit of the domain; it is inactive while the
|
|
group is inactive or has no members). A group can also let
|
|
its members send as other addresses (`send_as`, `sender_allowed`), open
|
|
other mailboxes (`imap_grants`), see shared SOGo folders (`sogo_grants`)
|
|
and get a mailbox template (`template_id`).
|
|
|
|
|
|
Admins (every read/write API key) may create groups in every domain and
|
|
set `template_id`, `priority` and `idp_ref`; domain admins need the
|
|
`mailbox_groups` ACL and may only use their domains and mailboxes.
|
|
Members must be regular mailboxes (no resources).
|
|
|
|
|
|
Answers `group_added` plus warnings of the follow-up work
|
|
(`group_too_many_members` when a group with an address has more than
|
|
1000 members, `group_template_failed`, `group_imap_grant_failed`,
|
|
`group_subscription_failed`, `group_sogo_init_failed`; failed steps
|
|
are retried by a cron). Errors (nothing is written): `domain_not_found`,
|
|
`access_denied`, `group_name_invalid`, `group_description_invalid`,
|
|
`object_exists` (name exists in the domain), `group_address_invalid`,
|
|
`is_alias_or_mailbox`, `max_alias_exceeded`, `group_member_invalid`,
|
|
`group_member_idp`, `group_send_as_invalid`, `group_grant_invalid`,
|
|
`template_id_invalid`, `group_priority_invalid`.
|
|
operationId: addMailboxGroup
|
|
tags:
|
|
- Groups
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- type: object
|
|
required:
|
|
- domain
|
|
- name
|
|
properties:
|
|
domain:
|
|
type: string
|
|
description: Domain of the group (no alias domain), case-insensitive
|
|
- $ref: "#/components/schemas/MailboxGroupAttributes"
|
|
example:
|
|
domain: example.org
|
|
name: Sales
|
|
description: Sales team
|
|
local_part: sales
|
|
members:
|
|
- alice@example.org
|
|
- bob@example.org
|
|
send_as:
|
|
- orders@example.org
|
|
sender_allowed: 1
|
|
imap_grants:
|
|
- owner: shared@example.org
|
|
rights: write
|
|
subscribe: 1
|
|
template_id: 3
|
|
priority: 10
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/oauth2-client:
|
|
post:
|
|
summary: Create OAuth2 client
|
|
description: >-
|
|
Creates an OAuth2 client with a random client ID and secret and the
|
|
scope `profile`. The answer does not contain them: read them with
|
|
`get/oauth2-client/all`. The redirect URI is not validated.
|
|
|
|
|
|
Success: `Added client access`.
|
|
operationId: addOAuth2Client
|
|
tags:
|
|
- oAuth Clients
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
redirect_uri:
|
|
type: string
|
|
description: Redirect (callback) URL of the client application
|
|
required:
|
|
- redirect_uri
|
|
example:
|
|
redirect_uri: https://app.example.org/oauth/callback
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/recipient_map:
|
|
post:
|
|
tags:
|
|
- Address Rewriting
|
|
summary: Create a recipient map
|
|
operationId: addRecipientMap
|
|
description: >-
|
|
Replaces the recipient address of mail before delivery: mail to
|
|
`recipient_map_old` goes to `recipient_map_new`. Administrators and API
|
|
keys only (other callers get `Cannot add item`).
|
|
|
|
|
|
Messages: `recipient_map_entry_saved`; `invalid_recipient_map_old`,
|
|
`invalid_recipient_map_new`, `recipient_map_entry_exists`.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
recipient_map_old:
|
|
type: string
|
|
description: >-
|
|
Original recipient: an e-mail address or a domain (stored
|
|
as `@example.org`, IDN in punycode; a leading `@` is
|
|
optional)
|
|
recipient_map_new:
|
|
type: string
|
|
description: New recipient, an e-mail address or a domain
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
default: 0
|
|
required:
|
|
- recipient_map_old
|
|
- recipient_map_new
|
|
example:
|
|
recipient_map_old: jane.doe@example.org
|
|
recipient_map_new: jane.smith@example.org
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/relayhost:
|
|
post:
|
|
tags:
|
|
- Routing
|
|
summary: Create a sender-dependent transport
|
|
operationId: addRelayhost
|
|
description: >-
|
|
Adds a relay host for outgoing mail. Domains and mailboxes use it when
|
|
their `relayhost` attribute is set to its ID (edit/domain,
|
|
edit/mailbox). The service is always `smtp:` (TLS when offered, no
|
|
SMTPS). The new entry is always active. Colons in `username` and
|
|
`password` are stored as `\:` (in the password as `\\:`); edit/relayhost
|
|
stores both unchanged. Administrators and API keys only.
|
|
|
|
|
|
Messages: `relayhost_added` (without the host name),
|
|
`invalid_host` (empty `hostname`), `access_denied`, `mysql_error`.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
description: >-
|
|
Next hop: `host`, `host:25`, `[host]:587`, `[192.0.2.1]`
|
|
or `[192.0.2.1]:25`
|
|
username:
|
|
type: string
|
|
description: SMTP user name, empty for no authentication
|
|
default: ""
|
|
password:
|
|
type: string
|
|
description: SMTP password
|
|
default: ""
|
|
required:
|
|
- hostname
|
|
example:
|
|
hostname: "[smtp.example.com]:587"
|
|
username: relay-user@example.com
|
|
password: Secret-Passphrase-42
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/resource:
|
|
post:
|
|
tags:
|
|
- Resources
|
|
summary: Create a resource
|
|
operationId: addResource
|
|
description: >-
|
|
Creates a bookable resource (room, equipment, group) for SOGo. Its
|
|
address is made of the letters and digits of the description and the
|
|
domain (description "Meeting Room 1" → `MeetingRoom1@example.org`).
|
|
Admins and domain admins (for their domains). Errors:
|
|
`resource_invalid` (address or kind invalid), `description_invalid`,
|
|
`domain_invalid`, `access_denied`, `object_exists`, `is_alias`,
|
|
`is_spam_alias`, `domain_not_found`. Success: `resource_added`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- domain
|
|
- description
|
|
- kind
|
|
properties:
|
|
domain:
|
|
type: string
|
|
description: Domain of the resource
|
|
description:
|
|
type: string
|
|
description: Name of the resource, also the source of its address
|
|
kind:
|
|
type: string
|
|
enum:
|
|
- location
|
|
- group
|
|
- thing
|
|
description: Type of resource
|
|
multiple_bookings:
|
|
type: [integer, string]
|
|
default: 0
|
|
description: >-
|
|
Booking rule: 0 always free (bookings are not limited and
|
|
do not block), -1 unlimited but shown as busy when booked,
|
|
n ≥ 1 at most n overlapping bookings; values below -1 mean -1
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: 1 active, 0 inactive
|
|
example:
|
|
domain: example.org
|
|
description: Meeting Room 1
|
|
kind: location
|
|
multiple_bookings: 0
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/syncjob:
|
|
post:
|
|
summary: Create sync job
|
|
description: >-
|
|
Creates a sync job that copies the remote account `user1` of a sync
|
|
source into a local mailbox. Host, port, encryption and authentication
|
|
come from the source (`source_id`); the job only carries the remote
|
|
login. Needs the `syncjobs` ACL (admins and API keys have it); the
|
|
caller must have access to the local mailbox. An API key must name the
|
|
mailbox in `username` (`no_user_defined` otherwise), mailbox users
|
|
always create jobs for their own mailbox.
|
|
|
|
|
|
Answers `mailbox_modified` with the local mailbox. Errors:
|
|
`access_denied` (no access to the mailbox, `mins_interval` missing or
|
|
not 1-43800, `exclude` no valid regular expression), `no_user_defined`,
|
|
`imapsync_user1_invalid`, `imapsync_source_unavailable` (source unknown,
|
|
invisible to the caller or inactive), `password_empty`,
|
|
`imapsync_source_oauth_connect_required` (XOAUTH2 authorization_code
|
|
source without a sign-in of the mailbox for `user1`), `object_exists`
|
|
(the mailbox already syncs `user1` from this source),
|
|
`imapsync_custom_params_format`, `imapsync_custom_param_invalid`,
|
|
`imapsync_custom_param_value`. Passwords are logged as `*`.
|
|
operationId: addSyncJob
|
|
tags:
|
|
- Sync jobs
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- type: object
|
|
required:
|
|
- username
|
|
- source_id
|
|
- user1
|
|
- mins_interval
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: >-
|
|
Local mailbox the job syncs into (`user2`); cannot be
|
|
changed later. Optional for mailbox users (own mailbox).
|
|
- $ref: "#/components/schemas/SyncJobAttributes"
|
|
example:
|
|
username: alice@example.org
|
|
source_id: 3
|
|
user1: alice@old-provider.example.com
|
|
password1: remote-password
|
|
mins_interval: 20
|
|
subfolder2: Imported
|
|
exclude: "(?i)spam|(?i)junk"
|
|
custom_params:
|
|
- o: folder
|
|
v: INBOX
|
|
delete2duplicates: 1
|
|
automap: 1
|
|
subscribeall: 1
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/syncjob_source:
|
|
post:
|
|
summary: Create sync source
|
|
description: >-
|
|
Creates a reusable IMAP sync source: server, encryption and
|
|
authentication of a remote system that sync jobs use by `source_id`.
|
|
Password sources (PLAIN, LOGIN, CRAM-MD5) take the password from each
|
|
job, XOAUTH2 sources carry an OAuth2 client (client_credentials: one
|
|
token of the source for every mailbox of the tenant; authorization_code:
|
|
every mailbox owner signs in once in the mailcow UI). The creator is
|
|
stored in `created_by` (`API` for API keys); names are unique per
|
|
creator. Needs the `syncjobs` ACL. Only admins create `all` sources;
|
|
XOAUTH2 sources are created by admins and domain admins only. OAuth2
|
|
endpoints must be https:// URLs with a valid host name; for sources
|
|
not created by a superadmin or an API key every resolved address must
|
|
also be public.
|
|
|
|
|
|
A client_credentials source fetches its token while it is saved: the
|
|
source is saved even when that fails, the answer then also has
|
|
`imapsync_source_token_refresh_failed`. Answers
|
|
`imapsync_source_added`. Errors (nothing is written):
|
|
`imapsync_source_name_invalid`, `imapsync_source_description_invalid`,
|
|
`imapsync_source_host_invalid`, `imapsync_source_port_invalid`,
|
|
`imapsync_source_enc_invalid`, `imapsync_source_auth_invalid`,
|
|
`imapsync_source_oauth_required`, `imapsync_source_oauth_invalid`,
|
|
`imapsync_source_oauth_endpoint_invalid`,
|
|
`imapsync_source_oauth_extra_invalid`, `imapsync_source_scope_empty`,
|
|
`access_denied` (scope or targets not allowed), `object_exists`.
|
|
Secrets are logged as `*`.
|
|
operationId: addSyncJobSource
|
|
tags:
|
|
- Sync jobs
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- type: object
|
|
required:
|
|
- name
|
|
- host
|
|
- port
|
|
- $ref: "#/components/schemas/SyncJobSourceAttributes"
|
|
examples:
|
|
password:
|
|
summary: Password source for a domain
|
|
value:
|
|
name: Old provider
|
|
description: Migration from the old provider
|
|
host: imap.example.com
|
|
port: 993
|
|
enc: SSL
|
|
auth_type: PLAIN
|
|
scope: domain
|
|
domains:
|
|
- example.org
|
|
active: 1
|
|
client_credentials:
|
|
summary: XOAUTH2 source with an app token (Microsoft 365)
|
|
value:
|
|
name: M365 tenant
|
|
host: outlook.office365.com
|
|
port: 993
|
|
enc: SSL
|
|
auth_type: XOAUTH2
|
|
oauth_flow: client_credentials
|
|
oauth_token_endpoint: https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/oauth2/v2.0/token
|
|
oauth_client_id: 11111111-2222-3333-4444-555555555555
|
|
oauth_client_secret: client-secret-value
|
|
oauth_scope: https://outlook.office365.com/.default
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/tls-policy-map:
|
|
post:
|
|
tags:
|
|
- Outgoing TLS Policy Map Overrides
|
|
summary: Create a TLS policy map
|
|
operationId: addTlsPolicyMap
|
|
description: >-
|
|
Sets the TLS policy Postfix uses for outgoing connections to a
|
|
destination (`smtp_tls_policy_maps`). Administrators and API keys only
|
|
(other callers get `Cannot add item`).
|
|
|
|
|
|
Messages: `tls_policy_map_entry_saved`; `tls_policy_map_dest_invalid`
|
|
(empty, `.`, `*` or `@`), `tls_policy_map_parameter_invalid`,
|
|
`tls_policy_map_entry_exists`. The backend does not check `policy`; the
|
|
database only takes the listed values.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
dest:
|
|
type: string
|
|
description: >-
|
|
Destination, e.g. `example.org`, `.example.org` (its
|
|
subdomains) or `[mail.example.org]:25`; IDN in punycode
|
|
policy:
|
|
type: string
|
|
description: >-
|
|
Postfix TLS security level (see
|
|
[smtp_tls_policy_maps](https://www.postfix.org/TLS_README.html#client_tls_policy))
|
|
enum:
|
|
- none
|
|
- may
|
|
- encrypt
|
|
- dane
|
|
- dane-only
|
|
- fingerprint
|
|
- verify
|
|
- secure
|
|
parameters:
|
|
type: string
|
|
description: >-
|
|
Empty or space-separated `name=value` attributes, e.g.
|
|
`protocols=!SSLv2 ciphers=medium exclude=3DES`
|
|
default: ""
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
default: 0
|
|
required:
|
|
- dest
|
|
- policy
|
|
example:
|
|
dest: example.com
|
|
policy: encrypt
|
|
parameters: protocols=>=TLSv1.2
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/transport:
|
|
post:
|
|
tags:
|
|
- Routing
|
|
summary: Create transport maps
|
|
operationId: addTransport
|
|
description: >-
|
|
Routes mail for the destinations over a next hop. A transport map
|
|
entry overrules a sender-dependent transport. The service is always
|
|
`smtp:` (TLS when offered, no SMTPS); addresses matching `/localhost$/`
|
|
are always delivered locally. Administrators and API keys only.
|
|
|
|
|
|
One entry is created per destination. All entries with the same next
|
|
hop share one set of credentials: `username` and `password` are
|
|
written to every existing entry of `nexthop`.
|
|
|
|
|
|
Messages: `relayhost_added` (without names); `invalid_nexthop`
|
|
(empty), `invalid_nexthop_authenticated` (the next hop exists with
|
|
another user name), `next_hop_interferes`, `next_hop_interferes_any`
|
|
(`host` and `[host]:port` cannot be used side by side) stop the call;
|
|
`transport_dest_exists` and `invalid_destination` drop the
|
|
destination. The destinations are only checked when other transport
|
|
maps exist. Without any valid destination the answer is the messages
|
|
or `Cannot add item`.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
destination:
|
|
type: string
|
|
description: >-
|
|
Destinations, separated by spaces, commas, semicolons or
|
|
line breaks: `example.org`, `.example.org` (its
|
|
subdomains), `*` or `box@example.org`. With `is_mx_based`
|
|
a regular expression matched against the MX name of the
|
|
recipient domain, e.g. `.*\.google\.com`.
|
|
nexthop:
|
|
type: string
|
|
description: >-
|
|
`host`, `host:25`, `[host]:25` or an IP address (put in
|
|
brackets automatically)
|
|
username:
|
|
type: string
|
|
description: SMTP user name, empty for no authentication
|
|
default: ""
|
|
password:
|
|
type: string
|
|
description: SMTP password
|
|
default: ""
|
|
is_mx_based:
|
|
type: [boolean, integer, string]
|
|
description: 1 = `destination` is a regular expression for MX names
|
|
default: 0
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
default: 0
|
|
required:
|
|
- destination
|
|
- nexthop
|
|
example:
|
|
destination: example.com, .example.com
|
|
nexthop: "[mx.example.com]:25"
|
|
username: ""
|
|
password: ""
|
|
is_mx_based: "0"
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/alias:
|
|
post:
|
|
tags:
|
|
- Aliases
|
|
summary: Delete aliases
|
|
operationId: deleteAlias
|
|
description: >-
|
|
Deletes the aliases and the send-as rights granted for their addresses
|
|
(`alias_removed` per alias). Unknown aliases and aliases of domains the
|
|
caller does not manage answer `access_denied`; distribution addresses
|
|
of mailbox groups `alias_group_managed`.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: IDs or addresses of the aliases (a single value works too)
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 12
|
|
- info@example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/api-key:
|
|
post:
|
|
summary: Delete API keys
|
|
description: >-
|
|
Deletes API keys. Service keys from mailcow.conf cannot be deleted here.
|
|
|
|
|
|
One message per key. Success: `api_key_deleted`. Errors:
|
|
`access_denied` (no key with this ID), `api_key_service_locked`.
|
|
operationId: deleteApiKey
|
|
tags:
|
|
- API Keys
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: IDs of the API keys
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 3
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/app-passwd:
|
|
post:
|
|
tags:
|
|
- App Passwords
|
|
summary: Delete app passwords
|
|
operationId: deleteAppPassword
|
|
description: >-
|
|
Deletes app passwords by ID. Needs the user ACL `app_passwds` and
|
|
access to the owning mailbox (API keys: any). Messages:
|
|
`app_passwd_removed` per ID; the first unknown ID
|
|
(`app_passwd_id_invalid`) or foreign ID (`access_denied`) stops the
|
|
call.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: App password IDs
|
|
items:
|
|
type: integer
|
|
example:
|
|
- 23
|
|
- 24
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/bcc:
|
|
post:
|
|
tags:
|
|
- Address Rewriting
|
|
summary: Delete BCC maps
|
|
operationId: deleteBccMap
|
|
description: >-
|
|
Deletes BCC maps by ID (`bcc_deleted` per map, `access_denied` for a
|
|
map of a domain the caller does not manage). A non-numeric ID stops the
|
|
call. Same callers as add/bcc.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: IDs of the BCC maps (a single value works too)
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 3
|
|
- 4
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/dkim:
|
|
post:
|
|
summary: Delete DKIM keys
|
|
description: >-
|
|
Deletes the DKIM keys of domains. Admins only. Success `dkim_removed`
|
|
per domain (also when it had no key), errors `access_denied`,
|
|
`dkim_domain_or_sel_invalid`.
|
|
operationId: deleteDkimKeys
|
|
tags:
|
|
- DKIM
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Domain names
|
|
items:
|
|
type: string
|
|
example:
|
|
- example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/domain:
|
|
post:
|
|
summary: Delete domains
|
|
description: >-
|
|
Deletes domains. Admins only. A domain that still has mailboxes or
|
|
resources is kept (`domain_not_empty`). With the domain go its aliases,
|
|
alias domains, domain admin assignments, BCC maps, MTA-STS policy, spam
|
|
policies, mailbox group data and rate limit; domain admins left without
|
|
any domain are deleted. Its mail storage is moved to the garbage
|
|
collector of Dovecot (a failure is a warning). The DKIM key is kept. Success `domain_removed`, errors `access_denied`,
|
|
`domain_invalid`.
|
|
operationId: deleteDomain
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Domain names
|
|
items:
|
|
type: string
|
|
example:
|
|
- example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/domain-admin:
|
|
post:
|
|
summary: Delete domain administrators
|
|
description: >-
|
|
Deletes domain administrators with their ACLs, two-factor
|
|
authentication and FIDO2 keys; sync job sources they created are
|
|
released. The domains and their mailboxes stay.
|
|
|
|
|
|
One message per account. Success: `domain_admin_removed`. Error:
|
|
`username_invalid` (no domain administrator of this name).
|
|
operationId: deleteDomainAdmin
|
|
tags:
|
|
- Domain admin
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Usernames of the domain administrators
|
|
items:
|
|
type: string
|
|
example:
|
|
- domainadmin1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/domain-policy:
|
|
post:
|
|
summary: Delete entries of domain allow and deny lists
|
|
description: >-
|
|
Deletes allow or deny list entries of domains by their `prefid` (see
|
|
get/policy_wl_domain and get/policy_bl_domain). Needs the ACL
|
|
`spam_policy`. Success `item_deleted` per entry, error `access_denied`
|
|
(non-numeric ID, entry of a mailbox or unknown entry).
|
|
operationId: deleteDomainPolicy
|
|
tags:
|
|
- Domain antispam policies
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Entry IDs (`prefid`)
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 12
|
|
- 13
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/fwdhost:
|
|
post:
|
|
tags:
|
|
- Forwarding Hosts
|
|
summary: Delete forwarding hosts
|
|
operationId: deleteForwardingHost
|
|
description: >-
|
|
Removes forwarding hosts (`forwarding_host_removed` per host, also for
|
|
hosts that do not exist). Administrators and API keys only.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Hosts as get/fwdhost lists them (`host`; a single value works too)
|
|
items:
|
|
type: string
|
|
example:
|
|
- 192.0.2.25
|
|
- "2001:db8::25"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/fwdhost/{host}:
|
|
get:
|
|
tags:
|
|
- Forwarding Hosts
|
|
summary: Get forwarding hosts
|
|
operationId: getForwardingHosts
|
|
description: >-
|
|
`all` lists the forwarding hosts (administrators and API keys), a host
|
|
address returns that entry (every logged-in role). `{}` if there is
|
|
none. Networks (`198.51.100.0/24`) cannot be read one by one: the path
|
|
ends at the slash.
|
|
parameters:
|
|
- name: host
|
|
in: path
|
|
required: true
|
|
description: "`all` or the address of a forwarding host"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The list of forwarding hosts (`all`) or one host
|
|
content:
|
|
application/json:
|
|
schema:
|
|
anyOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/ForwardingHost"
|
|
- $ref: "#/components/schemas/ForwardingHost"
|
|
examples:
|
|
all:
|
|
summary: get/fwdhost/all
|
|
value:
|
|
- host: 192.0.2.25
|
|
source: relay.example.com
|
|
keep_spam: "no"
|
|
- host: "2001:db8::25"
|
|
source: relay.example.com
|
|
keep_spam: "no"
|
|
- host: 198.51.100.0/24
|
|
source: 198.51.100.0/24
|
|
keep_spam: "yes"
|
|
one:
|
|
summary: get/fwdhost/192.0.2.25
|
|
value:
|
|
host: 192.0.2.25
|
|
source: relay.example.com
|
|
keep_spam: "no"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/delete/mailbox:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Delete mailboxes
|
|
operationId: deleteMailbox
|
|
description: >-
|
|
Deletes mailboxes with everything that belongs to them: maildir (moved
|
|
to the garbage collector), aliases pointing only to them, ACLs,
|
|
quarantine, filters, policies, time-limited aliases, sync jobs, SOGo
|
|
data, BCC maps, OAuth tokens, 2FA keys, rate limit; the address is
|
|
removed from the targets of other aliases. Admins and domain admins
|
|
(for their domains); a mailbox user session passes the check for its
|
|
own mailbox and can delete it. Messages per mailbox: `mailbox_removed`
|
|
or `access_denied`; a warning if the maildir could not be moved.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
example:
|
|
- john.doe@example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/mailbox-group:
|
|
post:
|
|
summary: Delete mailbox groups
|
|
description: >-
|
|
Deletes groups. The group alias, the send-as rights and the grants of
|
|
the group are removed; members keep their mailbox settings (another
|
|
group's template may become effective). Same permissions as edit.
|
|
Answers one message per id: `group_removed` or `access_denied` (unknown
|
|
id, id that is no number, no permission).
|
|
operationId: deleteMailboxGroups
|
|
tags:
|
|
- Groups
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Group ids
|
|
items:
|
|
type:
|
|
- integer
|
|
- string
|
|
example:
|
|
- 7
|
|
- 8
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/identity-link:
|
|
post:
|
|
summary: Remove identity links
|
|
description: >-
|
|
Admins only (every read/write API key). Removes the links of mailboxes
|
|
to their Identity Provider users; the next sync run or login links them
|
|
again by email. Use it to resolve conflicts, e.g. when an address was
|
|
given to another user of the provider. Answers `iam_link_removed` per
|
|
mailbox (also for mailboxes without a link), or `access_denied`.
|
|
operationId: deleteIdentityLinks
|
|
tags:
|
|
- Identity Provider
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Mailboxes
|
|
items:
|
|
type: string
|
|
example:
|
|
- alice@example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/mailq:
|
|
post:
|
|
summary: Delete queued messages
|
|
description: >-
|
|
Deletes messages from the Postfix queue (`postsuper -d <qid>`; admins
|
|
only, an API key may). To empty the whole queue use `super_delete` of
|
|
`POST /api/v1/edit/mailq`. Queue IDs that are not hexadecimal are
|
|
skipped.
|
|
|
|
|
|
Messages: `queue_command_success`; `Error: command failed: ...`
|
|
(danger); `unknown` (danger) when the command gave no answer;
|
|
`access_denied` for non-admins.
|
|
operationId: deleteQueuedMessages
|
|
tags:
|
|
- Queue Manager
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
description: Queue IDs (a single ID works too)
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: string
|
|
- type: string
|
|
example:
|
|
- B98C6260CA1
|
|
- 4C1E8260D02
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/oauth2-client:
|
|
post:
|
|
summary: Delete OAuth2 clients
|
|
description: >-
|
|
Deletes OAuth2 clients. Tokens issued to them are not deleted (use
|
|
`revoke_tokens` of `edit/oauth2-client` first).
|
|
|
|
|
|
Success: one `items_deleted` message for the whole call. Error:
|
|
`access_denied` for an ID that is no number.
|
|
operationId: deleteOAuth2Client
|
|
tags:
|
|
- oAuth Clients
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: IDs of the clients
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/qitem:
|
|
post:
|
|
summary: Delete quarantined messages
|
|
description: >-
|
|
Deletes quarantine items without releasing or learning them. An API
|
|
key (admin) may delete every item, others only items of their
|
|
mailboxes or domains; the quarantine module must be allowed for the
|
|
caller.
|
|
|
|
|
|
Messages: `item_deleted` per item (for an admin also for IDs that do
|
|
not exist); `access_denied` (danger) for a non-numeric or foreign ID.
|
|
operationId: deleteQuarantineItems
|
|
tags:
|
|
- Quarantine
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
description: IDs of quarantine items (a single ID works too)
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
example:
|
|
- "33"
|
|
- "34"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/qitem:
|
|
post:
|
|
summary: Release or learn quarantined messages
|
|
description: >-
|
|
Acts on quarantine items. An API key (admin) may act on every item,
|
|
others only on items of their mailboxes or domains; the quarantine
|
|
module must be allowed for the caller.
|
|
|
|
|
|
- `release` and `learnham` do the same: the message is delivered to
|
|
its recipient (through Postfix, as the original message or as an
|
|
attachment, see the release format of `POST /api/v1/edit/quarantine`),
|
|
deleted from the quarantine and learned as ham by Rspamd.
|
|
- `learnspam` deletes the item and learns the message as spam.
|
|
|
|
Messages: `item_released` and `learned_ham`, or `qlearn_spam`, per
|
|
item; `access_denied` (danger) for a non-numeric, unknown or foreign
|
|
ID; `release_send_failed` (warning); `ham_learn_error`,
|
|
`spam_learn_error` (danger); `fuzzy_learn_error` (warning). When
|
|
Postfix cannot be reached or answers with an unexpected SMTP code, the
|
|
remaining items are not processed. An unknown `action` does nothing
|
|
and is answered with `Task completed`.
|
|
operationId: editQuarantineItems
|
|
tags:
|
|
- Quarantine
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: ID or list of IDs of quarantine items
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
attr:
|
|
type: object
|
|
properties:
|
|
action:
|
|
type: string
|
|
enum:
|
|
- release
|
|
- learnham
|
|
- learnspam
|
|
required:
|
|
- action
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- "33"
|
|
- "34"
|
|
attr:
|
|
action: release
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/recipient_map:
|
|
post:
|
|
tags:
|
|
- Address Rewriting
|
|
summary: Delete recipient maps
|
|
operationId: deleteRecipientMap
|
|
description: >-
|
|
Deletes recipient maps by ID (`recipient_map_entry_deleted` per ID,
|
|
also for IDs that do not exist). A non-numeric ID stops the call.
|
|
Administrators and API keys only.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: IDs of the recipient maps (a single value works too)
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/relayhost:
|
|
post:
|
|
tags:
|
|
- Routing
|
|
summary: Delete sender-dependent transports
|
|
operationId: deleteRelayhost
|
|
description: >-
|
|
Deletes sender-dependent transports by ID (`relayhost_removed` per ID,
|
|
also for IDs that do not exist). Domains that used one fall back to the
|
|
default route (`relayhost` 0); the `relayhost` attribute of mailboxes
|
|
is not reset. Administrators and API keys only.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: IDs of the sender-dependent transports (a single value works too)
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/resource:
|
|
post:
|
|
tags:
|
|
- Resources
|
|
summary: Delete resources
|
|
operationId: deleteResource
|
|
description: >-
|
|
Deletes resources and their SOGo data. Admins and domain admins (for
|
|
their domains). Messages per resource: `resource_removed` or
|
|
`access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Resource addresses
|
|
items:
|
|
type: string
|
|
example:
|
|
- MeetingRoom1@example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/syncjob:
|
|
post:
|
|
summary: Delete sync jobs
|
|
description: >-
|
|
Deletes sync jobs. Needs the `syncjobs` ACL and access to the local
|
|
mailbox of each job (admins and API keys: every job). The OAuth2 token
|
|
of the job's remote account is deleted when no other job uses it.
|
|
Answers one message per id: `deleted_syncjob` with the id as sent, or
|
|
`access_denied` (unknown job, id that is no number, no access).
|
|
operationId: deleteSyncJobs
|
|
tags:
|
|
- Sync jobs
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Job ids
|
|
items:
|
|
type:
|
|
- integer
|
|
- string
|
|
example:
|
|
- 12
|
|
- 13
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/syncjob_source:
|
|
post:
|
|
summary: Delete sync sources
|
|
description: >-
|
|
Deletes sync sources that no sync job uses (ids that are no number are
|
|
skipped). Needs the `syncjobs` ACL and edit rights on the source.
|
|
Answers one message per id: `imapsync_source_deleted`, or
|
|
`imapsync_source_in_use`, `access_denied` (unknown id, no edit rights).
|
|
operationId: deleteSyncJobSources
|
|
tags:
|
|
- Sync jobs
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Source ids
|
|
items:
|
|
type:
|
|
- integer
|
|
- string
|
|
example:
|
|
- 3
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/tls-policy-map:
|
|
post:
|
|
tags:
|
|
- Outgoing TLS Policy Map Overrides
|
|
summary: Delete TLS policy maps
|
|
operationId: deleteTlsPolicyMap
|
|
description: >-
|
|
Deletes TLS policy maps by ID (`tls_policy_map_entry_deleted` per ID,
|
|
also for IDs that do not exist). A non-numeric ID stops the call.
|
|
Administrators and API keys only.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: IDs of the TLS policy maps (a single value works too)
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 2
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/transport:
|
|
post:
|
|
tags:
|
|
- Routing
|
|
summary: Delete transport maps
|
|
operationId: deleteTransport
|
|
description: >-
|
|
Deletes transport maps by ID (`relayhost_removed` per ID, also for IDs
|
|
that do not exist). Administrators and API keys only.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: IDs of the transport maps (a single value works too)
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 4
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/mailbox/tag/{mailbox}:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Remove tags from a mailbox
|
|
operationId: deleteMailboxTags
|
|
description: >-
|
|
Removes the given tags from the mailbox. Admins and domain admins (for
|
|
their domains); `access_denied` otherwise. Answers `mailbox_modified`,
|
|
or "Cannot delete item" when no tag was sent.
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Tag names
|
|
items:
|
|
type: string
|
|
example:
|
|
- sales
|
|
- trainee
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/domain/tag/{domain}:
|
|
post:
|
|
summary: Remove tags of a domain
|
|
description: >-
|
|
Removes tags from a domain. Answers `domain_modified` when at least one
|
|
tag name was sent (also when the domain did not have it), `Cannot
|
|
delete item` for an empty list; errors `domain_invalid`,
|
|
`access_denied`.
|
|
operationId: deleteDomainTags
|
|
tags:
|
|
- Domains
|
|
parameters:
|
|
- name: domain
|
|
in: path
|
|
required: true
|
|
description: Domain name
|
|
schema:
|
|
type: string
|
|
example: example.org
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Tag names
|
|
items:
|
|
type: string
|
|
example:
|
|
- customer
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/alias:
|
|
post:
|
|
tags:
|
|
- Aliases
|
|
summary: Update aliases
|
|
operationId: editAlias
|
|
description: >-
|
|
Changes the aliases in `items`; attributes that are left out keep their
|
|
value, except the `goto_*` flags, which are 0 when left out. An alias
|
|
that discards or learns its mail (`null@localhost`, `spam@localhost`,
|
|
`ham@localhost`) therefore needs its `goto_*` flag in every edit:
|
|
without it, the current destination fails the address check
|
|
(`goto_invalid`), nothing is saved and the answer still contains
|
|
`alias_modified`.
|
|
|
|
|
|
Per alias: `alias_modified` on success; `alias_invalid` for an unknown
|
|
alias or one of a domain the caller does not manage;
|
|
`alias_group_managed` for the distribution address of a mailbox group
|
|
(change it in the group). A new `address` is checked like in
|
|
add/alias (`access_denied`, `alias_invalid`, `is_alias_or_mailbox`,
|
|
`domain_not_found`, `is_spam_alias`); send-as grants of mailbox groups
|
|
follow the new address. Destinations that are no e-mail address
|
|
(`goto_invalid`), external while external destinations are disabled
|
|
(`external_goto_denied`) or equal to the alias (`alias_goto_identical`)
|
|
are dropped; if none remains, nothing is saved. Comments are not
|
|
limited to 160 characters here.
|
|
|
|
|
|
`expand_alias` does not change the alias: it creates the missing copies
|
|
of it in the alias domains of its domain (same destinations, active,
|
|
visible in SOGo, `sender_allowed` 0) and answers `alias_modified`, or
|
|
warns `is_not_primary_alias` for an alias that is itself in an alias
|
|
domain.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: IDs or addresses of the aliases, a single value or a list
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
attr:
|
|
type: object
|
|
properties:
|
|
address:
|
|
type: string
|
|
description: New alias address, `@example.org` for a catch-all
|
|
goto:
|
|
type: string
|
|
description: >-
|
|
New destination addresses, separated by spaces,
|
|
commas, semicolons or line breaks; replaces the current
|
|
ones. Ignored if a `goto_*` flag is 1.
|
|
goto_null:
|
|
type: [boolean, integer, string]
|
|
description: 1 = discard the mail silently
|
|
default: 0
|
|
goto_spam:
|
|
type: [boolean, integer, string]
|
|
description: 1 = learn the mail as spam
|
|
default: 0
|
|
goto_ham:
|
|
type: [boolean, integer, string]
|
|
description: 1 = learn the mail as ham
|
|
default: 0
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
sogo_visible:
|
|
type: [boolean, integer, string]
|
|
description: 1 = selectable sender in SOGo
|
|
internal:
|
|
type: [boolean, integer, string]
|
|
description: 1 = only reachable from its own domain and its alias domains
|
|
sender_allowed:
|
|
type: [boolean, integer, string]
|
|
description: 1 = the destination mailboxes may send as this alias
|
|
public_comment:
|
|
type: string
|
|
description: Comment shown to the users
|
|
private_comment:
|
|
type: string
|
|
description: Comment for administrators
|
|
expand_alias:
|
|
type: [boolean, integer]
|
|
description: >-
|
|
true or 1 = create the missing copies of the alias in
|
|
the alias domains; all other attributes are ignored
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 12
|
|
attr:
|
|
goto: anna@example.org,ben@example.org,carla@example.org
|
|
active: "1"
|
|
public_comment: Sales team
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/api-key:
|
|
post:
|
|
summary: Edit API keys
|
|
description: >-
|
|
Changes API keys; attributes that are not sent keep their value.
|
|
`regen_key` gives a key a new random value: clients using the old value
|
|
are locked out. Service keys from mailcow.conf (API_KEY,
|
|
API_KEY_READ_ONLY) cannot be changed here.
|
|
|
|
|
|
One message per key. Success: `api_key_modified`. Errors:
|
|
`access_denied` (no key with this ID), `api_key_service_locked`,
|
|
`api_key_access_invalid`, `api_key_description_invalid`,
|
|
`api_key_network_invalid`, `ip_list_empty`.
|
|
operationId: editApiKey
|
|
tags:
|
|
- API Keys
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: ID of the API key, or a list of IDs
|
|
oneOf:
|
|
- type: [integer, string]
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
attr:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ApiKeyAttributes"
|
|
- type: object
|
|
properties:
|
|
regen_key:
|
|
type: [integer, string, boolean]
|
|
description: 1 = generate a new key value
|
|
default: 0
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 3
|
|
attr:
|
|
allow_from:
|
|
- 192.0.2.10
|
|
- 198.51.100.0/24
|
|
regen_key: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/domain:
|
|
post:
|
|
summary: Edit domains
|
|
description: >-
|
|
Changes domains. With an API key (admin) every attribute can be set;
|
|
quotas are in MiB, attributes not sent keep their value (`aliases`,
|
|
`maxquota` and `quota` keep it also for 0 or an empty value).
|
|
`relay_all_recipients` = 1 sets `backupmx`, `relay_unknown_only` = 1
|
|
sets both. `tags` are added to the existing tags (remove tags with
|
|
delete/domain/tag); a tag the domain has already ends the request
|
|
without an answer after the other values were saved. A domain admin (UI session) can only change
|
|
`description` (with the ACL `domain_desc`), `gal` and `tags`. Rate
|
|
limits are set with edit/rl-domain. Errors per domain:
|
|
`domain_invalid`, `mailbox_defquota_exceeds_mailbox_maxquota`,
|
|
`defquota_empty`, `mailbox_quota_exceeds_domain_quota`,
|
|
`maxquota_empty`, `max_quota_in_use`, `domain_quota_m_in_use`,
|
|
`mailboxes_in_use`, `aliases_in_use`; success `domain_modified`.
|
|
operationId: editDomain
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Domain name or list of domain names
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
description:
|
|
type: string
|
|
description: Description
|
|
aliases:
|
|
type: [integer, string]
|
|
description: Max. number of aliases
|
|
mailboxes:
|
|
type: [integer, string]
|
|
description: Max. number of mailboxes
|
|
defquota:
|
|
type: [integer, string]
|
|
description: Default quota of new mailboxes in MiB
|
|
maxquota:
|
|
type: [integer, string]
|
|
description: Max. quota per mailbox in MiB
|
|
quota:
|
|
type: [integer, string]
|
|
description: Quota of the whole domain in MiB
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Domain active
|
|
gal:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Global address list in SOGo
|
|
backupmx:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Relay this domain (backup MX)
|
|
relay_all_recipients:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Relay all recipients
|
|
relay_unknown_only:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Relay non-existing mailboxes only
|
|
relayhost:
|
|
type: [integer, string]
|
|
description: >-
|
|
ID of the sender-dependent transport (get/relayhost/all)
|
|
the domain sends through, 0 = none
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Tags to add
|
|
example:
|
|
items:
|
|
- example.org
|
|
attr:
|
|
description: Example Org
|
|
aliases: 400
|
|
mailboxes: 20
|
|
defquota: 3072
|
|
maxquota: 10240
|
|
quota: 51200
|
|
active: 1
|
|
gal: 1
|
|
backupmx: 0
|
|
relay_all_recipients: 0
|
|
relay_unknown_only: 0
|
|
relayhost: 0
|
|
tags:
|
|
- premium
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/domain/footer:
|
|
post:
|
|
summary: Set the domain-wide footer
|
|
description: >-
|
|
Sets the footer that is added to all outgoing mails of addresses of the
|
|
domains. The footer is replaced as a whole: values not sent are emptied.
|
|
The footer texts can use `{= auth_user =}`, `{= from_user =}`,
|
|
`{= from_name =}`, `{= from_addr =}`, `{= from_domain =}` and custom
|
|
mailbox attributes like `{= foo =}`. Entries of `exclude` that are no
|
|
existing mailbox, alias or alias domain are reported with
|
|
`username_invalid` and left out. Success `domain_footer_modified`,
|
|
errors `domain_invalid`, `access_denied` (both stop the call).
|
|
operationId: editDomainFooter
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Domain name or list of domain names
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
html:
|
|
type: string
|
|
default: ""
|
|
description: HTML footer
|
|
plain:
|
|
type: string
|
|
default: ""
|
|
description: Plain text footer
|
|
skip_replies:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: No footer in replies
|
|
exclude:
|
|
description: >-
|
|
Mailboxes, aliases (addresses) and alias domains that
|
|
get no footer
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
example:
|
|
items:
|
|
- example.org
|
|
attr:
|
|
html: "<p>Example Org · {= from_name =}</p>"
|
|
plain: "Example Org - {= from_name =}"
|
|
skip_replies: 1
|
|
exclude:
|
|
- noreply@example.org
|
|
- example.com
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/fail2ban:
|
|
post:
|
|
summary: Edit Fail2Ban settings, bans and filters
|
|
description: >-
|
|
Changes Fail2Ban (admins only, an API key may). What happens depends
|
|
on `attr.action`:
|
|
|
|
|
|
- `unban`, `whitelist`, `blacklist` act on the networks in `items`:
|
|
queue the unban; add to the allowlist (and unban); add to the
|
|
denylist (not `0.0.0.0/0` or the mailcow networks). Answer
|
|
`object_modified` per network; `network_host_invalid` (danger)
|
|
for an invalid network with `whitelist`/`blacklist` (`unban`
|
|
skips it silently).
|
|
- `unban-all` queues all active bans for unbanning (the denylist
|
|
stays). Answer `f2b_modified`.
|
|
- `edit-regex` replaces the regex filters with the list in
|
|
`attr.regex` (numbered from 1). Answer `f2b_modified`.
|
|
- `reset-regex` restores the default filters and waits up to 15
|
|
seconds for netfilter (`reset_f2b_regex` (danger) when it takes
|
|
longer). Send a non-empty `items` (the UI sends `["self"]`); the
|
|
answer is `object_modified` per item.
|
|
- Without `action` the settings are saved. Values that are not sent
|
|
keep their value, except `ban_time_increment` and
|
|
`manage_external`, which become 0, and `whitelist`/`blacklist`
|
|
replace the lists. Values are clamped: `ban_time`, `max_ban_time`
|
|
at least 60, `max_attempts`, `retry_window` at least 1,
|
|
`netban_ipv4` 8-32, `netban_ipv6` 8-128. Answer `f2b_modified`,
|
|
`network_host_invalid` (danger) for every entry of the lists that
|
|
is left out.
|
|
|
|
An `unban`, `whitelist`, `blacklist` or `reset-regex` without `items`
|
|
saves the settings like a call without `action` (and so turns off
|
|
`ban_time_increment` and `manage_external`); an unknown `action` with
|
|
`items` answers `object_modified` without changing anything.
|
|
`access_denied` for non-admins.
|
|
operationId: editFail2Ban
|
|
tags:
|
|
- Fail2Ban
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: Networks or IPs for `unban`, `whitelist`, `blacklist` (single value or list)
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: string
|
|
- type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
action:
|
|
type: string
|
|
enum:
|
|
- unban
|
|
- whitelist
|
|
- blacklist
|
|
- unban-all
|
|
- edit-regex
|
|
- reset-regex
|
|
regex:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: "`edit-regex`: the regex filters; the first group must match the IP"
|
|
ban_time:
|
|
type: [integer, string]
|
|
description: Ban time in seconds (min. 60)
|
|
ban_time_increment:
|
|
type: [boolean, integer, string]
|
|
description: 1 = the ban time grows with every ban of a network; not sent = 0
|
|
max_ban_time:
|
|
type: [integer, string]
|
|
description: Maximum ban time in seconds (min. 60)
|
|
max_attempts:
|
|
type: [integer, string]
|
|
description: Failed logins within `retry_window` that lead to a ban (min. 1)
|
|
retry_window:
|
|
type: [integer, string]
|
|
description: Window in seconds for `max_attempts` (min. 1)
|
|
netban_ipv4:
|
|
type: [integer, string]
|
|
description: IPv4 prefix length that is banned (8-32)
|
|
netban_ipv6:
|
|
type: [integer, string]
|
|
description: IPv6 prefix length that is banned (8-128)
|
|
whitelist:
|
|
type: string
|
|
description: Allowlist, networks or host names separated by space, comma, semicolon or newline; replaces the list
|
|
blacklist:
|
|
type: string
|
|
description: Denylist, networks separated by space, comma, semicolon or newline; replaces the list
|
|
manage_external:
|
|
type: [boolean, integer, string]
|
|
description: 1 = netfilter only keeps the banlist and sets no rules (block with the banlist URL externally); not sent = 0
|
|
required:
|
|
- attr
|
|
examples:
|
|
settings:
|
|
summary: Save the settings
|
|
value:
|
|
items: []
|
|
attr:
|
|
ban_time: "1800"
|
|
ban_time_increment: "1"
|
|
max_ban_time: "86400"
|
|
max_attempts: "10"
|
|
retry_window: "600"
|
|
netban_ipv4: "32"
|
|
netban_ipv6: "128"
|
|
whitelist: |-
|
|
192.0.2.0/24
|
|
mail.example.org
|
|
blacklist: 198.51.100.66/32
|
|
manage_external: "0"
|
|
unban:
|
|
summary: Unban a network
|
|
value:
|
|
items:
|
|
- 203.0.113.7/32
|
|
attr:
|
|
action: unban
|
|
regex:
|
|
summary: Replace the regex filters
|
|
value:
|
|
items:
|
|
- self
|
|
attr:
|
|
action: edit-regex
|
|
regex:
|
|
- "^mailcow UI: Invalid password for .+ by ([0-9a-f\\.:]+)$"
|
|
- "^Rspamd UI: Invalid password by ([0-9a-f\\.:]+)$"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/mailbox:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Update mailboxes
|
|
operationId: editMailbox
|
|
description: >-
|
|
Changes the given mailboxes. Fields that are not sent keep their value,
|
|
except `attribute_hash`, which is cleared. Admins and domain admins (for
|
|
their domains); a mailbox user gets `access_denied`. Some fields need an
|
|
ACL of domain admins and are silently ignored without it: `sogo_access`
|
|
(sogo_access), the protocol fields (protocol_access), `relayhost`
|
|
(mailbox_relayhost), `extended_sender_acl` (extend_sender_acl, error
|
|
`extended_sender_acl_denied`); API keys have all ACLs.
|
|
|
|
|
|
Messages per mailbox: `mailbox_modified` or `username_invalid`,
|
|
`access_denied`, `mailbox_quota_left_exceeded`,
|
|
`mailbox_quota_exceeded`, `password_complexity`, `password_mismatch`,
|
|
`sender_acl_invalid`, `extra_acl_invalid`, `extra_acl_invalid_domain`.
|
|
Quota 0 (unlimited) for a mailbox with a quota needs the
|
|
`unlimited_quota` ACL (`unlimited_quota_acl`, stops the call).
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
$ref: "#/components/schemas/MailboxEdit"
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
name: John Doe
|
|
quota: 5120
|
|
active: 1
|
|
protocol_access:
|
|
- imap
|
|
- smtp
|
|
- sieve
|
|
- dav
|
|
sender_acl:
|
|
- sales@example.org
|
|
- "@example.com"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/mailbox/custom-attribute:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Set custom attributes of mailboxes
|
|
operationId: editMailboxCustomAttributes
|
|
description: >-
|
|
Replaces the custom attributes (free key/value pairs, e.g. for
|
|
identity provider mappings) of the given mailboxes: `attribute[i]`
|
|
gets `value[i]`, attributes that are not sent are removed; spaces in
|
|
attribute names are removed. Both lists must have the same length.
|
|
Admins and domain admins (for their domains). Messages per mailbox:
|
|
`mailbox_modified`, `username_invalid`, `access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
properties:
|
|
attribute:
|
|
description: Attribute names (a single string is one name)
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
value:
|
|
description: Values, in the order of `attribute`
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
attribute:
|
|
- department
|
|
- employee_id
|
|
value:
|
|
- Sales
|
|
- "4711"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/mailbox-group:
|
|
post:
|
|
summary: Update mailbox groups
|
|
description: >-
|
|
Applies `attr` to every group in `items`, attributes that are not sent
|
|
keep their value. The domain of a group cannot be changed. `members`
|
|
replaces the manual members the caller may access; members added by the
|
|
identity provider sync (`source` idp) stay and cannot be removed here
|
|
(`group_member_idp`). Admins (every read/write API key) may edit every
|
|
group; domain admins need the `mailbox_groups` ACL, and groups with
|
|
send-as addresses or grants outside their domains are read-only for
|
|
them.
|
|
|
|
|
|
Answers one message per id: `group_modified` (plus warnings as for
|
|
`add`) or the error of that group (`access_denied` for unknown ids and
|
|
ids that are no number, the errors listed for `add`).
|
|
operationId: editMailboxGroups
|
|
tags:
|
|
- Groups
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: >-
|
|
Group ids, a list or a single id. An `id` inside `attr`
|
|
replaces `items`.
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type:
|
|
- integer
|
|
- string
|
|
- type:
|
|
- integer
|
|
- string
|
|
attr:
|
|
allOf:
|
|
- $ref: "#/components/schemas/MailboxGroupAttributes"
|
|
- type: object
|
|
properties:
|
|
reapply_template:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: >-
|
|
Admins only: apply the effective templates to all
|
|
members again, also when nothing changed
|
|
default: 0
|
|
example:
|
|
items:
|
|
- 7
|
|
attr:
|
|
add_members:
|
|
- carol@example.org
|
|
remove_members:
|
|
- bob@example.org
|
|
sogo_grants:
|
|
- owner: shared@example.org
|
|
type: Calendar
|
|
folder: personal
|
|
access: write
|
|
subscribe: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/identity-provider-sync:
|
|
post:
|
|
summary: Request an identity sync run
|
|
description: >-
|
|
Admins only (every read/write API key). Queues a sync run of the
|
|
Identity Provider (Keycloak and LDAP); the identity sync cron starts it
|
|
within a minute, see `GET /api/v1/get/identity-provider/sync-status`.
|
|
An identical pending request is reused. `items` is not used.
|
|
|
|
|
|
Answers `iam_sync_requested`, or `iam_sync_mode_invalid`,
|
|
`iam_sync_unavailable` (no Keycloak or LDAP provider configured),
|
|
`access_denied`.
|
|
operationId: requestIdentitySync
|
|
tags:
|
|
- Identity Provider
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Not used
|
|
attr:
|
|
type: object
|
|
properties:
|
|
mode:
|
|
type: string
|
|
description: >-
|
|
`preview` lists the changes without applying them,
|
|
`run` applies them, `force` applies them without the
|
|
change limit (`offboarding_limit`)
|
|
enum:
|
|
- preview
|
|
- run
|
|
- force
|
|
default: run
|
|
example:
|
|
attr:
|
|
mode: preview
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/mailq:
|
|
post:
|
|
summary: Act on the mail queue
|
|
description: >-
|
|
Runs a Postfix queue command (admins only, an API key may):
|
|
|
|
|
|
- `hold` (`postsuper -h`), `unhold` (`postsuper -H`) and `deliver`
|
|
(`postqueue -i`) act on the queue IDs in `items`.
|
|
- `flush` (`postqueue -f`) tries to deliver the whole queue,
|
|
`super_delete` (`postsuper -d ALL`) deletes every queued message.
|
|
Both ignore `items`.
|
|
|
|
Messages: `queue_command_success`; `Error: command failed: ...`
|
|
(danger) with the output of the command; `unknown` (danger) when the
|
|
command gave no answer; `access_denied` for non-admins. An unknown
|
|
`action`, or `hold`/`unhold`/`deliver` without `items`, does nothing
|
|
and is answered with `Task completed`. Queue IDs that are not
|
|
hexadecimal are skipped.
|
|
operationId: editMailQueue
|
|
tags:
|
|
- Queue Manager
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: Queue ID or list of queue IDs (for `hold`, `unhold`, `deliver`)
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: string
|
|
- type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
action:
|
|
type: string
|
|
enum:
|
|
- hold
|
|
- unhold
|
|
- deliver
|
|
- flush
|
|
- super_delete
|
|
required:
|
|
- action
|
|
required:
|
|
- attr
|
|
examples:
|
|
hold:
|
|
summary: Hold two messages
|
|
value:
|
|
items:
|
|
- B98C6260CA1
|
|
- 4C1E8260D02
|
|
attr:
|
|
action: hold
|
|
flush:
|
|
summary: Flush the whole queue
|
|
value:
|
|
items: []
|
|
attr:
|
|
action: flush
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/pushover:
|
|
post:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Set the Pushover notifications of mailboxes
|
|
operationId: editPushover
|
|
description: >-
|
|
Saves the Pushover settings (push notification on new mail) of the
|
|
mailboxes, or removes them with `delete: "true"`. Needs the user ACL
|
|
`pushover` (domain admins: their own ACL `pushover`, off by default).
|
|
API keys may change any mailbox, a mailbox user only its own (the UI
|
|
sends its address as `items`). `key` and `token` must be sent the first
|
|
time; later, empty fields keep their value. Messages per mailbox:
|
|
`pushover_settings_edited` or `access_denied`, `pushover_key`,
|
|
`pushover_token`, "Invalid regex".
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
properties:
|
|
key:
|
|
type: string
|
|
description: Pushover user key, 30 letters and digits
|
|
token:
|
|
type: string
|
|
description: Pushover application token, 30 letters and digits
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
title:
|
|
type: string
|
|
description: Title of the notification (default "Mail")
|
|
text:
|
|
type: string
|
|
description: Text of the notification
|
|
senders:
|
|
type: string
|
|
description: Only notify for these senders (addresses separated by comma, space or semicolon; invalid ones are dropped)
|
|
senders_regex:
|
|
type: string
|
|
description: Only notify for senders matching this regular expression
|
|
evaluate_x_prio:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: 1 sends high-priority mails as high-priority notifications (0 when not sent)
|
|
only_x_prio:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: 1 notifies for high-priority mails only (0 when not sent)
|
|
sound:
|
|
type: string
|
|
description: Pushover sound name (empty when not sent)
|
|
delete:
|
|
type: string
|
|
enum:
|
|
- "true"
|
|
description: '"true" removes the Pushover settings, other fields are ignored'
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
key: uQiRzpo4DXghDmr9QzzfQu27cmVRsG
|
|
token: azGDORePK8gMaC0QOYAMyEEuzJnyUi
|
|
active: 1
|
|
title: New mail
|
|
text: You've got mail
|
|
senders: boss@example.org
|
|
evaluate_x_prio: 1
|
|
only_x_prio: 0
|
|
sound: pushover
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/quarantine_notification:
|
|
post:
|
|
tags:
|
|
- Quarantine
|
|
summary: Set the quarantine notification interval of mailboxes
|
|
operationId: editQuarantineNotification
|
|
description: >-
|
|
How often the mailbox user gets a summary of quarantined mail. Needs
|
|
the user ACL `quarantine_notification`. API keys may change any
|
|
mailbox, a mailbox user only its own. `quarantine_notification` must be
|
|
sent: without it the call fails with an empty answer. Messages per
|
|
mailbox: `mailbox_modified` or `access_denied` (also for an invalid
|
|
value).
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
required:
|
|
- quarantine_notification
|
|
properties:
|
|
quarantine_notification:
|
|
type: string
|
|
enum:
|
|
- never
|
|
- hourly
|
|
- daily
|
|
- weekly
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
quarantine_notification: daily
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/syncjob:
|
|
post:
|
|
summary: Update sync jobs
|
|
description: >-
|
|
Applies `attr` to every job in `items`; attributes that are not sent
|
|
keep their value, an empty `password1` or `user1` keeps the stored one.
|
|
The local mailbox (`username`) cannot be changed. Needs the `syncjobs`
|
|
ACL and access to the local mailbox of each job (admins and API keys:
|
|
every job). The source is only checked again when `source_id` changes.
|
|
Sending `last_run` or `success` (any value except null) resets that
|
|
field. `prio` is set by admins only.
|
|
|
|
|
|
Answers one message per id: `mailbox_modified` with the local mailbox,
|
|
or the error of that job (`access_denied` for unknown jobs and ids that
|
|
are no number, otherwise the errors of `add`).
|
|
operationId: editSyncJobs
|
|
tags:
|
|
- Sync jobs
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: >-
|
|
Job ids, a list or a single id. An `id` inside `attr`
|
|
replaces `items`.
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type:
|
|
- integer
|
|
- string
|
|
- type:
|
|
- integer
|
|
- string
|
|
attr:
|
|
allOf:
|
|
- $ref: "#/components/schemas/SyncJobAttributes"
|
|
- type: object
|
|
properties:
|
|
last_run:
|
|
description: Any value except null resets the last run time (the job is due again)
|
|
success:
|
|
description: Any value except null resets the result of the last run
|
|
prio:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: >-
|
|
Admins only: queue priority, higher runs first (see
|
|
`edit/syncjob/run_next`)
|
|
example:
|
|
items:
|
|
- 12
|
|
- 13
|
|
attr:
|
|
active: 0
|
|
mins_interval: 60
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/syncjob/run_next:
|
|
post:
|
|
summary: Run sync jobs next
|
|
description: >-
|
|
Admins only (every read/write API key): moves the jobs to the front of
|
|
the queue. Each job gets a `prio` above the current maximum, `last_run`
|
|
and `success` are cleared, so the runner starts them next. Values in
|
|
`items` that are no number are ignored, `attr` is not used.
|
|
|
|
|
|
Answers `imapsync_job_running` (danger) for each job that is running
|
|
right now and `imapsync_run_next_done` with the number of moved jobs.
|
|
When no job was moved and none is running (e.g. unknown ids) the answer
|
|
is `{"type": "error", "msg": "Cannot edit item"}`; without valid ids
|
|
`access_denied`.
|
|
operationId: runSyncJobsNext
|
|
tags:
|
|
- Sync jobs
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
description: Job ids
|
|
type: array
|
|
items:
|
|
type:
|
|
- integer
|
|
- string
|
|
attr:
|
|
description: Not used
|
|
type: object
|
|
example:
|
|
items:
|
|
- 12
|
|
attr: {}
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/syncjob_source:
|
|
post:
|
|
summary: Update sync sources
|
|
description: >-
|
|
Applies `attr` to every source in `items` (ids that are no number are
|
|
skipped); attributes that are not sent keep their value, an empty
|
|
`oauth_client_secret` keeps the stored secret. Domains and users are
|
|
only replaced when `scope` is sent. Needs the `syncjobs` ACL and edit
|
|
rights on the source (admins and API keys: every source; others the
|
|
sources they created, domain admins also those of their mailboxes).
|
|
Changing the server or the OAuth2 client drops the stored tokens.
|
|
Changing the server or the OAuth2 client, or turning `verify_cert` off,
|
|
needs access to every mailbox whose jobs use the source
|
|
(`imapsync_source_used_by_others`). A client_credentials source fetches
|
|
a new token while it is saved.
|
|
|
|
|
|
Answers one message per id: `imapsync_source_modified` (plus
|
|
`imapsync_source_token_refresh_failed` when the new token could not be
|
|
fetched), or the error of that source (`access_denied` for unknown
|
|
ids, the errors of `add`).
|
|
operationId: editSyncJobSources
|
|
tags:
|
|
- Sync jobs
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: >-
|
|
Source ids, a list or a single id. An `id` inside `attr`
|
|
replaces `items`.
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type:
|
|
- integer
|
|
- string
|
|
- type:
|
|
- integer
|
|
- string
|
|
attr:
|
|
$ref: "#/components/schemas/SyncJobSourceAttributes"
|
|
example:
|
|
items:
|
|
- 3
|
|
attr:
|
|
description: Migration finished in December
|
|
scope: user
|
|
users:
|
|
- alice@example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/syncjob_source/refresh_token:
|
|
post:
|
|
summary: Refresh the token of a sync source
|
|
description: >-
|
|
Fetches a new OAuth2 token for a XOAUTH2 client_credentials source now
|
|
(the cron refreshes tokens before they expire). Only the first id of
|
|
`items` is used, `attr` is not used. Needs the `syncjobs` ACL and edit
|
|
rights on the source. Answers `imapsync_source_token_refreshed`, or
|
|
`imapsync_source_refresh_unsupported` (other sources),
|
|
`imapsync_source_token_refresh_failed` (with the provider error),
|
|
`access_denied` (unknown id, id that is no number, no edit rights).
|
|
operationId: refreshSyncJobSourceToken
|
|
tags:
|
|
- Sync jobs
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
description: Source id (the first entry is used)
|
|
type: array
|
|
items:
|
|
type:
|
|
- integer
|
|
- string
|
|
attr:
|
|
description: Not used
|
|
type: object
|
|
example:
|
|
items:
|
|
- 5
|
|
attr: {}
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/imapsync_settings:
|
|
post:
|
|
summary: Update global sync job settings
|
|
description: >-
|
|
Admins only (every read/write API key). Sets how many sync jobs run at
|
|
the same time and the bandwidth limit of every sync job process (a
|
|
lower per-job `maxbytespersecond` still applies). `items` is not used.
|
|
Answers `max_parallel_saved`, or `imapsync_max_parallel_invalid`,
|
|
`imapsync_max_kb_per_second_invalid`, `access_denied`.
|
|
operationId: editSyncJobSettings
|
|
tags:
|
|
- Sync jobs
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Not used
|
|
attr:
|
|
type: object
|
|
required:
|
|
- max_parallel
|
|
properties:
|
|
max_parallel:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: Sync jobs running at the same time, 1-32
|
|
minimum: 1
|
|
maximum: 32
|
|
max_kb_per_second:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: >-
|
|
Bandwidth limit per sync job process in KB/s, 0-10485760
|
|
(stored as bytes/s); 0, empty or not sent = unlimited
|
|
default: 0
|
|
minimum: 0
|
|
maximum: 10485760
|
|
example:
|
|
attr:
|
|
max_parallel: 4
|
|
max_kb_per_second: 2000
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/user-acl:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Set the ACL of mailboxes
|
|
operationId: editUserAcl
|
|
description: >-
|
|
Sets the user ACL (what a mailbox user may change in the UI) of the
|
|
given mailboxes: listed ACLs are switched on, all others off. Admins
|
|
and domain admins (for their domains); a domain admin cannot change
|
|
ACLs that it does not have itself. Mailbox users get `access_denied`.
|
|
Success: `acl_saved` per mailbox.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
properties:
|
|
user_acl:
|
|
description: ACLs to switch on (a single string is one ACL); an empty list switches all off
|
|
oneOf:
|
|
- $ref: "#/components/schemas/UserAclName"
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/UserAclName"
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
user_acl:
|
|
- spam_alias
|
|
- tls_policy
|
|
- spam_score
|
|
- spam_policy
|
|
- delimiter_action
|
|
- eas_reset
|
|
- pushover
|
|
- quarantine
|
|
- quarantine_notification
|
|
- app_passwds
|
|
- pw_reset
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/alias/{id}:
|
|
get:
|
|
tags:
|
|
- Aliases
|
|
summary: Get aliases
|
|
operationId: getAliases
|
|
description: >-
|
|
`all` lists the aliases of every domain and alias domain the caller
|
|
manages (an API key: all), an ID or address returns that alias.
|
|
Mailbox addresses (alias rows pointing to themselves) are not listed.
|
|
`{}` if there is none.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all`, or the ID or address of an alias"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The list of aliases (`all`) or one alias
|
|
content:
|
|
application/json:
|
|
schema:
|
|
anyOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/Alias"
|
|
- $ref: "#/components/schemas/Alias"
|
|
examples:
|
|
all:
|
|
summary: get/alias/all
|
|
value:
|
|
- in_primary_domain: ""
|
|
id: 12
|
|
domain: example.org
|
|
public_comment: Sales team
|
|
private_comment: null
|
|
goto: anna@example.org,ben@example.org
|
|
address: sales@example.org
|
|
is_catch_all: 0
|
|
internal: 0
|
|
active: 1
|
|
active_int: 1
|
|
sogo_visible: 1
|
|
sogo_visible_int: 1
|
|
sender_allowed: 1
|
|
group_id: null
|
|
group_name: null
|
|
created: "2026-10-26 14:43:58"
|
|
modified: "2026-11-08 20:38:01"
|
|
- in_primary_domain: example.org
|
|
id: 20
|
|
domain: example.net
|
|
public_comment: ""
|
|
private_comment: ""
|
|
goto: null@localhost
|
|
address: "@example.net"
|
|
is_catch_all: 1
|
|
internal: 0
|
|
active: 1
|
|
active_int: 1
|
|
sogo_visible: 0
|
|
sogo_visible_int: 0
|
|
sender_allowed: 0
|
|
group_id: null
|
|
group_name: null
|
|
created: "2026-11-02 09:12:40"
|
|
modified: null
|
|
one:
|
|
summary: get/alias/12
|
|
value:
|
|
in_primary_domain: ""
|
|
id: 12
|
|
domain: example.org
|
|
public_comment: Sales team
|
|
private_comment: null
|
|
goto: anna@example.org,ben@example.org
|
|
address: sales@example.org
|
|
is_catch_all: 0
|
|
internal: 0
|
|
active: 1
|
|
active_int: 1
|
|
sogo_visible: 1
|
|
sogo_visible_int: 1
|
|
sender_allowed: 1
|
|
group_id: null
|
|
group_name: null
|
|
created: "2026-10-26 14:43:58"
|
|
modified: "2026-11-08 20:38:01"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/alias/all/{domains}:
|
|
get:
|
|
tags:
|
|
- Aliases
|
|
summary: Get the aliases of domains
|
|
operationId: getAliasesByDomain
|
|
description: >-
|
|
Lists the aliases of the named domains or alias domains. Domains the
|
|
caller does not manage are skipped. `{}` if there is none.
|
|
parameters:
|
|
- name: domains
|
|
in: path
|
|
required: true
|
|
description: Comma-separated domain names
|
|
schema:
|
|
type: string
|
|
example: example.org,example.net
|
|
responses:
|
|
"200":
|
|
description: The list of aliases
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Alias"
|
|
example:
|
|
- in_primary_domain: ""
|
|
id: 12
|
|
domain: example.org
|
|
public_comment: Sales team
|
|
private_comment: null
|
|
goto: anna@example.org,ben@example.org
|
|
address: sales@example.org
|
|
is_catch_all: 0
|
|
internal: 0
|
|
active: 1
|
|
active_int: 1
|
|
sogo_visible: 1
|
|
sogo_visible_int: 1
|
|
sender_allowed: 1
|
|
group_id: null
|
|
group_name: null
|
|
created: "2026-10-26 14:43:58"
|
|
modified: "2026-11-08 20:38:01"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/time_limited_aliases/{mailbox}:
|
|
get:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Get the time-limited aliases of a mailbox
|
|
operationId: getTimeLimitedAliases
|
|
description: >-
|
|
The time-limited aliases of the mailbox that are still valid or
|
|
permanent. `{}` when there are none or the caller has no access (a
|
|
mailbox user: other mailboxes). If `{mailbox}` is no address, the
|
|
session user's aliases are returned (nothing for API keys).
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: List of aliases
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/TimeLimitedAlias"
|
|
example:
|
|
- address: kahd.osuwe@example.org
|
|
goto: john.doe@example.org
|
|
description: Online shop registration
|
|
validity: 1795699200
|
|
created: "2026-11-10 09:00:00"
|
|
modified: null
|
|
permanent: 0
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/time_limited_alias:
|
|
post:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Update time-limited aliases
|
|
operationId: editTimeLimitedAlias
|
|
description: >-
|
|
Sets a new expiry (`validity` hours from now) or makes the aliases
|
|
permanent. Needs the user ACL `spam_alias` and access to the target
|
|
mailbox (API keys: any, mailbox users: their own). Aliases are skipped
|
|
silently when neither `validity` nor a true `permanent` is sent.
|
|
Messages per alias: `mailbox_modified` (without the address) or
|
|
`access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Alias address or list of addresses
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
validity:
|
|
type: [integer, string]
|
|
description: Hours from now until the alias expires (not range-checked); ends a permanent state
|
|
permanent:
|
|
type: [boolean, integer, string]
|
|
description: true makes the alias permanent (wins over `validity`)
|
|
example:
|
|
items:
|
|
- kahd.osuwe@example.org
|
|
attr:
|
|
validity: 24
|
|
permanent: 0
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/time_limited_alias:
|
|
post:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Delete time-limited aliases
|
|
operationId: deleteTimeLimitedAlias
|
|
description: >-
|
|
Deletes time-limited aliases. Needs the user ACL `spam_alias` and
|
|
access to the target mailbox (API keys: any, mailbox users: their own).
|
|
Messages per alias: `mailbox_modified` or `access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Alias addresses
|
|
items:
|
|
type: string
|
|
example:
|
|
- kahd.osuwe@example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/pushover-test:
|
|
post:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Verify the Pushover credentials of mailboxes
|
|
operationId: testPushover
|
|
description: >-
|
|
Checks the stored Pushover key and token of each mailbox with the
|
|
Pushover API; `attr` is not used. Same access rules as `edit/pushover`.
|
|
Messages per mailbox: "Pushover API OK (200): ..." (success) or
|
|
"Pushover API ERR (code): ..." (danger), `access_denied`; a mailbox
|
|
without settings stops the call with `pushover_credentials_missing`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
description: Not used
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr: {}
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/delimiter_action:
|
|
post:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Set the handling of tagged mail
|
|
operationId: editDelimiterAction
|
|
description: >-
|
|
What happens to mail for `user+tag@example.org`: moved to the subfolder
|
|
"tag" (`subfolder`), "[tag]" added to the subject (`subject`), or
|
|
nothing (`none`, also for any other value). Needs the user ACL
|
|
`delimiter_action`. API keys may change any mailbox, a mailbox user
|
|
only its own. Messages per mailbox: `mailbox_modified` or
|
|
`access_denied`, `redis_error`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
properties:
|
|
tagged_mail_handler:
|
|
type: string
|
|
enum:
|
|
- subfolder
|
|
- subject
|
|
- none
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
tagged_mail_handler: subfolder
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/tls_policy:
|
|
post:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Set the TLS policy of mailboxes
|
|
operationId: editTlsPolicy
|
|
description: >-
|
|
Enforces TLS for incoming and/or outgoing mail of the mailboxes; a
|
|
field that is not sent keeps its value. Needs the user ACL
|
|
`tls_policy`. API keys may change any mailbox, a mailbox user only its
|
|
own. Messages per mailbox: `mailbox_modified` or `access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
properties:
|
|
tls_enforce_in:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: 1 accepts incoming mail only over TLS
|
|
tls_enforce_out:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: 1 sends outgoing mail only over TLS
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
tls_enforce_in: 1
|
|
tls_enforce_out: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/spam-score:
|
|
get:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Get the default spam score
|
|
operationId: getDefaultSpamScore
|
|
description: >-
|
|
The spam score thresholds of the session user; for API keys, which have
|
|
no mailbox, the server default from the Rspamd actions ("add header"
|
|
and "reject"; "5,15" if Rspamd cannot be asked).
|
|
responses:
|
|
"200":
|
|
description: Thresholds
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SpamScore"
|
|
example:
|
|
score: "8,15"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/api-key/{id}:
|
|
get:
|
|
summary: Get API key
|
|
description: One API key including its key value. A read-only API key gets `{}`.
|
|
operationId: getApiKey
|
|
tags:
|
|
- API Keys
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: ID of the API key
|
|
schema:
|
|
type: integer
|
|
example: 3
|
|
responses:
|
|
"200":
|
|
description: The API key, `{}` if there is none with this ID or for a read-only API key
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ApiKey"
|
|
example:
|
|
id: 3
|
|
description: provisioning
|
|
access: rw
|
|
api_key: 1B7E2C-94F0A3-6D5B18-C2E7F4-03A9D6
|
|
allow_from:
|
|
- 192.0.2.10
|
|
- 2001:db8::/64
|
|
skip_ip_check: 0
|
|
service: 0
|
|
active: 1
|
|
created: "2026-11-02 09:12:44"
|
|
modified: "2026-11-05 16:40:02"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/api-key/all:
|
|
get:
|
|
summary: Get API keys
|
|
description: >-
|
|
Lists all API keys including their key values, service keys from
|
|
mailcow.conf first. A read-only API key gets `{}`: it may not see the
|
|
keys.
|
|
operationId: getApiKeys
|
|
tags:
|
|
- API Keys
|
|
responses:
|
|
"200":
|
|
description: The API keys, `{}` if there are none or for a read-only API key
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ApiKey"
|
|
example:
|
|
- id: 1
|
|
description: API_KEY
|
|
access: rw
|
|
api_key: 8F2D41-0C9A7B-5E3F12-AB46C0-77D1E9
|
|
allow_from:
|
|
- 192.0.2.0/24
|
|
skip_ip_check: 0
|
|
service: 1
|
|
active: 1
|
|
created: "2026-09-21 10:20:00"
|
|
modified: null
|
|
- id: 3
|
|
description: provisioning
|
|
access: rw
|
|
api_key: 1B7E2C-94F0A3-6D5B18-C2E7F4-03A9D6
|
|
allow_from:
|
|
- 192.0.2.10
|
|
- 2001:db8::/64
|
|
skip_ip_check: 0
|
|
service: 0
|
|
active: 1
|
|
created: "2026-11-02 09:12:44"
|
|
modified: "2026-11-05 16:40:02"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/app-passwd/all/{mailbox}:
|
|
get:
|
|
tags:
|
|
- App Passwords
|
|
summary: Get the app passwords of a mailbox
|
|
operationId: getAppPasswords
|
|
description: >-
|
|
The app passwords of the mailbox, including the password hashes. `{}`
|
|
if there are none or the caller has no access to the mailbox (a
|
|
mailbox user: other mailboxes).
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: List of app passwords
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/AppPassword"
|
|
example:
|
|
- id: 23
|
|
name: Thunderbird
|
|
mailbox: john.doe@example.org
|
|
domain: example.org
|
|
password: "{BLF-CRYPT}$2y$10$..."
|
|
created: "2026-11-08 20:38:01"
|
|
modified: null
|
|
imap_access: 1
|
|
smtp_access: 1
|
|
dav_access: 0
|
|
eas_access: 0
|
|
pop3_access: 0
|
|
sieve_access: 1
|
|
active: 1
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/app-passwd/all:
|
|
get:
|
|
tags:
|
|
- App Passwords
|
|
summary: Get the app passwords of the logged-in mailbox
|
|
operationId: getOwnAppPasswords
|
|
description: >-
|
|
The app passwords of the session user. Meant for a mailbox user
|
|
session; an API key has no mailbox and gets `{}` (use
|
|
`get/app-passwd/all/{mailbox}`).
|
|
responses:
|
|
"200":
|
|
description: List of app passwords
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/AppPassword"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/app-passwd/{id}:
|
|
get:
|
|
tags:
|
|
- App Passwords
|
|
summary: Get an app password (broken)
|
|
operationId: getAppPassword
|
|
description: >-
|
|
Does not work: json_api.php reads `$object['id']` from the path segment,
|
|
which is a string, so the request ends with an error and an empty body.
|
|
Use `get/app-passwd/all/{mailbox}`.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: App password ID
|
|
schema:
|
|
type: integer
|
|
example: 23
|
|
responses:
|
|
"200":
|
|
description: Empty body
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/app-passwd:
|
|
post:
|
|
tags:
|
|
- App Passwords
|
|
summary: Update app passwords
|
|
operationId: editAppPassword
|
|
description: >-
|
|
Changes app passwords by ID; fields that are not sent keep their value.
|
|
Needs the user ACL `app_passwds`. The app passwords are assigned to
|
|
`username`, which defaults to the session user: API keys must send the
|
|
mailbox the app passwords belong to (without it the backend tries to
|
|
assign them to "API", the database refuses that and the answer is
|
|
empty); a mailbox user may leave it out. Messages per ID:
|
|
`object_modified`, `app_passwd_id_invalid`, `password_complexity`,
|
|
`password_mismatch`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: App password ID or list of IDs
|
|
oneOf:
|
|
- type: integer
|
|
- type: array
|
|
items:
|
|
type: integer
|
|
attr:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Mailbox the app passwords belong to (required for API keys)
|
|
app_name:
|
|
type: string
|
|
app_passwd:
|
|
type: string
|
|
format: password
|
|
description: New password; changed only together with `app_passwd2`
|
|
app_passwd2:
|
|
type: string
|
|
format: password
|
|
protocols:
|
|
description: Replaces the allowed protocols
|
|
type: array
|
|
items:
|
|
type: string
|
|
enum:
|
|
- imap_access
|
|
- smtp_access
|
|
- pop3_access
|
|
- sieve_access
|
|
- dav_access
|
|
- eas_access
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
example:
|
|
items:
|
|
- 23
|
|
attr:
|
|
username: john.doe@example.org
|
|
active: 0
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/bcc/{id}:
|
|
get:
|
|
tags:
|
|
- Address Rewriting
|
|
summary: Get BCC maps
|
|
operationId: getBccMaps
|
|
description: >-
|
|
`all` lists the BCC maps of the domains the caller manages (an API key:
|
|
all), an ID returns that map. `{}` if there is none. The answer for an
|
|
ID carries an additional member `"0": null` (json_api.php appends an
|
|
undefined variable).
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all` or the ID of a BCC map"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The list of BCC maps (`all`) or one BCC map
|
|
content:
|
|
application/json:
|
|
schema:
|
|
anyOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/BccMap"
|
|
- $ref: "#/components/schemas/BccMap"
|
|
examples:
|
|
all:
|
|
summary: get/bcc/all
|
|
value:
|
|
- id: 3
|
|
local_dest: "@example.org"
|
|
bcc_dest: archive@example.com
|
|
active: 1
|
|
type: rcpt
|
|
created: "2026-11-03 10:15:22"
|
|
domain: example.org
|
|
modified: null
|
|
one:
|
|
summary: get/bcc/3
|
|
value:
|
|
id: 3
|
|
local_dest: "@example.org"
|
|
bcc_dest: archive@example.com
|
|
active: 1
|
|
type: rcpt
|
|
created: "2026-11-03 10:15:22"
|
|
domain: example.org
|
|
modified: null
|
|
"0": null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/dkim/{domain}:
|
|
get:
|
|
summary: Get the DKIM key of a domain
|
|
description: >-
|
|
The DKIM public key of a domain or alias domain with the TXT record to
|
|
publish at `<selector>._domainkey.<domain>`; `{}` if it has none. The
|
|
private key is only answered when `SHOW_DKIM_PRIV_KEYS` is enabled in
|
|
vars.local.inc.php, else `privkey` is empty.
|
|
operationId: getDkimKey
|
|
tags:
|
|
- DKIM
|
|
parameters:
|
|
- name: domain
|
|
in: path
|
|
required: true
|
|
description: Domain or alias domain name
|
|
schema:
|
|
type: string
|
|
example: example.org
|
|
responses:
|
|
"200":
|
|
description: The DKIM key
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DkimKey"
|
|
example:
|
|
pubkey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxV3...IDAQAB
|
|
length: "2048"
|
|
dkim_txt: v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxV3...IDAQAB
|
|
dkim_selector: dkim
|
|
privkey: ""
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/add/dkim_import:
|
|
post:
|
|
summary: Import a DKIM key
|
|
description: >-
|
|
Imports an RSA private key as the DKIM key of a domain; the public key
|
|
is derived from it. Admins only. The domain name must be valid but is
|
|
not checked against the domains of mailcow. The old key of the domain
|
|
is removed first, so a successful import answers `dkim_removed` and
|
|
`dkim_added`. Errors `access_denied`, `private_key_error`,
|
|
`dkim_domain_or_sel_invalid`, `dkim_domain_or_sel_exists` (a key exists
|
|
and `overwrite_existing` is not set).
|
|
operationId: importDkimKey
|
|
tags:
|
|
- DKIM
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- domain
|
|
- private_key_file
|
|
properties:
|
|
domain:
|
|
type: string
|
|
description: Domain name
|
|
dkim_selector:
|
|
type: string
|
|
default: dkim
|
|
description: Selector (letters, digits, `-`, `_`, `.`)
|
|
private_key_file:
|
|
type: string
|
|
description: The private key in PEM format (the text, not a file upload)
|
|
overwrite_existing:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: Replace an existing key of the domain
|
|
example:
|
|
domain: example.org
|
|
dkim_selector: dkim2026
|
|
private_key_file: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC...\n-----END PRIVATE KEY-----"
|
|
overwrite_existing: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/domain-admin/all:
|
|
get:
|
|
summary: Get domain administrators
|
|
description: Lists all domain administrators with their details.
|
|
operationId: getDomainAdmins
|
|
tags:
|
|
- Domain admin
|
|
responses:
|
|
"200":
|
|
description: The domain administrators, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/DomainAdmin"
|
|
example:
|
|
- username: domainadmin1
|
|
tfa_active: 0
|
|
tfa_active_int: 0
|
|
active: 1
|
|
active_int: 1
|
|
created: "2026-09-21 10:24:48"
|
|
attributes:
|
|
force_tfa: "0"
|
|
force_pw_update: "0"
|
|
selected_domains:
|
|
- example.org
|
|
unselected_domains:
|
|
- example.com
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/domain-admin/{username}:
|
|
get:
|
|
summary: Get domain administrator
|
|
description: Details of one domain administrator.
|
|
operationId: getDomainAdmin
|
|
tags:
|
|
- Domain admin
|
|
parameters:
|
|
- name: username
|
|
in: path
|
|
required: true
|
|
description: Username of the domain administrator
|
|
schema:
|
|
type: string
|
|
example: domainadmin1
|
|
responses:
|
|
"200":
|
|
description: The domain administrator, `{}` if there is none of this name
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DomainAdmin"
|
|
example:
|
|
username: domainadmin1
|
|
tfa_active: 0
|
|
tfa_active_int: 0
|
|
active: 1
|
|
active_int: 1
|
|
created: "2026-09-21 10:24:48"
|
|
attributes:
|
|
force_tfa: "0"
|
|
force_pw_update: "0"
|
|
selected_domains:
|
|
- example.org
|
|
- example.com
|
|
unselected_domains: ""
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/domain/{id}:
|
|
get:
|
|
summary: Get domains
|
|
description: >-
|
|
`all` answers the list of all domains, a domain name answers that
|
|
domain. An alias domain name answers its target domain. An API key sees
|
|
every domain, a domain admin (UI session) only the domains assigned to
|
|
it. Quotas are in bytes. `{}` when nothing is found, also for `all`
|
|
without domains.
|
|
operationId: getDomains
|
|
tags:
|
|
- Domains
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all` or a domain name"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
- name: tags
|
|
in: query
|
|
required: false
|
|
description: >-
|
|
Only with `all`: comma-separated tag names, answers only the domains
|
|
with a tag that contains one of them
|
|
schema:
|
|
type: string
|
|
example: customer,premium
|
|
responses:
|
|
"200":
|
|
description: The list of domains (`all`) or one domain
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/Domain"
|
|
- $ref: "#/components/schemas/Domain"
|
|
example:
|
|
- max_new_mailbox_quota: 10632560640
|
|
def_new_mailbox_quota: 3221225472
|
|
quota_used_in_domain: "104857600"
|
|
bytes_total: "79324302"
|
|
msgs_total: "132"
|
|
mboxes_in_domain: 3
|
|
mboxes_left: 7
|
|
domain_name: example.org
|
|
domain_h_name: example.org
|
|
description: Example Org
|
|
max_num_aliases_for_domain: 400
|
|
max_num_mboxes_for_domain: 10
|
|
def_quota_for_mbox: 3221225472
|
|
max_quota_for_mbox: 10737418240
|
|
max_quota_for_domain: 10737418240
|
|
relayhost: "0"
|
|
backupmx: 0
|
|
backupmx_int: 0
|
|
gal: 1
|
|
gal_int: 1
|
|
rl:
|
|
value: "100"
|
|
frame: h
|
|
active: 1
|
|
active_int: 1
|
|
relay_all_recipients: 0
|
|
relay_all_recipients_int: 0
|
|
relay_unknown_only: 0
|
|
relay_unknown_only_int: 0
|
|
created: "2026-09-21 10:24:34"
|
|
modified: "2026-11-06 18:15:08"
|
|
aliases_in_domain: 1
|
|
aliases_left: 399
|
|
domain_admins: anna.admin
|
|
tags:
|
|
- customer
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/domain/template/{id}:
|
|
get:
|
|
summary: Get domain templates
|
|
description: >-
|
|
`all` answers the list of domain templates, an ID that template
|
|
(`{}` if there is none; a non-numeric ID is read as 0). Admins and
|
|
domain admins. The template attributes hold the quotas in bytes.
|
|
operationId: getDomainTemplates
|
|
tags:
|
|
- Domains
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all` or a template ID"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The list of templates (`all`) or one template
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/DomainTemplate"
|
|
- $ref: "#/components/schemas/DomainTemplate"
|
|
example:
|
|
- id: 1
|
|
template: Default
|
|
type: domain
|
|
attributes:
|
|
tags: []
|
|
max_num_aliases_for_domain: 400
|
|
max_num_mboxes_for_domain: 10
|
|
def_quota_for_mbox: 3221225472
|
|
max_quota_for_mbox: 10737418240
|
|
max_quota_for_domain: 10737418240
|
|
rl_frame: s
|
|
rl_value: ""
|
|
active: 1
|
|
gal: 1
|
|
backupmx: 0
|
|
relay_all_recipients: 0
|
|
relay_unknown_only: 0
|
|
dkim_selector: dkim
|
|
key_size: 2048
|
|
created: "2026-09-21 10:23:08"
|
|
modified: null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/add/domain/template:
|
|
post:
|
|
summary: Add a domain template
|
|
description: >-
|
|
Adds a domain template, the defaults for new domains (see `template` of
|
|
add/domain). Admins only. Quotas are sent in MiB and stored in bytes;
|
|
values not sent get the defaults shown (numbers and quotas also for
|
|
0). Success `template_added`,
|
|
errors `access_denied`, `template_name_invalid`, `template_exists`.
|
|
operationId: addDomainTemplate
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/DomainTemplateInput"
|
|
- required:
|
|
- template
|
|
example:
|
|
template: Small business
|
|
max_num_aliases_for_domain: 400
|
|
max_num_mboxes_for_domain: 25
|
|
def_quota_for_mbox: 2048
|
|
max_quota_for_mbox: 5120
|
|
max_quota_for_domain: 51200
|
|
rl_value: 500
|
|
rl_frame: h
|
|
active: 1
|
|
gal: 1
|
|
backupmx: 0
|
|
relay_all_recipients: 0
|
|
relay_unknown_only: 0
|
|
dkim_selector: dkim
|
|
key_size: 2048
|
|
tags:
|
|
- small
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/domain/template:
|
|
post:
|
|
summary: Edit domain templates
|
|
description: >-
|
|
Replaces the attributes of domain templates. Admins only. Send all
|
|
attributes: one that is not sent is reset (numbers and quotas to 0,
|
|
`tags` to none, `rl_frame` to `s`, `active` and `gal` to 1,
|
|
`dkim_selector` to `dkim`, `key_size` to 2048). The `Default` template
|
|
keeps its name. Edit one template per call: with several IDs the
|
|
templates after the first get the name of the first one. Unknown IDs
|
|
answer `template_id_invalid`; the call always ends with
|
|
`template_modified`.
|
|
operationId: editDomainTemplate
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Template ID or list of template IDs
|
|
oneOf:
|
|
- type: [integer, string]
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
attr:
|
|
$ref: "#/components/schemas/DomainTemplateInput"
|
|
example:
|
|
items:
|
|
- 2
|
|
attr:
|
|
template: Small business
|
|
max_num_aliases_for_domain: 400
|
|
max_num_mboxes_for_domain: 50
|
|
def_quota_for_mbox: 2048
|
|
max_quota_for_mbox: 5120
|
|
max_quota_for_domain: 102400
|
|
rl_value: 500
|
|
rl_frame: h
|
|
active: 1
|
|
gal: 1
|
|
backupmx: 0
|
|
relay_all_recipients: 0
|
|
relay_unknown_only: 0
|
|
dkim_selector: dkim
|
|
key_size: 2048
|
|
tags:
|
|
- small
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/domain/template:
|
|
post:
|
|
summary: Delete a domain template
|
|
description: >-
|
|
Deletes a domain template. Admins only. Only the first ID of the list
|
|
is deleted. The `Default` template is never deleted; the answer is
|
|
`template_removed` in every case.
|
|
operationId: deleteDomainTemplate
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Template IDs (only the first is used)
|
|
items:
|
|
type: [integer, string]
|
|
example:
|
|
- 2
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/search/domain:
|
|
post:
|
|
summary: Search domains (table of the UI)
|
|
description: >-
|
|
Paging, sorting and searching of domains with the server-side
|
|
processing parameters of DataTables, used by the domain table of the
|
|
UI. Admins (also read-only API keys) search all domains, domain admins
|
|
their domains; other logins get `403` with `Insufficient permissions`.
|
|
|
|
|
|
The position of an entry in `columns` (and `order[].column`) selects
|
|
the database column: 2 domain name, 3 max. aliases (sorted by the
|
|
number of aliases), 4 max. mailboxes (sorted by the number of
|
|
mailboxes), 5 domain quota (sorted by the quota of the mailboxes), 6
|
|
storage (sorting only), 7 default mailbox quota, 8 max. mailbox quota,
|
|
10 relay domain, 14 tags (global search only), 15 active; other positions
|
|
mean the domain name. `search.value` is searched (`LIKE %value%`) in
|
|
the columns with `searchable: true` (positions 2 and 14 in the UI),
|
|
`columns[].search.value` filters one column: the one whose position is
|
|
given in `data`, else the domain name. `orderable` and `searchable`
|
|
must be set (`true` or `"true"`). `columns` is required when
|
|
`search.value` is set.
|
|
|
|
|
|
Send `Content-Type: application/json`; without it the body is ignored
|
|
and all domains are answered. A database error answers
|
|
`{"error": "An SQL error occurred: ..."}` (status 200), e.g. a search
|
|
in position 6.
|
|
operationId: searchDomains
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DomainSearchRequest"
|
|
example:
|
|
draw: 1
|
|
start: 0
|
|
length: 10
|
|
search:
|
|
value: example
|
|
order:
|
|
- column: 2
|
|
dir: asc
|
|
columns:
|
|
- data: ""
|
|
searchable: false
|
|
orderable: false
|
|
- data: chkbox
|
|
searchable: false
|
|
orderable: false
|
|
- data: domain_h_name
|
|
searchable: true
|
|
orderable: true
|
|
search:
|
|
value: ""
|
|
responses:
|
|
"200":
|
|
description: One page of domains, with the counts DataTables needs
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DomainSearchResult"
|
|
example:
|
|
draw: 1
|
|
recordsTotal: 12
|
|
recordsFiltered: 1
|
|
data:
|
|
- max_new_mailbox_quota: 10632560640
|
|
def_new_mailbox_quota: 3221225472
|
|
quota_used_in_domain: "104857600"
|
|
bytes_total: "79324302"
|
|
msgs_total: "132"
|
|
mboxes_in_domain: 3
|
|
mboxes_left: 7
|
|
domain_name: example.org
|
|
domain_h_name: example.org
|
|
description: Example Org
|
|
max_num_aliases_for_domain: 400
|
|
max_num_mboxes_for_domain: 10
|
|
def_quota_for_mbox: 3221225472
|
|
max_quota_for_mbox: 10737418240
|
|
max_quota_for_domain: 10737418240
|
|
relayhost: "0"
|
|
backupmx: 0
|
|
backupmx_int: 0
|
|
gal: 1
|
|
gal_int: 1
|
|
rl: false
|
|
active: 1
|
|
active_int: 1
|
|
relay_all_recipients: 0
|
|
relay_all_recipients_int: 0
|
|
relay_unknown_only: 0
|
|
relay_unknown_only_int: 0
|
|
created: "2026-09-21 10:24:34"
|
|
modified: "2026-11-06 18:15:08"
|
|
aliases_in_domain: 1
|
|
aliases_left: 399
|
|
domain_admins: "-"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/alias-domain/{id}:
|
|
get:
|
|
summary: Get alias domains
|
|
description: >-
|
|
`all` answers the list of all alias domains, an alias domain name
|
|
answers that alias domain; `{}` when nothing is found. An API key sees
|
|
every alias domain, a domain admin those of its domains.
|
|
operationId: getAliasDomains
|
|
tags:
|
|
- Domains
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all` or an alias domain name"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The list of alias domains (`all`) or one alias domain
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/AliasDomain"
|
|
- $ref: "#/components/schemas/AliasDomain"
|
|
example:
|
|
- alias_domain: example.net
|
|
parent_is_backupmx: 0
|
|
target_domain: example.org
|
|
active: 1
|
|
active_int: 1
|
|
rl: false
|
|
created: "2026-10-02 08:12:45"
|
|
modified: null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/add/alias-domain:
|
|
post:
|
|
summary: Add alias domains
|
|
description: >-
|
|
Adds alias domains: mail to an address of the alias domain goes to the
|
|
same local part in the target domain. Needs the ACL `alias_domains`
|
|
(API keys have it) and access to the target domain, which must be an
|
|
existing domain and no relay domain. Like add/domain this can set the
|
|
rate limit and create a DKIM key for each alias domain. Per alias
|
|
domain: success `aliasd_added`, errors `alias_domain_invalid` (also
|
|
when the name is taken by a domain or alias domain),
|
|
`aliasd_targetd_identical`, `targetd_not_found`,
|
|
`targetd_relay_domain`; for the call: `access_denied`,
|
|
`target_domain_invalid`. An invalid alias domain name currently ends
|
|
the request without an answer.
|
|
operationId: addAliasDomain
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- alias_domain
|
|
- target_domain
|
|
properties:
|
|
alias_domain:
|
|
type: string
|
|
description: >-
|
|
Alias domain name; several are separated by spaces, commas,
|
|
semicolons or line breaks
|
|
target_domain:
|
|
type: string
|
|
description: The domain the alias domain points to
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: Alias domain active (inactive when not sent)
|
|
rl_value:
|
|
type: [integer, string]
|
|
description: Rate limit, messages per `rl_frame`; empty or 0 = none
|
|
rl_frame:
|
|
type: string
|
|
enum: [s, m, h, d]
|
|
description: Rate limit time frame
|
|
dkim_selector:
|
|
type: string
|
|
description: Selector of the DKIM key that is created
|
|
key_size:
|
|
type: [integer, string]
|
|
description: >-
|
|
RSA key size in bits of the DKIM key that is created; a key
|
|
is created only when `key_size` and `dkim_selector` are sent
|
|
example:
|
|
alias_domain: example.net
|
|
target_domain: example.org
|
|
active: 1
|
|
rl_value: 100
|
|
rl_frame: h
|
|
dkim_selector: dkim
|
|
key_size: 2048
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/alias-domain:
|
|
post:
|
|
summary: Edit alias domains
|
|
description: >-
|
|
Changes alias domains; attributes not sent keep their value. The new
|
|
target domain must be an existing domain (no alias domain) the caller
|
|
has access to. Success `aliasd_modified`, errors per alias domain
|
|
`alias_domain_invalid` (unknown), `target_domain_invalid`,
|
|
`access_denied`. Rate limits are set with edit/rl-domain.
|
|
operationId: editAliasDomain
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Alias domain name or list of alias domain names
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Alias domain active
|
|
target_domain:
|
|
type: string
|
|
description: New target domain
|
|
example:
|
|
items:
|
|
- example.net
|
|
attr:
|
|
active: 1
|
|
target_domain: example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/alias-domain:
|
|
post:
|
|
summary: Delete alias domains
|
|
description: >-
|
|
Deletes alias domains together with their aliases, spam aliases, BCC
|
|
maps and mailbox group data. Success `alias_domain_removed`, errors
|
|
`domain_invalid`, `access_denied`. The rate limit of the alias domain
|
|
is not removed.
|
|
operationId: deleteAliasDomain
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Alias domain names
|
|
items:
|
|
type: string
|
|
example:
|
|
- example.net
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/mta-sts:
|
|
post:
|
|
summary: Add an MTA-STS policy
|
|
description: >-
|
|
Adds the MTA-STS policy of a domain, published (when active) at
|
|
`https://mta-sts.<domain>/.well-known/mta-sts.txt`. Alias domains always
|
|
publish the policy of their target domain: a policy added for an alias
|
|
domain is accepted but never published. The policy ID for the
|
|
`_mta-sts` TXT record is the time of the change (`YYYYMMDDhhmmss`). There is no read route: the policy is shown in the
|
|
UI only. Answers `Task completed` on success; errors `access_denied`
|
|
(unknown domain or no access), `version_invalid`, `mode_invalid`,
|
|
`max_age_invalid`, `mx_invalid`, and the database message when the
|
|
domain has a policy already (use edit/mta-sts).
|
|
operationId: addMtaSts
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- domain
|
|
- version
|
|
- mode
|
|
- mx
|
|
- max_age
|
|
properties:
|
|
domain:
|
|
type: string
|
|
description: Domain or alias domain
|
|
version:
|
|
type: string
|
|
enum: [stsv1, STSv1]
|
|
description: Policy version (case-insensitive)
|
|
mode:
|
|
type: string
|
|
enum: [enforce, testing, none]
|
|
description: >-
|
|
`enforce` rejects delivery without valid TLS, `testing`
|
|
only reports, `none` publishes without effect
|
|
mx:
|
|
type: string
|
|
description: >-
|
|
Comma-separated MX host names the senders may deliver to,
|
|
wildcards like `*.example.org` allowed
|
|
max_age:
|
|
type: [integer, string]
|
|
description: Seconds senders may cache the policy, 1 to 31536000
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: Policy published (inactive when not sent)
|
|
example:
|
|
domain: example.org
|
|
version: stsv1
|
|
mode: enforce
|
|
mx: mail.example.org,mx2.example.org
|
|
max_age: 86400
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/mta-sts:
|
|
post:
|
|
summary: Edit MTA-STS policies
|
|
description: >-
|
|
Changes the MTA-STS policies of domains; attributes not sent keep their
|
|
value, but `version` must always be sent (else `version_invalid`). A
|
|
change of `version`, `mode`, `mx` or `max_age` gives the policy a new
|
|
ID. Success `object_modified`, errors per domain `access_denied` (also
|
|
for a domain without policy), `version_invalid`, `mode_invalid`,
|
|
`max_age_invalid`, `mx_invalid`.
|
|
operationId: editMtaSts
|
|
tags:
|
|
- Domains
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Domain name or list of domain names
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
required:
|
|
- version
|
|
properties:
|
|
version:
|
|
type: string
|
|
enum: [stsv1, STSv1]
|
|
description: Policy version
|
|
mode:
|
|
type: string
|
|
enum: [enforce, testing, none]
|
|
description: Policy mode
|
|
mx:
|
|
type: string
|
|
description: Comma-separated MX host names
|
|
max_age:
|
|
type: [integer, string]
|
|
description: Seconds senders may cache the policy, 1 to 31557600
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
description: Policy published
|
|
example:
|
|
items:
|
|
- example.org
|
|
attr:
|
|
version: stsv1
|
|
mode: testing
|
|
mx: mail.example.org
|
|
max_age: 604800
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/fail2ban:
|
|
get:
|
|
summary: Get Fail2Ban settings and bans
|
|
description: >-
|
|
Returns the Fail2Ban (netfilter) settings, the regex filters, the
|
|
allow- and denylists and the current bans. Admins only (an API key
|
|
may); other callers get `{}`. Any further path segment
|
|
(e.g. `/api/v1/get/fail2ban/all`) gives the same answer.
|
|
operationId: getFail2Ban
|
|
tags:
|
|
- Fail2Ban
|
|
responses:
|
|
"200":
|
|
description: Settings and bans
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Fail2Ban"
|
|
example:
|
|
ban_time: 1800
|
|
ban_time_increment: true
|
|
max_ban_time: 86400
|
|
netban_ipv4: 32
|
|
netban_ipv6: 128
|
|
max_attempts: 10
|
|
retry_window: 600
|
|
banlist_id: a2c11baf-5770-47de-9c5e-575bd7bc9218
|
|
manage_external: 0
|
|
regex:
|
|
"1": "^mailcow UI: Invalid password for .+ by ([0-9a-f\\.:]+)$"
|
|
"2": "^Rspamd UI: Invalid password by ([0-9a-f\\.:]+)$"
|
|
whitelist: |-
|
|
192.0.2.0/24
|
|
mail.example.org
|
|
blacklist: 198.51.100.66/32
|
|
perm_bans:
|
|
- network: 198.51.100.66/32
|
|
ip: 198.51.100.66
|
|
active_bans:
|
|
- queued_for_unban: 0
|
|
network: 203.0.113.7/32
|
|
ip: 203.0.113.7
|
|
banned_until: 00h 27m 08s
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/fail2ban/banlist:
|
|
post:
|
|
summary: Renew the Fail2Ban banlist URL
|
|
description: >-
|
|
Gives the banlist (`/f2b-banlist?id=<banlist_id>`, the list of denied
|
|
and banned networks for an external firewall) a new random ID, so the
|
|
old URL stops working. `items` must hold the current `banlist_id`
|
|
(from `GET /api/v1/get/fail2ban`); `attr` can be left out. Admins
|
|
only (an API key may).
|
|
|
|
|
|
Answers `f2b_banlist_refreshed`; a wrong ID is answered with status
|
|
404 and `Cannot edit item`, a Redis error with 500 and `redis_error`.
|
|
operationId: refreshFail2BanBanlist
|
|
tags:
|
|
- Fail2Ban
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: The current banlist ID (single value or a list with it as first element)
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: string
|
|
- type: string
|
|
attr:
|
|
type: object
|
|
description: Not used
|
|
required:
|
|
- items
|
|
example:
|
|
items:
|
|
- a2c11baf-5770-47de-9c5e-575bd7bc9218
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
"404":
|
|
description: "`items` does not hold the current banlist ID"
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/TaskResult"
|
|
example:
|
|
type: error
|
|
msg: Cannot edit item
|
|
/api/v1/get/logs/acme/{count}:
|
|
get:
|
|
summary: Get ACME logs (count or range)
|
|
description: Entries of the ACME log (Let's Encrypt certificates), newest first.
|
|
operationId: getAcmeLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/AcmeLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/api/{count}:
|
|
get:
|
|
summary: Get API logs (count or range)
|
|
description: >-
|
|
Entries of the API log: every request to `/api/v1` with its form data
|
|
(values of keys like passwords and secrets replaced by `*`). Newest
|
|
first.
|
|
operationId: getApiLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/ApiLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/autodiscover/{count}:
|
|
get:
|
|
summary: Get Autodiscover logs (count or range)
|
|
description: >-
|
|
Requests to Autodiscover (Outlook, ActiveSync) and the service that was
|
|
offered, newest first.
|
|
operationId: getAutodiscoverLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/AutodiscoverLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/dovecot/{count}:
|
|
get:
|
|
summary: Get Dovecot logs (count or range)
|
|
description: Entries of the Dovecot log (IMAP, POP3, Sieve, LMTP), newest first.
|
|
operationId: getDovecotLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/DovecotLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/netfilter/{count}:
|
|
get:
|
|
summary: Get netfilter logs (count or range)
|
|
description: Entries of netfilter (failed logins, bans), newest first.
|
|
operationId: getNetfilterLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/NetfilterLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/postfix/{count}:
|
|
get:
|
|
summary: Get Postfix logs (count or range)
|
|
description: Entries of the Postfix log (SMTP), newest first.
|
|
operationId: getPostfixLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/PostfixLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/ratelimited/{count}:
|
|
get:
|
|
summary: Get rate limit logs (count or range)
|
|
description: >-
|
|
Messages that were rejected because a rate limit was exceeded, newest
|
|
first.
|
|
operationId: getRatelimitLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/RatelimitLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/rspamd-history/{count}:
|
|
get:
|
|
summary: Get Rspamd history (count or range)
|
|
description: >-
|
|
Messages scanned by Rspamd with score, action and symbols, newest
|
|
first.
|
|
operationId: getRspamdHistoryByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N messages. `from-to` (from ≥ 1, to ≥ from) is
|
|
passed to Rspamd, which counts from 0: `2-3` gives the third and
|
|
fourth newest message. Characters other than digits and `-` are
|
|
removed; `0` gives `{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/RspamdHistory"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/sogo/{count}:
|
|
get:
|
|
summary: Get SOGo logs (count or range)
|
|
description: Entries of the SOGo log, newest first.
|
|
operationId: getSogoLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/SogoLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/watchdog/{count}:
|
|
get:
|
|
summary: Get watchdog logs (count or range)
|
|
description: Health checks of the watchdog container, newest first.
|
|
operationId: getWatchdogLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WatchdogLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/acme:
|
|
get:
|
|
summary: Get ACME logs
|
|
description: >-
|
|
The newest 1000 entries of the ACME log (Let's Encrypt certificates),
|
|
newest first.
|
|
operationId: getAcmeLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/AcmeLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/api:
|
|
get:
|
|
summary: Get API logs
|
|
description: >-
|
|
The newest 1000 entries of the API log: every request to `/api/v1`
|
|
with its form data (values of keys like passwords and secrets
|
|
replaced by `*`). Requests with a JSON body show the body as `attr` or
|
|
`items`. Newest first.
|
|
operationId: getApiLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/ApiLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/autodiscover:
|
|
get:
|
|
summary: Get Autodiscover logs
|
|
description: >-
|
|
The newest 1000 requests to Autodiscover (Outlook, ActiveSync) and the
|
|
service that was offered, newest first.
|
|
operationId: getAutodiscoverLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/AutodiscoverLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/cron:
|
|
get:
|
|
summary: Get cron logs
|
|
description: >-
|
|
The newest 1000 entries of the scheduled tasks of mailcow (e.g.
|
|
identity provider sync, group shares), newest first.
|
|
operationId: getCronLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/CronLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/cron/{count}:
|
|
get:
|
|
summary: Get cron logs (count or range)
|
|
description: >-
|
|
Entries of the scheduled tasks of mailcow (e.g. identity provider
|
|
sync, group shares), newest first.
|
|
operationId: getCronLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: the entries from position
|
|
`from` to `to` (the newest entry is 1). Characters other than
|
|
digits and `-` are removed; `0` or a range with `to` < `from` gives
|
|
`{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/CronLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/dovecot:
|
|
get:
|
|
summary: Get Dovecot logs
|
|
description: The newest 1000 entries of the Dovecot log (IMAP, POP3, Sieve, LMTP), newest first.
|
|
operationId: getDovecotLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/DovecotLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/netfilter:
|
|
get:
|
|
summary: Get netfilter logs
|
|
description: >-
|
|
The newest 1000 entries of netfilter (failed logins, bans), newest
|
|
first.
|
|
operationId: getNetfilterLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/NetfilterLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/postfix:
|
|
get:
|
|
summary: Get Postfix logs
|
|
description: The newest 1000 entries of the Postfix log (SMTP), newest first.
|
|
operationId: getPostfixLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/PostfixLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/ratelimited:
|
|
get:
|
|
summary: Get rate limit logs
|
|
description: >-
|
|
The newest 1000 messages that were rejected because a rate limit was
|
|
exceeded, newest first.
|
|
operationId: getRatelimitLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/RatelimitLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/rspamd-history:
|
|
get:
|
|
summary: Get Rspamd history
|
|
description: >-
|
|
The newest 1000 messages scanned by Rspamd with score, action and
|
|
symbols, newest first.
|
|
operationId: getRspamdHistory
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/RspamdHistory"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/rspamd-stats:
|
|
get:
|
|
summary: Get Rspamd statistics
|
|
description: >-
|
|
The statistics of Rspamd (`/stat` of its controller): scanned and
|
|
learned messages, actions, Bayes statistics. Further path segments are
|
|
ignored.
|
|
operationId: getRspamdStats
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
description: The statistics, `{}` if Rspamd cannot be reached
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/RspamdStats"
|
|
example:
|
|
version: 3.12.1
|
|
config_id: ch8ha1o68oxb3xf9izngisz4wxuxgs86n9gg6yko7jtt4msu4bxhuunnoi4pk7an4y5htzjb1y9nwsxmkjhdu671ocb5b5ea1g38csb
|
|
uptime: 25891
|
|
read_only: false
|
|
scanned: 300
|
|
learned: 30
|
|
actions:
|
|
reject: 38
|
|
soft reject: 0
|
|
rewrite subject: 0
|
|
add header: 6
|
|
greylist: 1
|
|
no action: 255
|
|
scan_times:
|
|
- 0.340365
|
|
- 0.48114
|
|
spam_count: 44
|
|
ham_count: 256
|
|
connections: 24
|
|
control_connections: 700
|
|
total_learns: 29
|
|
statfiles:
|
|
- revision: 6
|
|
users: 1
|
|
used: 0
|
|
total: 0
|
|
size: 0
|
|
symbol: BAYES_SPAM
|
|
type: redis
|
|
languages: 0
|
|
class: spam
|
|
fuzzy_hashes:
|
|
mailcow: 0
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/sasl:
|
|
get:
|
|
summary: Get SASL logs
|
|
description: >-
|
|
The newest 1000 successful logins (IMAP, POP3, SMTP, SOGo, ...), one
|
|
entry per service, address and user with the time of the last login,
|
|
newest first.
|
|
operationId: getSaslLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/SaslLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/sasl/{count}:
|
|
get:
|
|
summary: Get SASL logs (count or range)
|
|
description: >-
|
|
Successful logins (IMAP, POP3, SMTP, SOGo, ...), one entry per
|
|
service, address and user with the time of the last login, newest
|
|
first.
|
|
operationId: getSaslLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: `to` entries starting at
|
|
position `from` (the newest entry is 1), so `2-3` gives the entries
|
|
2 to 4. Characters other than digits and `-` are removed; `0` or a
|
|
range with `to` < `from` gives `{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/SaslLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/sogo:
|
|
get:
|
|
summary: Get SOGo logs
|
|
description: The newest 1000 entries of the SOGo log, newest first.
|
|
operationId: getSogoLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/SogoLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/ui:
|
|
get:
|
|
summary: Get mailcow UI logs
|
|
description: >-
|
|
The newest 1000 actions of the mailcow UI and API (the messages of
|
|
their calls), newest first.
|
|
operationId: getUiLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/UiLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/ui/{count}:
|
|
get:
|
|
summary: Get mailcow UI logs (count or range)
|
|
description: >-
|
|
Actions of the mailcow UI and API (the messages of their calls),
|
|
newest first.
|
|
operationId: getUiLogsByCount
|
|
tags:
|
|
- Logs
|
|
parameters:
|
|
- name: count
|
|
in: path
|
|
required: true
|
|
description: >-
|
|
`N`: the newest N entries. `from-to`: `to` entries starting at
|
|
position `from` (the newest entry is 1), so `2-3` gives the entries
|
|
2 to 4. Characters other than digits and `-` are removed; `0` or a
|
|
range with `to` < `from` gives `{}`.
|
|
schema:
|
|
type: string
|
|
pattern: ^[0-9]+(-[0-9]+)?$
|
|
example: "50"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/UiLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/logs/watchdog:
|
|
get:
|
|
summary: Get watchdog logs
|
|
description: >-
|
|
The newest 1000 health checks of the watchdog container, newest first.
|
|
operationId: getWatchdogLogs
|
|
tags:
|
|
- Logs
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WatchdogLogs"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox/{id}:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get a mailbox
|
|
operationId: getMailbox
|
|
description: >-
|
|
Details of one mailbox, `{}` if it does not exist or the caller has no
|
|
access to it. A mailbox user may read its own mailbox.
|
|
|
|
|
|
With the query parameter `tags`, `{id}` is a search term instead: the
|
|
answer is the list of mailboxes whose address contains `{id}` and that
|
|
have a tag containing one of the tags, `[]` when none matches.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "Mailbox address (with `tags`: part of the address, e.g. a domain)"
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
- $ref: "#/components/parameters/MailboxTagsQuery"
|
|
responses:
|
|
"200":
|
|
description: The mailbox; with `tags` a list of mailboxes
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- $ref: "#/components/schemas/Mailbox"
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/Mailbox"
|
|
examples:
|
|
mailbox:
|
|
$ref: "#/components/examples/MailboxDetails"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox-group/{id}:
|
|
get:
|
|
summary: Get mailbox group
|
|
description: >-
|
|
One group by id, with the same visibility rules as
|
|
`GET /api/v1/get/mailbox-group/all`. Answers `{}` when the id is not a
|
|
number, the group does not exist or the caller may not see it.
|
|
operationId: getMailboxGroup
|
|
tags:
|
|
- Groups
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Group id
|
|
schema:
|
|
type: integer
|
|
example: 7
|
|
responses:
|
|
"200":
|
|
description: The group
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MailboxGroup"
|
|
example:
|
|
id: 7
|
|
domain: example.org
|
|
name: Sales
|
|
description: Sales team
|
|
address: sales@example.org
|
|
sender_allowed: 1
|
|
sogo_visible: 0
|
|
internal: 1
|
|
template_id: 3
|
|
template: Staff
|
|
priority: 10
|
|
idp_ref: null
|
|
members:
|
|
- username: alice@example.org
|
|
source: manual
|
|
send_as:
|
|
- "@example.com"
|
|
imap_grants: []
|
|
sogo_grants: []
|
|
active: 1
|
|
created: "2026-10-25 12:00:00"
|
|
modified: null
|
|
can_edit: true
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox-group/member/{username}:
|
|
get:
|
|
summary: Get group memberships of a mailbox
|
|
description: >-
|
|
The groups of a mailbox, its effective group template (the template of
|
|
the active group with the highest priority, then the lowest id) and the
|
|
addresses it may send as through its active groups. Admins (every API
|
|
key) get it for every existing mailbox, domain admins with the
|
|
`mailbox_groups` ACL for their mailboxes (only the groups of their
|
|
domains), a mailbox user for himself. Answers `{}` for unknown mailboxes
|
|
or without access.
|
|
operationId: getMailboxGroupMemberships
|
|
tags:
|
|
- Groups
|
|
parameters:
|
|
- name: username
|
|
in: path
|
|
required: true
|
|
description: Mailbox (case-insensitive)
|
|
schema:
|
|
type: string
|
|
example: alice@example.org
|
|
responses:
|
|
"200":
|
|
description: The memberships
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MailboxGroupMemberships"
|
|
example:
|
|
groups:
|
|
- id: 7
|
|
domain: example.org
|
|
name: Sales
|
|
address: sales@example.org
|
|
sender_allowed: 1
|
|
active: 1
|
|
priority: 10
|
|
template: Staff
|
|
source: manual
|
|
template: Staff
|
|
send_as:
|
|
- orders@example.org
|
|
- sales@example.org
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox-group/all:
|
|
get:
|
|
summary: Get mailbox groups
|
|
description: >-
|
|
All groups the caller may see, ordered by domain and name: admins (and
|
|
every API key) all groups, domain admins with the `mailbox_groups` ACL
|
|
the groups of their domains, others none. `can_edit` is false for
|
|
read-only API keys. Answers `{}` when there is no group.
|
|
operationId: getMailboxGroups
|
|
tags:
|
|
- Groups
|
|
responses:
|
|
"200":
|
|
description: The groups
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/MailboxGroup"
|
|
example:
|
|
- id: 7
|
|
domain: example.org
|
|
name: Sales
|
|
description: Sales team
|
|
address: sales@example.org
|
|
sender_allowed: 1
|
|
sogo_visible: 0
|
|
internal: 0
|
|
template_id: 3
|
|
template: Staff
|
|
priority: 10
|
|
idp_ref: null
|
|
members:
|
|
- username: alice@example.org
|
|
source: manual
|
|
- username: bob@example.org
|
|
source: idp
|
|
send_as:
|
|
- orders@example.org
|
|
imap_grants:
|
|
- owner: shared@example.org
|
|
rights: write
|
|
subscribe: 1
|
|
state: applied
|
|
last_error: null
|
|
sogo_grants:
|
|
- owner: shared@example.org
|
|
type: Calendar
|
|
folder: personal
|
|
access: read
|
|
subscribe: 0
|
|
state: pending
|
|
last_error: null
|
|
active: 1
|
|
created: "2026-10-25 12:00:00"
|
|
modified: "2026-10-28 09:14:03"
|
|
can_edit: true
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox-group/all/{domains}:
|
|
get:
|
|
summary: Get mailbox groups of domains
|
|
description: >-
|
|
Like `GET /api/v1/get/mailbox-group/all`, limited to the groups of the
|
|
given domains. Answers `{}` when there is no group.
|
|
operationId: getMailboxGroupsOfDomains
|
|
tags:
|
|
- Groups
|
|
parameters:
|
|
- name: domains
|
|
in: path
|
|
required: true
|
|
description: One domain or a comma-separated list of domains
|
|
schema:
|
|
type: string
|
|
example: example.org,example.com
|
|
responses:
|
|
"200":
|
|
description: The groups of the domains
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/MailboxGroup"
|
|
example:
|
|
- id: 7
|
|
domain: example.org
|
|
name: Sales
|
|
description: ""
|
|
address: sales@example.org
|
|
sender_allowed: 1
|
|
sogo_visible: 1
|
|
internal: 0
|
|
template_id: null
|
|
template: null
|
|
priority: 0
|
|
idp_ref: null
|
|
members:
|
|
- username: alice@example.org
|
|
source: manual
|
|
send_as: []
|
|
imap_grants: []
|
|
sogo_grants: []
|
|
active: 1
|
|
created: "2026-10-25 12:00:00"
|
|
modified: null
|
|
can_edit: true
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/identity-provider/sync-status:
|
|
get:
|
|
summary: Get identity sync status
|
|
description: >-
|
|
Status of the Identity Provider sync (admins and API keys, also
|
|
read-only; `{}` for others): the provider, whether it can be synced
|
|
(Keycloak and LDAP) and a scheduled sync is enabled, counts of the
|
|
mailboxes of the provider and their links, and the last 10 sync runs,
|
|
newest first. Run status: `pending`, `running`, `ok`, `blocked` (the
|
|
change limit `offboarding_limit` stopped the run, nothing was changed)
|
|
or `error` (`summary.error`, nothing was changed).
|
|
operationId: getIdentitySyncStatus
|
|
tags:
|
|
- Identity Provider
|
|
responses:
|
|
"200":
|
|
description: The sync status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/IdentitySyncStatus"
|
|
example:
|
|
provider: keycloak
|
|
can_sync: true
|
|
sync_enabled: true
|
|
counts:
|
|
accounts: 120
|
|
linked: 118
|
|
idp_disabled: 2
|
|
missing: 1
|
|
runs:
|
|
- id: 42
|
|
provider: keycloak
|
|
mode: run
|
|
status: ok
|
|
requested_by: ""
|
|
created: "2026-11-09 12:00:00"
|
|
started: "2026-11-09 12:00:01"
|
|
finished: "2026-11-09 12:00:03"
|
|
summary:
|
|
counts:
|
|
links: 0
|
|
creates: 1
|
|
deactivate: 1
|
|
restore: 0
|
|
release: 0
|
|
missing: 1
|
|
found: 0
|
|
updates: 3
|
|
group_creates: 0
|
|
group_renames: 0
|
|
memberships: 2
|
|
orphaned_groups: 0
|
|
conflicts: 0
|
|
membership_removals: 0
|
|
skipped: 0
|
|
errors: 0
|
|
details:
|
|
creates:
|
|
- new.user@example.org
|
|
deactivate:
|
|
- left.user@example.org
|
|
restore: []
|
|
missing:
|
|
- left.user@example.org
|
|
group_creates: []
|
|
conflicts: []
|
|
blocked: false
|
|
errors: []
|
|
mode: run
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/identity-link/{username}:
|
|
get:
|
|
summary: Get identity link of a mailbox
|
|
description: >-
|
|
The Identity Provider user a mailbox is linked to (admins and API keys,
|
|
domain admins for their mailboxes). Answers `{}` without a link or
|
|
without access. `missing_since` is set while the sync does not find the
|
|
mailbox at the provider; a mailbox that was never linked then has a row
|
|
without `external_id`.
|
|
operationId: getIdentityLink
|
|
tags:
|
|
- Identity Provider
|
|
parameters:
|
|
- name: username
|
|
in: path
|
|
required: true
|
|
description: Mailbox (case-insensitive)
|
|
schema:
|
|
type: string
|
|
example: alice@example.org
|
|
responses:
|
|
"200":
|
|
description: The link
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/IdentityLink"
|
|
example:
|
|
provider: keycloak
|
|
external_id: 8d5da28d-7541-428b-8356-a9704f73e7f4
|
|
idp_disabled: 0
|
|
missing_since: null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailq/all:
|
|
get:
|
|
summary: Get the mail queue
|
|
description: >-
|
|
Returns the Postfix mail queue (`postqueue -j`), at most 10000
|
|
entries. Admins only (an API key may); other callers and an empty
|
|
queue get `[]`.
|
|
operationId: getMailQueue
|
|
tags:
|
|
- Queue Manager
|
|
responses:
|
|
"200":
|
|
description: List of queued messages
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/MailQueueItem"
|
|
example:
|
|
- queue_name: deferred
|
|
queue_id: B98C6260CA1
|
|
arrival_time: 1762768034
|
|
message_size: 1848
|
|
forced_expire: false
|
|
sender: sender@example.org
|
|
recipients:
|
|
- "rcpt@example.com (connect to mx.example.com[192.0.2.25]:25: Connection timed out)"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/postcat/{qid}:
|
|
get:
|
|
summary: Get a queued message
|
|
description: >-
|
|
Returns the output of `postcat -q <qid>` for a message in the Postfix
|
|
queue: envelope records, headers and body. Admins only (an API key
|
|
may); other callers get an empty answer.
|
|
|
|
|
|
The answer is sent with `Content-Type: application/json`, but the body
|
|
is the plain postcat text, not JSON-encoded. An unknown or
|
|
non-hexadecimal queue ID gives the error text of postcat.
|
|
operationId: getQueuedMessage
|
|
tags:
|
|
- Queue Manager
|
|
parameters:
|
|
- name: qid
|
|
in: path
|
|
required: true
|
|
description: Postfix queue ID
|
|
schema:
|
|
type: string
|
|
example: B98C6260CA1
|
|
responses:
|
|
"200":
|
|
description: The postcat output as plain text (despite the JSON content type)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: string
|
|
example: |
|
|
*** ENVELOPE RECORDS deferred/B/B98C6260CA1 ***
|
|
message_size: 1848 612 1 0 1848 0
|
|
message_arrival_time: Mon Nov 10 09:47:14 2026
|
|
create_time: Mon Nov 10 09:47:14 2026
|
|
named_attribute: rewrite_context=local
|
|
sender: sender@example.org
|
|
*** MESSAGE CONTENTS deferred/B/B98C6260CA1 ***
|
|
From: Sender <sender@example.org>
|
|
To: rcpt@example.com
|
|
Subject: Test
|
|
|
|
Hello
|
|
*** HEADER EXTRACTED deferred/B/B98C6260CA1 ***
|
|
original_recipient: rcpt@example.com
|
|
recipient: rcpt@example.com
|
|
*** MESSAGE FILE END deferred/B/B98C6260CA1 ***
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/oauth2-client/{id}:
|
|
get:
|
|
summary: Get OAuth2 client
|
|
description: One OAuth2 client including its secret.
|
|
operationId: getOAuth2Client
|
|
tags:
|
|
- oAuth Clients
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: ID of the client (`id`, not `client_id`)
|
|
schema:
|
|
type: integer
|
|
example: 1
|
|
responses:
|
|
"200":
|
|
description: The client, `{}` if there is none with this ID
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/OAuth2Client"
|
|
example:
|
|
id: 1
|
|
client_id: 17c76aaa88c0
|
|
client_secret: 73fc668a88147e32a31ff80c
|
|
redirect_uri: https://app.example.org/oauth/callback
|
|
grant_types: null
|
|
scope: profile
|
|
user_id: null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/oauth2-client/all:
|
|
get:
|
|
summary: Get OAuth2 clients
|
|
description: >-
|
|
Lists the OAuth2 clients that may use mailcow as OAuth2 server,
|
|
including their secrets.
|
|
operationId: getOAuth2Clients
|
|
tags:
|
|
- oAuth Clients
|
|
responses:
|
|
"200":
|
|
description: The clients, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/OAuth2Client"
|
|
example:
|
|
- id: 1
|
|
client_id: 17c76aaa88c0
|
|
client_secret: 73fc668a88147e32a31ff80c
|
|
redirect_uri: https://app.example.org/oauth/callback
|
|
grant_types: null
|
|
scope: profile
|
|
user_id: null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/oauth2-client:
|
|
post:
|
|
summary: Edit OAuth2 clients
|
|
description: >-
|
|
Does one of three things per client, in this order of precedence:
|
|
`revoke_tokens` deletes all access and refresh tokens of the client,
|
|
`renew_secret` gives it a new random secret, otherwise `redirect_uri`
|
|
is set. `revoke_tokens` and `renew_secret` act when they are present,
|
|
whatever their value.
|
|
|
|
|
|
Success: `object_modified` per client. Errors: `access_denied` (no
|
|
client with this ID; stops the call), `Redirect/Callback URL cannot be
|
|
empty`.
|
|
operationId: editOAuth2Client
|
|
tags:
|
|
- oAuth Clients
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: ID of the client, or a list of IDs
|
|
oneOf:
|
|
- type: [integer, string]
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
attr:
|
|
type: object
|
|
properties:
|
|
redirect_uri:
|
|
type: string
|
|
description: New redirect URL; empty or missing keeps the current one
|
|
revoke_tokens:
|
|
type: [integer, string, boolean]
|
|
description: Present = delete the access and refresh tokens of the client
|
|
renew_secret:
|
|
type: [integer, string, boolean]
|
|
description: Present = generate a new client secret
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 1
|
|
attr:
|
|
redirect_uri: https://app.example.org/oauth/callback2
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/policy_bl_domain/{domain}:
|
|
get:
|
|
summary: Get the sender deny list of a domain
|
|
description: >-
|
|
The deny list (blacklist) entries of the domain and of all its
|
|
mailboxes (`object` tells which); `{}` if there are none or the domain
|
|
is unknown.
|
|
operationId: getDomainBlacklist
|
|
tags:
|
|
- Domain antispam policies
|
|
parameters:
|
|
- name: domain
|
|
in: path
|
|
required: true
|
|
description: Domain name
|
|
schema:
|
|
type: string
|
|
example: example.org
|
|
responses:
|
|
"200":
|
|
description: The deny list entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/DomainPolicyEntry"
|
|
example:
|
|
- object: example.org
|
|
value: "*@spam.example.com"
|
|
prefid: 13
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/policy_wl_domain/{domain}:
|
|
get:
|
|
summary: Get the sender allow list of a domain
|
|
description: >-
|
|
The allow list (whitelist) entries of the domain and of all its
|
|
mailboxes (`object` tells which); `{}` if there are none or the domain
|
|
is unknown.
|
|
operationId: getDomainWhitelist
|
|
tags:
|
|
- Domain antispam policies
|
|
parameters:
|
|
- name: domain
|
|
in: path
|
|
required: true
|
|
description: Domain name
|
|
schema:
|
|
type: string
|
|
example: example.org
|
|
responses:
|
|
"200":
|
|
description: The allow list entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/DomainPolicyEntry"
|
|
example:
|
|
- object: example.org
|
|
value: "*@partner.example.com"
|
|
prefid: 12
|
|
- object: anna@example.org
|
|
value: newsletter@example.net
|
|
prefid: 15
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/quarantine/all:
|
|
get:
|
|
summary: Get quarantined messages
|
|
description: >-
|
|
Returns the quarantined messages without their content. An API key
|
|
(admin) gets every item, a domain admin the items of their domains, a
|
|
mailbox user their own items. `[]` when there are none.
|
|
operationId: getQuarantine
|
|
tags:
|
|
- Quarantine
|
|
responses:
|
|
"200":
|
|
description: List of quarantine items
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/QuarantineItem"
|
|
example:
|
|
- id: 33
|
|
qid: 8224615004C1
|
|
subject: You have won
|
|
virus_flag: 0
|
|
score: 15.48
|
|
rcpt: john.doe@example.org
|
|
sender: bounces@send.example.com
|
|
action: reject
|
|
created: 1762768034
|
|
notified: 1
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/quarantine_category:
|
|
post:
|
|
tags:
|
|
- Quarantine
|
|
summary: Set the quarantine notification category of mailboxes
|
|
operationId: editQuarantineCategory
|
|
description: >-
|
|
Which quarantined mail the notifications list: rejected mail
|
|
(`reject`), mail sent to the junk folder (`add_header`) or both
|
|
(`all`). Needs the user ACL `quarantine_category`. API keys may change
|
|
any mailbox, a mailbox user only its own. `quarantine_category` must be
|
|
sent: without it the call fails with an empty answer. Messages per
|
|
mailbox: `mailbox_modified` or `access_denied` (also for an invalid
|
|
value).
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
required:
|
|
- quarantine_category
|
|
properties:
|
|
quarantine_category:
|
|
type: string
|
|
enum:
|
|
- reject
|
|
- add_header
|
|
- all
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
quarantine_category: all
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/quarantine/{id}:
|
|
get:
|
|
summary: Get a quarantined message
|
|
description: >-
|
|
Returns one quarantine item with the raw message and the Rspamd
|
|
symbols. An API key (admin) may read every item; others only items of
|
|
their mailboxes or domains. `[]` for an unknown or non-numeric ID or
|
|
without access.
|
|
operationId: getQuarantineItem
|
|
tags:
|
|
- Quarantine
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: ID of the quarantine item
|
|
schema:
|
|
type: string
|
|
example: "33"
|
|
responses:
|
|
"200":
|
|
description: The quarantine item
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/QuarantineItemDetails"
|
|
example:
|
|
id: 33
|
|
qid: 8224615004C1
|
|
subject: You have won
|
|
score: 15.48
|
|
ip: 198.51.100.23
|
|
action: reject
|
|
symbols: '[{"name":"BAYES_SPAM","score":5.1,"options":["99.99%"]},{"name":"RBL_SPAMHAUS_SBL","score":4.0}]'
|
|
fuzzy_hashes: "[]"
|
|
sender: bounces@send.example.com
|
|
rcpt: john.doe@example.org
|
|
msg: "Return-Path: <bounces@send.example.com>\r\nFrom: Prize <bounces@send.example.com>\r\nTo: john.doe@example.org\r\nSubject: You have won\r\n\r\nClick here\r\n"
|
|
domain: null
|
|
notified: 1
|
|
created: "2026-11-10 09:47:14"
|
|
user: unknown
|
|
qhash: 3f9d8c0b2a4e6f1d7c5b9a8e0f2d4c6b8a1e3f5d7c9b0a2e4f6d8c1b3a5e7f9d
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/quarantine:
|
|
post:
|
|
summary: Edit quarantine settings
|
|
description: >-
|
|
Saves the global quarantine settings (admins only, an API key may).
|
|
`attr.action` must be `settings`; `items` is ignored. Every call
|
|
writes all settings: an attribute that is not sent is reset (a missing
|
|
`retention_size` or `max_size` becomes 0, which turns the quarantine
|
|
off). The current values cannot be read through the API.
|
|
|
|
|
|
Messages: `saved_settings`; `redis_error` (danger); `access_denied`
|
|
for non-admins. Without `action` nothing happens and the answer is
|
|
`Task completed`.
|
|
operationId: editQuarantineSettings
|
|
tags:
|
|
- Quarantine
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: Ignored
|
|
attr:
|
|
type: object
|
|
properties:
|
|
action:
|
|
type: string
|
|
const: settings
|
|
retention_size:
|
|
type: [integer, string]
|
|
description: Items kept per mailbox; 0 disables the quarantine
|
|
max_size:
|
|
type: [integer, string]
|
|
description: Maximum message size in MiB; larger messages are not quarantined (0 is not unlimited)
|
|
max_score:
|
|
type: [number, string]
|
|
description: No notification for messages with a higher spam score; empty = no limit (9999.0)
|
|
max_age:
|
|
type: [integer, string]
|
|
description: Days an item is kept; 0 or less becomes 365
|
|
release_format:
|
|
type: string
|
|
enum:
|
|
- raw
|
|
- attachment
|
|
default: raw
|
|
description: Deliver released messages as they are or as an attachment of a new message
|
|
exclude_domains:
|
|
type: array
|
|
items:
|
|
type: string
|
|
description: Domains and alias domains whose mail is not quarantined
|
|
sender:
|
|
type: string
|
|
description: Sender of the notifications (invalid address = empty)
|
|
subject:
|
|
type: string
|
|
description: Subject of the notifications
|
|
bcc:
|
|
type: string
|
|
description: Address that gets a copy of every notification (invalid address = empty)
|
|
redirect:
|
|
type: string
|
|
description: Address that gets all notifications instead of the mailboxes (invalid address = empty)
|
|
html_tmpl:
|
|
type: string
|
|
description: HTML template of the notifications (empty = the default template)
|
|
required:
|
|
- action
|
|
required:
|
|
- attr
|
|
example:
|
|
items:
|
|
- self
|
|
attr:
|
|
action: settings
|
|
retention_size: "20"
|
|
max_size: "15"
|
|
max_score: ""
|
|
max_age: "365"
|
|
release_format: raw
|
|
exclude_domains:
|
|
- example.com
|
|
sender: quarantine@example.org
|
|
subject: Spam Quarantine Notification
|
|
bcc: ""
|
|
redirect: ""
|
|
html_tmpl: ""
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/recipient_map/{id}:
|
|
get:
|
|
tags:
|
|
- Address Rewriting
|
|
summary: Get recipient maps
|
|
operationId: getRecipientMaps
|
|
description: >-
|
|
`all` lists the recipient maps, an ID returns that map. `{}` if there
|
|
is none or the caller is no administrator. The answer for an ID
|
|
carries an additional member `"0": null` (json_api.php appends an
|
|
undefined variable).
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all` or the ID of a recipient map"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The list of recipient maps (`all`) or one recipient map
|
|
content:
|
|
application/json:
|
|
schema:
|
|
anyOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/RecipientMap"
|
|
- $ref: "#/components/schemas/RecipientMap"
|
|
examples:
|
|
all:
|
|
summary: get/recipient_map/all
|
|
value:
|
|
- id: 1
|
|
recipient_map_old: jane.doe@example.org
|
|
recipient_map_new: jane.smith@example.org
|
|
active: 1
|
|
created: "2026-11-04 08:30:00"
|
|
modified: null
|
|
- id: 2
|
|
recipient_map_old: "@example.net"
|
|
recipient_map_new: "@example.org"
|
|
active: 0
|
|
created: "2026-11-04 08:31:12"
|
|
modified: "2026-11-05 17:02:45"
|
|
one:
|
|
summary: get/recipient_map/1
|
|
value:
|
|
id: 1
|
|
recipient_map_old: jane.doe@example.org
|
|
recipient_map_new: jane.smith@example.org
|
|
active: 1
|
|
created: "2026-11-04 08:30:00"
|
|
modified: null
|
|
"0": null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/bcc:
|
|
post:
|
|
tags:
|
|
- Address Rewriting
|
|
summary: Update BCC maps
|
|
operationId: editBccMap
|
|
description: >-
|
|
Changes the BCC maps in `items`; attributes that are left out keep
|
|
their value, `local_dest` cannot be changed. Same callers as
|
|
add/bcc. Per map: `bcc_edited`, `access_denied` (unknown, no access or
|
|
no ACL), `bcc_must_be_email`, `bcc_exists`. `type` is not checked by the
|
|
backend: use `sender` or `rcpt`.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: IDs of the BCC maps, a single value or a list
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
attr:
|
|
type: object
|
|
properties:
|
|
bcc_dest:
|
|
type: string
|
|
description: E-mail address that gets the copies
|
|
type:
|
|
type: string
|
|
enum:
|
|
- sender
|
|
- rcpt
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 3
|
|
attr:
|
|
bcc_dest: journal@example.com
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/recipient_map:
|
|
post:
|
|
tags:
|
|
- Address Rewriting
|
|
summary: Update recipient maps
|
|
operationId: editRecipientMap
|
|
description: >-
|
|
Changes the recipient maps in `items`; attributes that are left out
|
|
keep their value. Administrators and API keys only. Per map:
|
|
`recipient_map_entry_saved`, `access_denied` (unknown ID),
|
|
`invalid_recipient_map_old`, `invalid_recipient_map_new`;
|
|
`recipient_map_entry_exists` stops the call.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: IDs of the recipient maps, a single value or a list
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
attr:
|
|
type: object
|
|
properties:
|
|
recipient_map_old:
|
|
type: string
|
|
description: Original recipient, an e-mail address or a domain
|
|
recipient_map_new:
|
|
type: string
|
|
description: New recipient, an e-mail address or a domain
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 1
|
|
attr:
|
|
recipient_map_new: jane.smith@example.org
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/relayhost/{id}:
|
|
get:
|
|
tags:
|
|
- Routing
|
|
summary: Get sender-dependent transports
|
|
operationId: getRelayhosts
|
|
description: >-
|
|
`all` lists the sender-dependent transports, an ID returns that entry,
|
|
with the password in clear text and the domains and mailboxes that use
|
|
it. `{}` if there is none or the caller is no administrator.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all` or the ID of a sender-dependent transport"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The list of sender-dependent transports (`all`) or one entry
|
|
content:
|
|
application/json:
|
|
schema:
|
|
anyOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/Relayhost"
|
|
- $ref: "#/components/schemas/Relayhost"
|
|
examples:
|
|
all:
|
|
summary: get/relayhost/all
|
|
value:
|
|
- id: 1
|
|
hostname: "[smtp.example.com]:587"
|
|
username: relay-user@example.com
|
|
password: Secret-Passphrase-42
|
|
active: 1
|
|
password_short: Sec...
|
|
used_by_domains: example.org, example.net
|
|
used_by_mailboxes: anna@example.com
|
|
one:
|
|
summary: get/relayhost/1
|
|
value:
|
|
id: 1
|
|
hostname: "[smtp.example.com]:587"
|
|
username: relay-user@example.com
|
|
password: Secret-Passphrase-42
|
|
active: 1
|
|
password_short: Sec...
|
|
used_by_domains: example.org, example.net
|
|
used_by_mailboxes: anna@example.com
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/resource/all:
|
|
get:
|
|
tags:
|
|
- Resources
|
|
summary: Get all resources
|
|
operationId: getResources
|
|
description: >-
|
|
All resources of the domains the caller manages, `{}` when there are
|
|
none.
|
|
responses:
|
|
"200":
|
|
description: List of resources
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Resource"
|
|
example:
|
|
- name: MeetingRoom1@example.org
|
|
kind: location
|
|
multiple_bookings: 0
|
|
description: Meeting Room 1
|
|
active: 1
|
|
active_int: 1
|
|
domain: example.org
|
|
local_part: MeetingRoom1
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/resource/{id}:
|
|
get:
|
|
tags:
|
|
- Resources
|
|
summary: Get a resource
|
|
operationId: getResource
|
|
description: >-
|
|
One resource by its address, `{}` if it does not exist or the caller
|
|
does not manage its domain.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Address of the resource
|
|
schema:
|
|
type: string
|
|
example: MeetingRoom1@example.org
|
|
responses:
|
|
"200":
|
|
description: The resource
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Resource"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/resource:
|
|
post:
|
|
tags:
|
|
- Resources
|
|
summary: Update resources
|
|
operationId: editResource
|
|
description: >-
|
|
Changes resources; fields that are not sent keep their value (the
|
|
address does not change with the description). Admins and domain
|
|
admins (for their domains). Messages per resource: `resource_modified`
|
|
or `resource_invalid`, `description_invalid`, `access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Resource address or list of addresses
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
description:
|
|
type: string
|
|
description: Name shown in SOGo
|
|
kind:
|
|
type: string
|
|
enum:
|
|
- location
|
|
- group
|
|
- thing
|
|
multiple_bookings:
|
|
type: [integer, string]
|
|
description: 0 always free, -1 unlimited but busy when booked, n ≥ 1 at most n overlapping bookings
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
example:
|
|
items:
|
|
- MeetingRoom1@example.org
|
|
attr:
|
|
description: Meeting Room 1 (2nd floor)
|
|
multiple_bookings: -1
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/rl-mbox/{mailbox}:
|
|
get:
|
|
tags:
|
|
- Ratelimits
|
|
summary: Get the rate limit of a mailbox
|
|
operationId: getMailboxRatelimit
|
|
description: >-
|
|
The outgoing rate limit set on the mailbox, `{}` when it has none (the
|
|
domain limit applies then) or the caller is no admin or domain admin of
|
|
it.
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: The rate limit
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MailboxRatelimit"
|
|
example:
|
|
value: "100"
|
|
frame: h
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/rl-domain/{domain}:
|
|
get:
|
|
summary: Get rate limits of domains
|
|
description: >-
|
|
The rate limit (outgoing messages per time frame) of a domain or alias
|
|
domain, `{}` if it has none. `all` answers the list of all domains and
|
|
alias domains that have a rate limit, each with its `domain`.
|
|
operationId: getDomainRatelimits
|
|
tags:
|
|
- Ratelimits
|
|
parameters:
|
|
- name: domain
|
|
in: path
|
|
required: true
|
|
description: "`all` or a domain or alias domain name"
|
|
schema:
|
|
type: string
|
|
example: example.org
|
|
responses:
|
|
"200":
|
|
description: The rate limit, or the list of rate limits (`all`)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- $ref: "#/components/schemas/DomainRatelimit"
|
|
- type: array
|
|
items:
|
|
allOf:
|
|
- $ref: "#/components/schemas/DomainRatelimit"
|
|
- type: object
|
|
properties:
|
|
domain:
|
|
type: string
|
|
description: Domain or alias domain
|
|
example:
|
|
value: "100"
|
|
frame: h
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/rl-domain:
|
|
post:
|
|
summary: Set rate limits of domains
|
|
description: >-
|
|
Sets the rate limit (outgoing messages per time frame) of domains or
|
|
alias domains. Needs the ACL `ratelimit` (API keys have it).
|
|
`rl_value` empty or 0 removes the limit; `rl_frame` must be valid then
|
|
too. Success `rl_saved`, errors `rl_timeframe`, `access_denied`.
|
|
operationId: editDomainRatelimits
|
|
tags:
|
|
- Ratelimits
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Domain or alias domain name, or a list of them
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
required:
|
|
- rl_frame
|
|
properties:
|
|
rl_value:
|
|
type: [integer, string]
|
|
description: Messages per `rl_frame`; empty or 0 removes the limit
|
|
rl_frame:
|
|
type: string
|
|
enum: [s, m, h, d]
|
|
description: Time frame (second, minute, hour, day)
|
|
example:
|
|
items:
|
|
- example.org
|
|
attr:
|
|
rl_value: 100
|
|
rl_frame: h
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/rl-mbox/all:
|
|
get:
|
|
tags:
|
|
- Ratelimits
|
|
summary: Get the rate limits of all mailboxes
|
|
operationId: getMailboxRatelimits
|
|
description: >-
|
|
The outgoing rate limits set on mailboxes the caller manages; mailboxes
|
|
without their own limit are left out. Admins and domain admins, `{}`
|
|
when there is none.
|
|
responses:
|
|
"200":
|
|
description: List of rate limits
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
allOf:
|
|
- $ref: "#/components/schemas/MailboxRatelimit"
|
|
- type: object
|
|
properties:
|
|
mailbox:
|
|
type: string
|
|
example:
|
|
- value: "100"
|
|
frame: h
|
|
mailbox: john.doe@example.org
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/rl-mbox:
|
|
post:
|
|
tags:
|
|
- Ratelimits
|
|
summary: Set the rate limit of mailboxes
|
|
operationId: editMailboxRatelimit
|
|
description: >-
|
|
Sets or removes the outgoing rate limit of mailboxes: `rl_value`
|
|
messages per `rl_frame`. A value of 0 or empty removes the limit;
|
|
`rl_frame` must be valid in that case too. Needs the ACL `ratelimit`
|
|
(admins, domain admins for their domains); mailbox users get
|
|
`access_denied`. Messages per mailbox: `rl_saved` or `rl_timeframe`,
|
|
`access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
required:
|
|
- rl_frame
|
|
properties:
|
|
rl_value:
|
|
type: [integer, string]
|
|
description: Number of messages, 0 or empty removes the limit
|
|
rl_frame:
|
|
type: string
|
|
enum:
|
|
- s
|
|
- m
|
|
- h
|
|
- d
|
|
description: Per second, minute, hour or day
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
rl_value: 100
|
|
rl_frame: h
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/rlhash:
|
|
post:
|
|
tags:
|
|
- Ratelimits
|
|
summary: Reset a rate limit counter
|
|
operationId: deleteRatelimitHash
|
|
description: >-
|
|
Deletes the counter of a rate-limited sender (the `rl_hash` of an entry
|
|
of `get/logs/ratelimited`) and its log lines, so the sender can send
|
|
again. Admins only. The body is a list with one hash (several are
|
|
concatenated into one). Unlike other write routes the answer is not
|
|
JSON: `1` when the hash was deleted, an empty body when it was not
|
|
found, is invalid or the caller is no admin.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: The hash
|
|
items:
|
|
type: string
|
|
pattern: "^RL[0-9A-Za-z=]+$"
|
|
example:
|
|
- RLkfx5cv4sq1i3ehpkz5bgdhcq9u9gkzj
|
|
responses:
|
|
"200":
|
|
description: "`1` if deleted, else an empty body"
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: integer
|
|
const: 1
|
|
example: 1
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/status/containers:
|
|
get:
|
|
summary: Get container status
|
|
description: >-
|
|
State, start time and image of every container of the mailcow
|
|
installation, stopped containers included, keyed by service name.
|
|
operationId: getContainerStatus
|
|
tags:
|
|
- Status
|
|
responses:
|
|
"200":
|
|
description: The containers, `null` if dockerapi cannot be reached
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties:
|
|
$ref: "#/components/schemas/ContainerStatus"
|
|
example:
|
|
dovecot-mailcow:
|
|
type: info
|
|
container: dovecot-mailcow
|
|
state: running
|
|
started_at: "2026-11-10T11:00:51.541059812Z"
|
|
image: ghcr.io/mailcow/dovecot:2.3.21.1-4
|
|
postfix-mailcow:
|
|
type: info
|
|
container: postfix-mailcow
|
|
state: running
|
|
started_at: "2026-11-10T11:00:51.292779901Z"
|
|
image: ghcr.io/mailcow/postfix:1.80
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/status/vmail:
|
|
get:
|
|
summary: Get mail storage status
|
|
description: Disk usage of the file system that holds the mail storage (`/var/vmail`).
|
|
operationId: getVmailStatus
|
|
tags:
|
|
- Status
|
|
responses:
|
|
"200":
|
|
description: The disk usage (`df -H` values)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
const: info
|
|
disk:
|
|
type: string
|
|
description: Device
|
|
used:
|
|
type: string
|
|
description: Used space
|
|
total:
|
|
type: string
|
|
description: Size of the file system
|
|
used_percent:
|
|
type: string
|
|
description: Used space in percent
|
|
example:
|
|
type: info
|
|
disk: /dev/sda1
|
|
used: 65G
|
|
total: 105G
|
|
used_percent: 66%
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/status/version:
|
|
get:
|
|
summary: Get mailcow version
|
|
description: >-
|
|
The installed mailcow version: the release tag on the master branch,
|
|
else the short commit ID.
|
|
operationId: getVersion
|
|
tags:
|
|
- Status
|
|
responses:
|
|
"200":
|
|
description: The version
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
version:
|
|
type: [string, "null"]
|
|
description: Release tag or commit ID
|
|
example:
|
|
version: "2026-11"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/status/container/{id}:
|
|
get:
|
|
summary: Get container statistics
|
|
description: >-
|
|
Resource statistics of one container: the last (up to three) Docker
|
|
stats snapshots, taken about five seconds apart while this route is
|
|
called. The container is named by its full Docker container ID (64 hex
|
|
digits, e.g. from `docker ps --no-trunc`), which the API does not
|
|
list. For an unknown ID the call waits until the dockerapi timeout (60
|
|
seconds) and answers with the curl error text as a JSON string.
|
|
operationId: getContainerStats
|
|
tags:
|
|
- Status
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Full Docker container ID
|
|
schema:
|
|
type: string
|
|
example: 5d0f3cbb2a6e4f6c8e0e1c3b9a7d2f41b6c5e8a9d0f1e2c3b4a5968778695a4b
|
|
responses:
|
|
"200":
|
|
description: >-
|
|
Docker stats objects (see the Docker Engine API, `ContainerStats`),
|
|
oldest first; `false` without ID
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
description: One Docker stats snapshot
|
|
properties:
|
|
read:
|
|
type: string
|
|
description: Time of the snapshot
|
|
name:
|
|
type: string
|
|
id:
|
|
type: string
|
|
cpu_stats:
|
|
type: object
|
|
precpu_stats:
|
|
type: object
|
|
memory_stats:
|
|
type: object
|
|
blkio_stats:
|
|
type: object
|
|
networks:
|
|
type: object
|
|
pids_stats:
|
|
type: object
|
|
additionalProperties: true
|
|
example:
|
|
- read: "2026-11-10T19:20:01.123456789Z"
|
|
name: /mailcowdockerized-dovecot-mailcow-1
|
|
id: 5d0f3cbb2a6e4f6c8e0e1c3b9a7d2f41b6c5e8a9d0f1e2c3b4a5968778695a4b
|
|
pids_stats:
|
|
current: 38
|
|
memory_stats:
|
|
usage: 104857600
|
|
limit: 12541669376
|
|
blkio_stats:
|
|
io_service_bytes_recursive:
|
|
- major: 8
|
|
minor: 0
|
|
op: read
|
|
value: 1052672
|
|
- major: 8
|
|
minor: 0
|
|
op: write
|
|
value: 40960
|
|
networks:
|
|
eth0:
|
|
rx_bytes: 2621440
|
|
tx_bytes: 1048576
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/status/host:
|
|
get:
|
|
summary: Get host statistics
|
|
description: CPU, memory, uptime and architecture of the Docker host.
|
|
operationId: getHostStatus
|
|
tags:
|
|
- Status
|
|
responses:
|
|
"200":
|
|
description: The host statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/HostStats"
|
|
example:
|
|
cpu:
|
|
cores: 4
|
|
usage: 6
|
|
memory:
|
|
total: 12541669376
|
|
usage: 62.5
|
|
swap:
|
|
- 1022357504
|
|
- 512716800
|
|
- 509640704
|
|
- 50.2
|
|
- 1392812032
|
|
- 3864260608
|
|
uptime: 703800.5492310524
|
|
system_time: "10.11.2026 19:13:07"
|
|
architecture: x86_64
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/status/host/ip:
|
|
get:
|
|
summary: Get public IP addresses
|
|
description: >-
|
|
The public IPv4 and IPv6 address of the server, as seen by the third
|
|
party services ipv4.mailcow.email and ipv6.mailcow.email (requested on
|
|
every call, regardless of the IP check setting of `edit/ip_check`).
|
|
Other path segments after `host` give an empty answer.
|
|
operationId: getHostIps
|
|
tags:
|
|
- Status
|
|
responses:
|
|
"200":
|
|
description: The addresses, `false` for an address that could not be determined
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
ipv4:
|
|
type: [string, boolean]
|
|
description: Public IPv4 address
|
|
ipv6:
|
|
type: [string, boolean]
|
|
description: Public IPv6 address
|
|
example:
|
|
ipv4: 198.51.100.25
|
|
ipv6: 2001:db8::25
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/syncjobs/all/no_log:
|
|
get:
|
|
summary: Get all sync jobs without logs
|
|
description: >-
|
|
Like `GET /api/v1/get/syncjobs/all`, with an empty `log` (the job list
|
|
of the UI). The last segment is a comma-separated option list, only
|
|
`no_log` has a meaning; other values are ignored.
|
|
operationId: getSyncJobsWithoutLog
|
|
tags:
|
|
- Sync jobs
|
|
responses:
|
|
"200":
|
|
description: The sync jobs
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SyncJob"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/syncjob_source/{id}:
|
|
get:
|
|
summary: Get sync source
|
|
description: >-
|
|
One sync source by id, with the visibility rules of
|
|
`GET /api/v1/get/syncjob_source/all`. Answers `{}` when the id is not a
|
|
whole number, the source does not exist or the caller may not see it.
|
|
operationId: getSyncJobSource
|
|
tags:
|
|
- Sync jobs
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Source id
|
|
schema:
|
|
type: integer
|
|
example: 4
|
|
responses:
|
|
"200":
|
|
description: The sync source
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SyncJobSource"
|
|
example:
|
|
id: 4
|
|
name: Google Workspace
|
|
description: ""
|
|
created_by: admin
|
|
scope: all
|
|
host1: imap.gmail.com
|
|
port1: 993
|
|
enc1: SSL
|
|
verify_cert: 1
|
|
auth_type: XOAUTH2
|
|
oauth_flow: authorization_code
|
|
oauth_token_endpoint: https://oauth2.googleapis.com/token
|
|
oauth_authorize_endpoint: https://accounts.google.com/o/oauth2/v2/auth
|
|
oauth_userinfo_endpoint: null
|
|
oauth_client_id: 1234567890-example.apps.googleusercontent.com
|
|
oauth_scope: https://mail.google.com/ openid email
|
|
oauth_extra_params: '{"access_type":"offline","prompt":"consent"}'
|
|
oauth_token_expires: null
|
|
oauth_last_refresh_error: null
|
|
oauth_last_refresh_attempt: null
|
|
created: "2026-11-01 10:00:00"
|
|
modified: null
|
|
active: 1
|
|
domains: []
|
|
users: []
|
|
can_edit: true
|
|
host: imap.gmail.com
|
|
port: 993
|
|
enc: SSL
|
|
has_client_secret: true
|
|
has_access_token: false
|
|
oauth_redirect_uri: https://mail.example.org/syncjob-oauth
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/syncjob_options:
|
|
get:
|
|
summary: Get allowed custom imapsync options
|
|
description: >-
|
|
The imapsync options sync jobs may use in `custom_params`
|
|
(`$IMAPSYNC_OPTIONS` of vars.local.inc.php, defaults from vars.inc.php;
|
|
options that run code, use local files or print secrets are always
|
|
removed). Option name (lowercase, without dashes) mapped to its rule:
|
|
`true` needs a value, `false` is a flag without value, a string is a
|
|
regular expression the whole value must match. Available to every
|
|
logged-in caller.
|
|
operationId: getSyncJobOptions
|
|
tags:
|
|
- Sync jobs
|
|
responses:
|
|
"200":
|
|
description: Option name => rule
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties:
|
|
type:
|
|
- boolean
|
|
- string
|
|
example:
|
|
authmd51: false
|
|
debugssl: true
|
|
folder: true
|
|
maxsize: true
|
|
syncinternaldates: false
|
|
sslargs1: "^SSL_verify_mode=[01]$"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/imapsync_settings:
|
|
get:
|
|
summary: Get global sync job settings
|
|
description: >-
|
|
Settings of the sync job runner (admins and API keys; `{}` for others).
|
|
operationId: getSyncJobSettings
|
|
tags:
|
|
- Sync jobs
|
|
responses:
|
|
"200":
|
|
description: The settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SyncJobSettings"
|
|
example:
|
|
max_parallel: 3
|
|
max_bytes_per_second: 2048000
|
|
max_kb_per_second: 2000
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/syncjobs/all:
|
|
get:
|
|
summary: Get all sync jobs
|
|
description: >-
|
|
All sync jobs in queue order (highest `prio` first, then jobs that
|
|
never ran, then the least recently run), with their logs. Admins (every
|
|
API key) get every job, also jobs whose local mailbox no longer exists;
|
|
domain admins the jobs of the mailboxes of their domains; mailbox users
|
|
none (see `GET /api/v1/get/syncjobs/{mailbox}`). Answers `{}` when
|
|
there is no job.
|
|
operationId: getSyncJobs
|
|
tags:
|
|
- Sync jobs
|
|
responses:
|
|
"200":
|
|
description: The sync jobs
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SyncJob"
|
|
example:
|
|
- id: 12
|
|
user2: alice@example.org
|
|
regextrans2: ""
|
|
authmd51: 0
|
|
domain2: ""
|
|
subfolder2: Imported
|
|
user1: alice@old-provider.example.com
|
|
exclude: "(?i)spam|(?i)junk"
|
|
maxage: 0
|
|
mins_interval: 20
|
|
maxbytespersecond: "0"
|
|
delete2duplicates: 1
|
|
delete1: 0
|
|
delete2: 0
|
|
automap: 1
|
|
skipcrossduplicates: 0
|
|
custom_params: '[{"o":"folder","v":"INBOX"}]'
|
|
timeout1: 600
|
|
timeout2: 600
|
|
subscribeall: 1
|
|
dry: 0
|
|
is_running: 0
|
|
last_run: "2026-11-09 08:20:01"
|
|
success: 1
|
|
exit_status: EX_OK
|
|
created: "2026-11-03 09:40:09"
|
|
modified: "2026-11-03 09:42:21"
|
|
active: 1
|
|
source_id: 3
|
|
custom_params_legacy: null
|
|
prio: 0
|
|
source_name: Old provider
|
|
source_description: Migration from the old provider
|
|
source_host: imap.example.com
|
|
source_port: 993
|
|
source_enc: SSL
|
|
source_auth_type: PLAIN
|
|
source_created_by: API
|
|
source_scope: domain
|
|
source_oauth_flow: client_credentials
|
|
source_active: 1
|
|
source_oauth_token_expires: null
|
|
source_oauth_last_refresh_error: null
|
|
user_token_expires: null
|
|
user_token_error: null
|
|
user_token_exists: 0
|
|
log: "Transfer started at Mon Nov 9 08:20:02 2026\n..."
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/syncjobs/{mailbox}:
|
|
get:
|
|
summary: Get sync jobs of a mailbox
|
|
description: >-
|
|
The sync jobs of a local mailbox in queue order, with their logs.
|
|
Admins (every API key) get the jobs of every existing mailbox, domain
|
|
admins of their mailboxes, users of their own. A value that is no email
|
|
address returns the caller's own jobs (none for an API key). Answers
|
|
`{}` when there is no job or no access.
|
|
operationId: getMailboxSyncJobs
|
|
tags:
|
|
- Sync jobs
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Local mailbox (`user2` of the jobs)
|
|
schema:
|
|
type: string
|
|
example: alice@example.org
|
|
responses:
|
|
"200":
|
|
description: The sync jobs of the mailbox
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SyncJob"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/syncjobs/{mailbox}/no_log:
|
|
get:
|
|
summary: Get sync jobs of a mailbox without logs
|
|
description: >-
|
|
Like `GET /api/v1/get/syncjobs/{mailbox}`, with an empty `log`. The
|
|
last segment is a comma-separated option list, only `no_log` has a
|
|
meaning.
|
|
operationId: getMailboxSyncJobsWithoutLog
|
|
tags:
|
|
- Sync jobs
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Local mailbox (`user2` of the jobs)
|
|
schema:
|
|
type: string
|
|
example: alice@example.org
|
|
responses:
|
|
"200":
|
|
description: The sync jobs of the mailbox
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SyncJob"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/syncjob_source/all:
|
|
get:
|
|
summary: Get sync sources
|
|
description: >-
|
|
The sync sources the caller may see, ordered by name: admins (every API
|
|
key) all; domain admins their own, `all` sources, sources for their
|
|
domains or mailboxes and sources created by their mailboxes; users
|
|
their own, `all` sources and sources for them or their domain. Secrets
|
|
are never returned (`has_client_secret`, `has_access_token`), extra
|
|
OAuth2 parameters only to callers who may edit the source (`can_edit`,
|
|
false for read-only API keys). Answers `{}` when there is no source.
|
|
operationId: getSyncJobSources
|
|
tags:
|
|
- Sync jobs
|
|
responses:
|
|
"200":
|
|
description: The sync sources
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SyncJobSource"
|
|
example:
|
|
- id: 3
|
|
name: Old provider
|
|
description: Migration from the old provider
|
|
created_by: API
|
|
scope: domain
|
|
host1: imap.example.com
|
|
port1: 993
|
|
enc1: SSL
|
|
verify_cert: 1
|
|
auth_type: PLAIN
|
|
oauth_flow: client_credentials
|
|
oauth_token_endpoint: null
|
|
oauth_authorize_endpoint: null
|
|
oauth_userinfo_endpoint: null
|
|
oauth_client_id: null
|
|
oauth_scope: null
|
|
oauth_extra_params: null
|
|
oauth_token_expires: null
|
|
oauth_last_refresh_error: null
|
|
oauth_last_refresh_attempt: null
|
|
created: "2026-11-03 09:42:21"
|
|
modified: null
|
|
active: 1
|
|
domains:
|
|
- example.org
|
|
users: []
|
|
can_edit: true
|
|
host: imap.example.com
|
|
port: 993
|
|
enc: SSL
|
|
has_client_secret: false
|
|
has_access_token: false
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/tls-policy-map/{id}:
|
|
get:
|
|
tags:
|
|
- Outgoing TLS Policy Map Overrides
|
|
summary: Get TLS policy maps
|
|
operationId: getTlsPolicyMaps
|
|
description: >-
|
|
`all` lists the TLS policy maps, an ID returns that map. `{}` if there
|
|
is none or the caller is no administrator. The answer for an ID
|
|
carries an additional member `"0": null` (json_api.php appends an
|
|
undefined variable).
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all` or the ID of a TLS policy map"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The list of TLS policy maps (`all`) or one TLS policy map
|
|
content:
|
|
application/json:
|
|
schema:
|
|
anyOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/TlsPolicyMap"
|
|
- $ref: "#/components/schemas/TlsPolicyMap"
|
|
examples:
|
|
all:
|
|
summary: get/tls-policy-map/all
|
|
value:
|
|
- id: 2
|
|
dest: example.com
|
|
policy: encrypt
|
|
parameters: protocols=>=TLSv1.2
|
|
active: 1
|
|
created: "2026-11-06 12:00:31"
|
|
modified: null
|
|
one:
|
|
summary: get/tls-policy-map/2
|
|
value:
|
|
id: 2
|
|
dest: example.com
|
|
policy: encrypt
|
|
parameters: protocols=>=TLSv1.2
|
|
active: 1
|
|
created: "2026-11-06 12:00:31"
|
|
modified: null
|
|
"0": null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/tls-policy-map:
|
|
post:
|
|
tags:
|
|
- Outgoing TLS Policy Map Overrides
|
|
summary: Update TLS policy maps
|
|
operationId: editTlsPolicyMap
|
|
description: >-
|
|
Changes the TLS policy maps in `items`; attributes that are left out
|
|
keep their value (`parameters: ""` clears the parameters).
|
|
Administrators and API keys only. Per map: `tls_policy_map_entry_saved`
|
|
or `access_denied` (unknown ID); `tls_policy_map_dest_invalid`,
|
|
`tls_policy_map_parameter_invalid` and an existing destination (answered
|
|
with `recipient_map_entry_exists`) stop the call.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: IDs of the TLS policy maps, a single value or a list
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
attr:
|
|
type: object
|
|
properties:
|
|
dest:
|
|
type: string
|
|
description: Destination, e.g. `example.org` or `[mail.example.org]:25`
|
|
policy:
|
|
type: string
|
|
enum:
|
|
- none
|
|
- may
|
|
- encrypt
|
|
- dane
|
|
- dane-only
|
|
- fingerprint
|
|
- verify
|
|
- secure
|
|
parameters:
|
|
type: string
|
|
description: Empty or space-separated `name=value` attributes
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 2
|
|
attr:
|
|
policy: dane
|
|
parameters: ""
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/transport/{id}:
|
|
get:
|
|
tags:
|
|
- Routing
|
|
summary: Get transport maps
|
|
operationId: getTransports
|
|
description: >-
|
|
`all` lists the transport maps, an ID returns that entry, with the
|
|
password in clear text. `{}` if there is none or the caller is no
|
|
administrator.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all` or the ID of a transport map"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The list of transport maps (`all`) or one entry
|
|
content:
|
|
application/json:
|
|
schema:
|
|
anyOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/Transport"
|
|
- $ref: "#/components/schemas/Transport"
|
|
examples:
|
|
all:
|
|
summary: get/transport/all
|
|
value:
|
|
- id: 4
|
|
is_mx_based: 0
|
|
destination: example.com
|
|
nexthop: "[mx.example.com]:25"
|
|
username: ""
|
|
password: ""
|
|
active: 1
|
|
password_short: "..."
|
|
- id: 5
|
|
is_mx_based: 1
|
|
destination: .*\.google\.com
|
|
nexthop: "[smtp.example.net]:587"
|
|
username: relay-user@example.net
|
|
password: Secret-Passphrase-42
|
|
active: 1
|
|
password_short: Sec...
|
|
one:
|
|
summary: get/transport/4
|
|
value:
|
|
id: 4
|
|
is_mx_based: 0
|
|
destination: example.com
|
|
nexthop: "[mx.example.com]:25"
|
|
username: ""
|
|
password: ""
|
|
active: 1
|
|
password_short: "..."
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/relayhost:
|
|
post:
|
|
tags:
|
|
- Routing
|
|
summary: Update sender-dependent transports
|
|
operationId: editRelayhost
|
|
description: >-
|
|
Changes the sender-dependent transports in `items`; attributes that are
|
|
left out keep their value (an empty `hostname` too). Administrators
|
|
and API keys only. Per entry: `object_modified` (without the host
|
|
name), `relayhost_invalid` (unknown ID), `mysql_error`.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: IDs of the sender-dependent transports, a single value or a list
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
attr:
|
|
type: object
|
|
properties:
|
|
hostname:
|
|
type: string
|
|
description: Next hop, e.g. `[smtp.example.com]:587`
|
|
username:
|
|
type: string
|
|
description: SMTP user name, empty for no authentication
|
|
password:
|
|
type: string
|
|
description: SMTP password
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 1
|
|
attr:
|
|
password: New-Secret-Passphrase-43
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/transport:
|
|
post:
|
|
tags:
|
|
- Routing
|
|
summary: Update transport maps
|
|
operationId: editTransport
|
|
description: >-
|
|
Changes the transport maps in `items`; attributes that are left out
|
|
keep their value (an empty `destination`, `nexthop`, `is_mx_based` or
|
|
`active` too). An empty `username` also clears the password. The
|
|
credentials are written to every entry with the same next hop.
|
|
Administrators and API keys only.
|
|
|
|
|
|
Per entry: `object_modified` (without names), `relayhost_invalid`
|
|
(unknown ID), `mysql_error`; `transport_dest_exists`,
|
|
`invalid_destination`, `next_hop_interferes` and
|
|
`next_hop_interferes_any` stop the call.
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: IDs of the transport maps, a single value or a list
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
attr:
|
|
type: object
|
|
properties:
|
|
destination:
|
|
type: string
|
|
description: One destination (see add/transport)
|
|
nexthop:
|
|
type: string
|
|
description: Next hop, e.g. `[mx.example.com]:25`
|
|
username:
|
|
type: string
|
|
description: SMTP user name; empty removes the credentials
|
|
password:
|
|
type: string
|
|
description: SMTP password
|
|
is_mx_based:
|
|
type: [boolean, integer, string]
|
|
description: 1 = `destination` is a regular expression for MX names
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = active, 0 = inactive
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 4
|
|
attr:
|
|
nexthop: "[mx2.example.com]:25"
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/cors:
|
|
post:
|
|
summary: Edit CORS settings
|
|
description: >-
|
|
Sets which origins (web pages of other hosts) may call the API from a
|
|
browser and with which methods. A missing value is replaced by its
|
|
default. `items` is not used.
|
|
|
|
|
|
Success: `cors_headers_edited`. Errors: `cors_invalid_origin`,
|
|
`cors_invalid_method`.
|
|
operationId: editCors
|
|
tags:
|
|
- Cross-Origin Resource Sharing (CORS)
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
attr:
|
|
type: object
|
|
properties:
|
|
allowed_origins:
|
|
description: >-
|
|
Origins (`scheme://host[:port]`, http or https, no path)
|
|
or `*` for any origin; a list or a string with one
|
|
origin per line. Default: the URL of the mailcow host.
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: string
|
|
- type: string
|
|
allowed_methods:
|
|
description: >-
|
|
Allowed methods: `GET`, `POST`, `PUT`, `DELETE`
|
|
(uppercase); a list or a string separated by single
|
|
spaces, commas, semicolons or newlines (`GET,POST`, not
|
|
`GET, POST`). Default: all four.
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: string
|
|
enum:
|
|
- GET
|
|
- POST
|
|
- PUT
|
|
- DELETE
|
|
- type: string
|
|
required:
|
|
- attr
|
|
example:
|
|
attr:
|
|
allowed_origins:
|
|
- https://app.example.org
|
|
- https://admin.example.com:8443
|
|
allowed_methods:
|
|
- GET
|
|
- POST
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/spam-score/{mailbox}:
|
|
get:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Get the spam score of a mailbox
|
|
operationId: getSpamScore
|
|
description: >-
|
|
The spam score thresholds of the mailbox: its own values or the server
|
|
default. `{}` if the caller has no access to the mailbox (a mailbox
|
|
user: other mailboxes).
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: Thresholds
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SpamScore"
|
|
example:
|
|
score: "6,12"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/spam-score:
|
|
post:
|
|
tags:
|
|
- Mailbox user settings
|
|
summary: Set the spam score of mailboxes
|
|
operationId: editSpamScore
|
|
description: >-
|
|
Sets the spam thresholds of the mailboxes: from the first value on mail
|
|
goes to the junk folder, from the second it is rejected (equal values:
|
|
the second is raised by 0.1). `default` removes the own values. Needs
|
|
the user ACL `spam_score`. API keys may change any mailbox, a mailbox
|
|
user only its own. Messages per mailbox: `mailbox_modified` or
|
|
`access_denied`, "Invalid spam score, format must be "1,2" where first
|
|
is low and second is high spam value.".
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
attr:
|
|
type: object
|
|
required:
|
|
- spam_score
|
|
properties:
|
|
spam_score:
|
|
type: string
|
|
description: '"low,high" (numbers) or "default"'
|
|
examples:
|
|
- "6,12"
|
|
- default
|
|
example:
|
|
items:
|
|
- john.doe@example.org
|
|
attr:
|
|
spam_score: "6,12"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/mailbox/template:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Create a mailbox template
|
|
operationId: addMailboxTemplate
|
|
description: >-
|
|
Saves a named set of mailbox settings that `add/mailbox` (field
|
|
`template`) and the UI use as defaults. Admins only (`access_denied`
|
|
otherwise). Errors: `template_name_invalid` (empty name),
|
|
`template_exists`, `quarantine_category_invalid`. Success:
|
|
`template_added`. Fields that are not sent get the defaults named in
|
|
the schema; without `acl` the template grants no user ACL.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- type: object
|
|
required:
|
|
- template
|
|
properties:
|
|
template:
|
|
type: string
|
|
description: Name of the template
|
|
- $ref: "#/components/schemas/MailboxTemplateInput"
|
|
example:
|
|
template: Sales
|
|
quota: 2048
|
|
tags:
|
|
- sales
|
|
quarantine_notification: daily
|
|
quarantine_category: reject
|
|
rl_value: 100
|
|
rl_frame: h
|
|
active: 1
|
|
protocol_access:
|
|
- imap
|
|
- smtp
|
|
- sieve
|
|
acl:
|
|
- spam_alias
|
|
- spam_score
|
|
- app_passwds
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/mailbox/all:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get all mailboxes
|
|
operationId: getMailboxes
|
|
description: >-
|
|
Details of every mailbox in the domains the caller manages (API keys
|
|
and admins: all domains). Resources are not included. `{}` when there
|
|
are none.
|
|
parameters:
|
|
- $ref: "#/components/parameters/MailboxTagsQuery"
|
|
responses:
|
|
"200":
|
|
description: List of mailboxes
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Mailbox"
|
|
examples:
|
|
mailboxes:
|
|
$ref: "#/components/examples/MailboxList"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox/all/{domains}:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get the mailboxes of domains
|
|
operationId: getMailboxesOfDomains
|
|
description: >-
|
|
Like `get/mailbox/all`, limited to the given domains. Caution: a domain
|
|
that does not exist or that the caller does not manage adds all
|
|
mailboxes the caller manages (API keys: every mailbox) to the answer.
|
|
`{}` when nothing is found.
|
|
parameters:
|
|
- name: domains
|
|
in: path
|
|
required: true
|
|
description: Domain name or comma-separated list of domain names
|
|
schema:
|
|
type: string
|
|
example: example.org
|
|
- $ref: "#/components/parameters/MailboxTagsQuery"
|
|
responses:
|
|
"200":
|
|
description: List of mailboxes
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Mailbox"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox/reduced:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get all mailboxes (reduced details)
|
|
operationId: getMailboxesReduced
|
|
description: >-
|
|
Like `get/mailbox/all`, but each mailbox without the costly fields
|
|
`max_new_quota`, `spam_aliases`, `pushover_active`, `rl`, `rl_scope`,
|
|
`is_relayed` and `sender_acl`. Faster for large installations.
|
|
parameters:
|
|
- $ref: "#/components/parameters/MailboxTagsQuery"
|
|
responses:
|
|
"200":
|
|
description: List of mailboxes
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Mailbox"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox/reduced/{domains}:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get the mailboxes of domains (reduced details)
|
|
operationId: getMailboxesReducedOfDomains
|
|
description: >-
|
|
Like `get/mailbox/reduced`, limited to the given domains, with the same
|
|
caution as `get/mailbox/all/{domains}`: an unknown domain adds all
|
|
mailboxes the caller manages.
|
|
parameters:
|
|
- name: domains
|
|
in: path
|
|
required: true
|
|
description: Domain name or comma-separated list of domain names
|
|
schema:
|
|
type: string
|
|
example: example.org,example.com
|
|
- $ref: "#/components/parameters/MailboxTagsQuery"
|
|
responses:
|
|
"200":
|
|
description: List of mailboxes
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Mailbox"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox/template/all:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get all mailbox templates
|
|
operationId: getMailboxTemplates
|
|
description: >-
|
|
All mailbox templates. Admins and domain admins; `{}` for others or
|
|
when there is none.
|
|
responses:
|
|
"200":
|
|
description: List of templates
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/MailboxTemplate"
|
|
example:
|
|
- id: 2
|
|
template: Default
|
|
type: mailbox
|
|
attributes:
|
|
tags: []
|
|
quota: 0
|
|
quarantine_notification: hourly
|
|
quarantine_category: reject
|
|
rl_frame: s
|
|
rl_value: ""
|
|
force_pw_update: 0
|
|
force_tfa: 0
|
|
sogo_access: 1
|
|
active: 1
|
|
tls_enforce_in: 0
|
|
tls_enforce_out: 0
|
|
imap_access: 1
|
|
pop3_access: 1
|
|
smtp_access: 1
|
|
sieve_access: 1
|
|
eas_access: 1
|
|
dav_access: 1
|
|
acl_spam_alias: 1
|
|
acl_tls_policy: 1
|
|
acl_spam_score: 1
|
|
acl_spam_policy: 1
|
|
acl_delimiter_action: 1
|
|
acl_syncjobs: 0
|
|
acl_eas_reset: 1
|
|
acl_sogo_profile_reset: 0
|
|
acl_pushover: 1
|
|
acl_quarantine: 1
|
|
acl_quarantine_attachments: 1
|
|
acl_quarantine_notification: 1
|
|
acl_quarantine_category: 1
|
|
acl_app_passwds: 1
|
|
created: "2026-09-21 10:23:08"
|
|
modified: null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/mailbox/template/{id}:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get a mailbox template
|
|
operationId: getMailboxTemplate
|
|
description: >-
|
|
One mailbox template by its ID, `{}` if there is none. Admins and
|
|
domain admins.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Template ID
|
|
schema:
|
|
type: integer
|
|
example: 2
|
|
responses:
|
|
"200":
|
|
description: The template
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MailboxTemplate"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/mailbox/template:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Update mailbox templates
|
|
operationId: editMailboxTemplate
|
|
description: >-
|
|
Changes mailbox templates and passes the change on to the mailboxes
|
|
whose effective group template it is. Admins only (`access_denied`).
|
|
The template "Default" keeps its name. Messages: `template_id_invalid`,
|
|
`quarantine_category_invalid`, once at the end `template_modified`.
|
|
|
|
|
|
Send the complete template as the UI does: values that are not sent are
|
|
not taken over from the stored template. `quota` falls back to 0
|
|
(unlimited), `quarantine_category` must be sent (else
|
|
`quarantine_category_invalid`), and without `protocol_access` or `acl`
|
|
the protocol or ACL settings are lost.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Template ID or list of template IDs
|
|
oneOf:
|
|
- type: integer
|
|
- type: array
|
|
items:
|
|
type: integer
|
|
attr:
|
|
allOf:
|
|
- type: object
|
|
properties:
|
|
template:
|
|
type: string
|
|
description: New name of the template (not for "Default")
|
|
- $ref: "#/components/schemas/MailboxTemplateInput"
|
|
example:
|
|
items:
|
|
- 3
|
|
attr:
|
|
template: Sales
|
|
quota: 4096
|
|
tags:
|
|
- sales
|
|
tagged_mail_handler: subfolder
|
|
quarantine_notification: daily
|
|
quarantine_category: reject
|
|
rl_value: 100
|
|
rl_frame: h
|
|
force_pw_update: 0
|
|
force_tfa: 0
|
|
sogo_access: 1
|
|
active: 1
|
|
tls_enforce_in: 0
|
|
tls_enforce_out: 1
|
|
protocol_access:
|
|
- imap
|
|
- smtp
|
|
- sieve
|
|
- dav
|
|
acl:
|
|
- spam_alias
|
|
- spam_score
|
|
- delimiter_action
|
|
- app_passwds
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/rename-mbox:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Rename a mailbox
|
|
operationId: renameMailbox
|
|
description: >-
|
|
Renames `old_local_part@domain` to `new_local_part@domain`: the address
|
|
in all tables (aliases, ACLs, filters, app passwords, BCC and recipient
|
|
maps, sync jobs, groups, SOGo), the maildir and the SOGo account; IMAP
|
|
ACLs are moved over. `items` is not used, the mailbox is named in
|
|
`attr`. The mailbox must be active (1 or 2). Admins and domain admins
|
|
(for their domains). Errors: `username_invalid`, `access_denied`.
|
|
Success: `mailbox_renamed`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Not used
|
|
attr:
|
|
type: object
|
|
required:
|
|
- domain
|
|
- old_local_part
|
|
- new_local_part
|
|
properties:
|
|
domain:
|
|
type: string
|
|
description: Domain of the mailbox
|
|
old_local_part:
|
|
type: string
|
|
description: Current local part
|
|
new_local_part:
|
|
type: string
|
|
description: New local part
|
|
create_alias:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
description: 1 creates an alias from the old to the new address
|
|
example:
|
|
items: []
|
|
attr:
|
|
domain: example.org
|
|
old_local_part: john.doe
|
|
new_local_part: john
|
|
create_alias: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/mailbox/template:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Delete mailbox templates
|
|
operationId: deleteMailboxTemplate
|
|
description: >-
|
|
Deletes mailbox templates by ID; the template "Default" is kept
|
|
silently. Admins only (`access_denied`). Answers `template_removed`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Template IDs
|
|
items:
|
|
type: integer
|
|
example:
|
|
- 3
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/last-login/{mailbox}:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get the last logins of a mailbox
|
|
operationId: getLastLogin
|
|
description: >-
|
|
Logins of the mailbox in the last 7 days (`sasl`: one entry per
|
|
address, service and app password with the latest time) and its
|
|
previous UI login (`ui`, the one before the latest). `sasl` is empty
|
|
without access to the mailbox; `ui` is only given to admins (API keys)
|
|
and the mailbox user itself (`false` when there is none), domain admins
|
|
get an empty list.
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: Logins
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/LastLogin"
|
|
example:
|
|
ui:
|
|
remote: 198.51.100.23
|
|
time: 1793011200
|
|
sasl:
|
|
- real_rip: 198.51.100.23
|
|
datetime: "2026-11-09 08:12:44"
|
|
service: imap
|
|
app_password: 23
|
|
app_password_name: Thunderbird
|
|
location: DE
|
|
- real_rip: Web/EAS/Internal (172.22.1.248)
|
|
datetime: "2026-11-08 17:03:10"
|
|
service: SOGO
|
|
app_password: 0
|
|
app_password_name: null
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/last-login/{mailbox}/{days}:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get the last logins of a mailbox for a period
|
|
operationId: getLastLoginDays
|
|
description: >-
|
|
Like `get/last-login/{mailbox}` for the last `{days}` days; values
|
|
below 1 mean 7.
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
- name: days
|
|
in: path
|
|
required: true
|
|
description: Number of days
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
example: 30
|
|
responses:
|
|
"200":
|
|
description: Logins
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/LastLogin"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/reset-last-login/{mailbox}:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Clear the login history of a mailbox
|
|
operationId: resetLastLogin
|
|
description: >-
|
|
Deletes the stored logins of the mailbox (the SASL log and, for admins
|
|
and the mailbox user itself, the successful UI logins). A `get` route
|
|
that changes data: read-only API keys can call it too. Always answers
|
|
`true`.
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: Done
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: boolean
|
|
example: true
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/delete/eas_cache:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Reset the ActiveSync devices of mailboxes
|
|
operationId: deleteEasCache
|
|
description: >-
|
|
Deletes the ActiveSync device cache of the mailboxes, so devices sync
|
|
from scratch. Needs the user ACL `eas_reset`. API keys may reset any
|
|
mailbox, a mailbox user only its own. Messages per mailbox: `eas_reset`
|
|
or `access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
example:
|
|
- john.doe@example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/sogo_profile:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Reset the SOGo profile of mailboxes
|
|
operationId: deleteSogoProfile
|
|
description: >-
|
|
Deletes the SOGo data of the mailboxes: profile, settings, calendars,
|
|
address books and their shares. Needs the user ACL
|
|
`sogo_profile_reset`. API keys may reset any mailbox, a mailbox user
|
|
only its own. Messages per mailbox: `sogo_profile_reset` or
|
|
`access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MailboxItems"
|
|
example:
|
|
- john.doe@example.org
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/bcc-destination-options:
|
|
get:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Get the possible BCC map destinations
|
|
operationId: getBccDestinationOptions
|
|
description: >-
|
|
What a BCC map can be bound to: the domains the caller manages, per
|
|
mailbox the mailbox and its aliases (aliases of other domains only if
|
|
the caller manages them), and the alias domains. Keys without entries
|
|
are left out.
|
|
responses:
|
|
"200":
|
|
description: Domains, mailboxes with their addresses, alias domains
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
domains:
|
|
type: array
|
|
items:
|
|
type: string
|
|
mailboxes:
|
|
type: object
|
|
description: Mailbox address → the mailbox and its aliases
|
|
additionalProperties:
|
|
type: array
|
|
items:
|
|
type: string
|
|
alias_domains:
|
|
type: array
|
|
items:
|
|
type: string
|
|
example:
|
|
domains:
|
|
- example.org
|
|
mailboxes:
|
|
john.doe@example.org:
|
|
- john.doe@example.org
|
|
- sales@example.org
|
|
jane.roe@example.org:
|
|
- jane.roe@example.org
|
|
alias_domains:
|
|
- example.net
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/search/mailbox:
|
|
post:
|
|
tags:
|
|
- Mailboxes
|
|
summary: Search mailboxes page by page
|
|
operationId: searchMailboxes
|
|
description: >-
|
|
Server-side search behind the mailbox table of the UI, with the request
|
|
and answer format of DataTables (server-side processing): paging,
|
|
sorting and a search over the mailboxes the caller manages (API keys:
|
|
all; resources are not included). Read-only API keys may use it.
|
|
Mailbox users get `403` with `Insufficient permissions`.
|
|
|
|
|
|
Columns are addressed by number, as in the UI table: 2 address
|
|
(`username`), 3 quota, 4 last mail login, 5 last password change, 6
|
|
quota in use, 7 name, 20 messages, 23 tags, 24 active. Sorting works on
|
|
all of them except 23; searching on 2, 3, 7, 23 and 24. Searching in 4,
|
|
5, 6 or 20 or sorting by 23 makes the database query fail, so send
|
|
these columns as not searchable/orderable. Other numbers stand for the
|
|
address. `columns` is needed for a search or a sort:
|
|
`columns[n]` describes column n.
|
|
|
|
|
|
Each entry of `data` holds the full details of a mailbox, like
|
|
`get/mailbox/{id}`. `recordsTotal` counts the mailboxes after the
|
|
search too (same as `recordsFiltered`).
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/MailboxSearchRequest"
|
|
example:
|
|
draw: 1
|
|
start: 0
|
|
length: 25
|
|
search:
|
|
value: john
|
|
order:
|
|
- column: 2
|
|
dir: asc
|
|
columns:
|
|
- searchable: false
|
|
orderable: false
|
|
- searchable: false
|
|
orderable: false
|
|
- data: username
|
|
searchable: true
|
|
orderable: true
|
|
- searchable: false
|
|
orderable: true
|
|
- searchable: false
|
|
orderable: true
|
|
- searchable: false
|
|
orderable: true
|
|
- searchable: false
|
|
orderable: true
|
|
- data: name
|
|
searchable: true
|
|
orderable: true
|
|
responses:
|
|
"200":
|
|
description: >-
|
|
One page of mailboxes. A failing database query answers
|
|
`{"error": "An SQL error occurred: ..."}` instead.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- $ref: "#/components/schemas/MailboxSearchResult"
|
|
- type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
examples:
|
|
page:
|
|
$ref: "#/components/examples/MailboxSearchPage"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
description: The caller is a mailbox user or not logged in
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Error"
|
|
example:
|
|
type: error
|
|
msg: Insufficient permissions
|
|
/api/v1/edit/identity-provider:
|
|
post:
|
|
summary: Configure the Identity Provider
|
|
description: >-
|
|
Admins only (every read/write API key). Saves the configuration of the
|
|
external Identity Provider (Keycloak, generic OpenID Connect or LDAP).
|
|
Send the complete configuration of the provider: every setting of the
|
|
provider is written, settings that are not sent get their default (flags
|
|
off, `login_provisioning` off, `group_autocreate` off), and the secrets
|
|
(`client_secret`, `bindpass`) must be sent again. `redirect_url_extra`,
|
|
`default_template` and the `mappers`/`templates` pair are only changed
|
|
when sent. Settings of other providers stay stored. The cached Keycloak
|
|
access token is cleared. Changing the LDAP `id_attribute` drops the
|
|
stored LDAP ids (mailboxes are linked by email again). `items` is not
|
|
used.
|
|
|
|
|
|
Answers `object_modified`. Errors: `required_data_missing` (`authsource`
|
|
or a required setting missing: Keycloak `server_url`, `realm`,
|
|
`client_id`, `client_secret`, `redirect_url`, `version`; generic-oidc
|
|
`authorize_url`, `token_url`, `userinfo_url`, `client_id`,
|
|
`client_secret`, `redirect_url`; LDAP `basedn`, `binddn`, `bindpass`),
|
|
`invalid_authsource`, `authsource_in_use` (mailboxes use another
|
|
external provider), `access_denied`. Secrets are logged as `*`.
|
|
operationId: editIdentityProvider
|
|
tags:
|
|
- Identity Provider
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Not used
|
|
attr:
|
|
$ref: "#/components/schemas/IdentityProviderAttributes"
|
|
examples:
|
|
keycloak:
|
|
value:
|
|
attr:
|
|
authsource: keycloak
|
|
server_url: https://auth.example.org
|
|
realm: mailcow
|
|
client_id: mailcow
|
|
client_secret: client-secret-value
|
|
redirect_url: https://mail.example.org
|
|
redirect_url_extra:
|
|
- https://webmail.example.org
|
|
version: 26.1.3
|
|
login_provisioning: 1
|
|
mailpassword_flow: 0
|
|
periodic_sync: 1
|
|
import_users: 1
|
|
sync_interval: 15
|
|
offboarding: 1
|
|
offboarding_limit: 10
|
|
group_sync: 1
|
|
group_autocreate: 1
|
|
group_paths: /mailcow/*
|
|
group_default_domain: example.org
|
|
default_template: Default
|
|
mappers:
|
|
- staff
|
|
templates:
|
|
- Staff
|
|
ldap:
|
|
value:
|
|
attr:
|
|
authsource: ldap
|
|
host: ldap1.example.org,ldap2.example.org
|
|
port: 636
|
|
use_ssl: 1
|
|
use_tls: 0
|
|
ignore_ssl_error: 0
|
|
basedn: dc=example,dc=org
|
|
binddn: cn=mailcow,ou=services,dc=example,dc=org
|
|
bindpass: bind-password
|
|
username_field: mail
|
|
filter: (objectClass=inetOrgPerson)
|
|
attribute_field: departmentNumber
|
|
login_provisioning: 1
|
|
periodic_sync: 1
|
|
import_users: 1
|
|
sync_interval: 30
|
|
group_sync: 1
|
|
group_filter: (objectClass=groupOfNames)
|
|
group_member_mode: member
|
|
group_member_attribute: member
|
|
default_template: Default
|
|
generic-oidc:
|
|
value:
|
|
attr:
|
|
authsource: generic-oidc
|
|
authorize_url: https://sso.example.org/application/o/authorize/
|
|
token_url: https://sso.example.org/application/o/token/
|
|
userinfo_url: https://sso.example.org/application/o/userinfo/
|
|
client_id: mailcow
|
|
client_secret: client-secret-value
|
|
redirect_url: https://mail.example.org
|
|
client_scopes: openid profile email mailcow_template
|
|
login_provisioning: 1
|
|
default_template: Default
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/identity-provider:
|
|
get:
|
|
summary: Get Identity Provider settings
|
|
description: >-
|
|
The stored settings of the external Identity Provider (admins and API
|
|
keys; `{}` for others). Values are returned as stored (mostly strings),
|
|
also settings of a provider that was configured before. Read-only API
|
|
keys get `*` instead of `client_secret`, `bindpass` and `access_token`;
|
|
read/write API keys get them in plain text. Without a configuration the
|
|
answer is `{"login_provisioning": 1}`. Any further path segment other
|
|
than `sync-status` returns the same.
|
|
operationId: getIdentityProvider
|
|
tags:
|
|
- Identity Provider
|
|
responses:
|
|
"200":
|
|
description: The settings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/IdentityProviderSettings"
|
|
example:
|
|
authsource: keycloak
|
|
server_url: https://auth.example.org
|
|
realm: mailcow
|
|
client_id: mailcow
|
|
client_secret: "*"
|
|
redirect_url: https://mail.example.org
|
|
redirect_url_extra:
|
|
- https://webmail.example.org
|
|
version: 26.1.3
|
|
mailpassword_flow: "0"
|
|
periodic_sync: "1"
|
|
import_users: "1"
|
|
sync_interval: "15"
|
|
ignore_ssl_error: false
|
|
login_provisioning: true
|
|
group_paths: /mailcow/*
|
|
offboarding: "1"
|
|
offboarding_limit: "10"
|
|
group_sync: "1"
|
|
group_autocreate: "1"
|
|
group_default_domain: example.org
|
|
default_template: Default
|
|
mappers:
|
|
- staff
|
|
templates:
|
|
- Staff
|
|
access_token: "*"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/identity-provider-test:
|
|
post:
|
|
summary: Test an Identity Provider connection
|
|
description: >-
|
|
Admins only (every read/write API key). Tests the connection data in
|
|
`attr` (the stored settings are not used, send the secrets too):
|
|
Keycloak requests a client_credentials token from
|
|
`<server_url>/realms/<realm>/protocol/openid-connect/token`, generic-oidc
|
|
sends an OPTIONS request to `token_url` (both succeed on HTTP 200, 7 s
|
|
timeout), LDAP connects and binds with `host`, `port`, `basedn`,
|
|
`binddn`, `bindpass` (all required), `use_ssl`, `use_tls`. Nothing is
|
|
stored. `items` is not used.
|
|
|
|
|
|
The answer carries no details: `{"type": "success", "msg": "Task
|
|
completed"}` or `{"type": "error", "msg": "Cannot edit item"}`
|
|
(`access_denied` for non-admins). A missing or unknown `authsource`
|
|
answers success without testing anything.
|
|
operationId: testIdentityProvider
|
|
tags:
|
|
- Identity Provider
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Not used
|
|
attr:
|
|
type: object
|
|
required:
|
|
- authsource
|
|
properties:
|
|
authsource:
|
|
type: string
|
|
enum:
|
|
- keycloak
|
|
- generic-oidc
|
|
- ldap
|
|
server_url:
|
|
type: string
|
|
description: Keycloak base URL
|
|
realm:
|
|
type: string
|
|
description: Keycloak realm
|
|
client_id:
|
|
type: string
|
|
description: Keycloak client id
|
|
client_secret:
|
|
type: string
|
|
description: Keycloak client secret
|
|
token_url:
|
|
type: string
|
|
description: generic-oidc token endpoint
|
|
ignore_ssl_error:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: Do not verify the TLS certificate
|
|
host:
|
|
type: string
|
|
description: LDAP host, or several separated by commas
|
|
port:
|
|
type:
|
|
- integer
|
|
- string
|
|
description: LDAP port
|
|
basedn:
|
|
type: string
|
|
binddn:
|
|
type: string
|
|
bindpass:
|
|
type: string
|
|
use_ssl:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: LDAPS
|
|
use_tls:
|
|
type:
|
|
- boolean
|
|
- integer
|
|
- string
|
|
description: StartTLS, ignored with `use_ssl`
|
|
example:
|
|
attr:
|
|
authsource: keycloak
|
|
server_url: https://auth.example.org
|
|
realm: mailcow
|
|
client_id: mailcow
|
|
client_secret: client-secret-value
|
|
ignore_ssl_error: 0
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/identity-provider:
|
|
post:
|
|
summary: Delete the Identity Provider configuration
|
|
description: >-
|
|
Admins only (every read/write API key). Deletes all Identity Provider
|
|
settings, all mailbox links (`identity-link`) and the sync run history.
|
|
Refused with `authsource_in_use` while any mailbox uses an external
|
|
provider. The body must be valid JSON, its content is not used (e.g.
|
|
`[]`). Answers `item_deleted`, or `authsource_in_use`, `access_denied`.
|
|
operationId: deleteIdentityProvider
|
|
tags:
|
|
- Identity Provider
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
description: Not used, any JSON value
|
|
example: []
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/filter:
|
|
post:
|
|
tags:
|
|
- Mailbox filters
|
|
summary: Create a Sieve filter
|
|
operationId: addFilter
|
|
description: >-
|
|
Adds a Sieve script to a mailbox. Needs the ACL `filters`, which admins
|
|
(API keys) and domain admins have, mailbox users not. `username` is
|
|
required for API keys and domain admins (`no_user_defined`). The script
|
|
is checked with a Sieve parser (`sieve_error`). Activating a filter
|
|
deactivates the other filters of the same type and mailbox. Errors:
|
|
`access_denied`, `script_empty`, `value_missing`, `filter_type`.
|
|
Success: `mailbox_modified`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- username
|
|
- script_data
|
|
- script_desc
|
|
- filter_type
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Mailbox of the filter
|
|
script_desc:
|
|
type: string
|
|
description: Description
|
|
script_data:
|
|
type: string
|
|
description: The Sieve script
|
|
filter_type:
|
|
type: string
|
|
enum:
|
|
- prefilter
|
|
- postfilter
|
|
description: Runs before (prefilter) or after (postfilter) the user's own filters
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
default: 0
|
|
example:
|
|
username: john.doe@example.org
|
|
script_desc: Move newsletters
|
|
script_data: |-
|
|
require "fileinto";
|
|
if header :contains "List-Id" "newsletter" {
|
|
fileinto "Newsletters";
|
|
}
|
|
filter_type: prefilter
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/filters/all:
|
|
get:
|
|
tags:
|
|
- Mailbox filters
|
|
summary: Get all Sieve filters
|
|
operationId: getFilters
|
|
description: >-
|
|
The Sieve filters of all mailboxes the caller manages, `{}` when there
|
|
are none.
|
|
responses:
|
|
"200":
|
|
description: List of filters
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SieveFilter"
|
|
example:
|
|
- active: 1
|
|
id: 7
|
|
username: john.doe@example.org
|
|
filter_type: prefilter
|
|
script_data: |-
|
|
require "fileinto";
|
|
if header :contains "List-Id" "newsletter" {
|
|
fileinto "Newsletters";
|
|
}
|
|
script_desc: Move newsletters
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/filters/{mailbox}:
|
|
get:
|
|
tags:
|
|
- Mailbox filters
|
|
summary: Get the Sieve filters of a mailbox
|
|
operationId: getMailboxFilters
|
|
description: >-
|
|
The Sieve filters of the mailbox, `{}` when there are none or the
|
|
caller has no access. If `{mailbox}` is no address, the session user's
|
|
filters are returned (nothing for API keys).
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: List of filters
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SieveFilter"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/filter:
|
|
post:
|
|
tags:
|
|
- Mailbox filters
|
|
summary: Update Sieve filters
|
|
operationId: editFilter
|
|
description: >-
|
|
Changes filters by ID; fields that are not sent keep their value.
|
|
Needs the ACL `filters` (admins, domain admins). Activating a filter
|
|
deactivates the other filters of the same type and mailbox. Messages
|
|
per ID: `mailbox_modified` or `access_denied` (unknown ID or no
|
|
access), `sieve_error`, `filter_type`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- items
|
|
- attr
|
|
properties:
|
|
items:
|
|
description: Filter ID or list of IDs
|
|
oneOf:
|
|
- type: integer
|
|
- type: array
|
|
items:
|
|
type: integer
|
|
attr:
|
|
type: object
|
|
properties:
|
|
script_desc:
|
|
type: string
|
|
script_data:
|
|
type: string
|
|
filter_type:
|
|
type: string
|
|
enum:
|
|
- prefilter
|
|
- postfilter
|
|
active:
|
|
type: [integer, string]
|
|
enum: [0, 1, "0", "1"]
|
|
example:
|
|
items:
|
|
- 7
|
|
attr:
|
|
active: 0
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/filter:
|
|
post:
|
|
tags:
|
|
- Mailbox filters
|
|
summary: Delete Sieve filters
|
|
operationId: deleteFilter
|
|
description: >-
|
|
Deletes filters by ID; IDs that are not numeric are skipped. Needs the
|
|
ACL `filters` (admins, domain admins). Messages per ID: `delete_filter`
|
|
or `access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Filter IDs
|
|
items:
|
|
type: integer
|
|
example:
|
|
- 7
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/active-user-sieve/{mailbox}:
|
|
get:
|
|
tags:
|
|
- Mailbox filters
|
|
summary: Get the active Sieve script of a mailbox
|
|
operationId: getActiveUserSieve
|
|
description: >-
|
|
The Sieve script the user activated in its mail client or SOGo (read
|
|
from Dovecot), as a list with one string. `{}` when there is none or
|
|
the caller has no access. If `{mailbox}` is no address, the session
|
|
user's script is read (nothing for API keys).
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: The script as the only element of a list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
maxItems: 1
|
|
items:
|
|
type: string
|
|
example:
|
|
- |-
|
|
require ["fileinto"];
|
|
if header :contains "subject" "invoice" {
|
|
fileinto "Invoices";
|
|
}
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/add/mailbox-policy:
|
|
post:
|
|
tags:
|
|
- Mailbox antispam policies
|
|
summary: Add a sender to the allow or deny list of a mailbox
|
|
operationId: addMailboxPolicy
|
|
description: >-
|
|
Adds a sender address or pattern to the spam allow list (`wl`, mail is
|
|
never treated as spam) or deny list (`bl`, mail is rejected) of a
|
|
mailbox. Needs the user ACL `spam_policy`. `username` is required for
|
|
all callers; a mailbox user may only name its own mailbox. Errors:
|
|
`access_denied`, `policy_list_from_invalid` (characters other than
|
|
letters, digits, `@ _ . - *`), `policy_list_from_exists`. Success:
|
|
`mailbox_modified`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- username
|
|
- object_list
|
|
- object_from
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Mailbox
|
|
object_list:
|
|
type: string
|
|
enum:
|
|
- wl
|
|
- bl
|
|
description: wl = allow list, bl = deny list
|
|
object_from:
|
|
type: string
|
|
description: Sender address, domain or pattern with `*`
|
|
example:
|
|
username: john.doe@example.org
|
|
object_list: bl
|
|
object_from: "*@spam.example.com"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/policy_wl_mailbox/{mailbox}:
|
|
get:
|
|
tags:
|
|
- Mailbox antispam policies
|
|
summary: Get the allow list of a mailbox
|
|
operationId: getMailboxPolicyAllowList
|
|
description: >-
|
|
The allow list entries that apply to the mailbox: its own and those of
|
|
its domain (`object` tells which). `{}` when there are none, the
|
|
mailbox does not exist or the caller has no access. If `{mailbox}` is
|
|
no address, the session user's list is returned (nothing for API
|
|
keys).
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: List of entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SpamPolicyEntry"
|
|
example:
|
|
- object: john.doe@example.org
|
|
value: "*@partner.example.com"
|
|
prefid: 12
|
|
- object: example.org
|
|
value: newsletter@example.net
|
|
prefid: 4
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/policy_bl_mailbox/{mailbox}:
|
|
get:
|
|
tags:
|
|
- Mailbox antispam policies
|
|
summary: Get the deny list of a mailbox
|
|
operationId: getMailboxPolicyDenyList
|
|
description: >-
|
|
Like `get/policy_wl_mailbox/{mailbox}` for the deny list.
|
|
parameters:
|
|
- name: mailbox
|
|
in: path
|
|
required: true
|
|
description: Mailbox address
|
|
schema:
|
|
type: string
|
|
example: john.doe@example.org
|
|
responses:
|
|
"200":
|
|
description: List of entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/SpamPolicyEntry"
|
|
example:
|
|
- object: john.doe@example.org
|
|
value: "*@spam.example.com"
|
|
prefid: 13
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/delete/mailbox-policy:
|
|
post:
|
|
tags:
|
|
- Mailbox antispam policies
|
|
summary: Delete allow or deny list entries of mailboxes
|
|
operationId: deleteMailboxPolicy
|
|
description: >-
|
|
Deletes allow or deny list entries of mailboxes by their `prefid`.
|
|
Needs the user ACL `spam_policy` and access to the mailbox of the entry
|
|
(entries of a domain are refused, use `delete/domain-policy`). Messages
|
|
per ID: `items_deleted` or `access_denied`.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: prefid values
|
|
items:
|
|
type: integer
|
|
example:
|
|
- 13
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/add/rsetting:
|
|
post:
|
|
summary: Add Rspamd settings rule
|
|
description: >-
|
|
Adds a rule to the Rspamd settings map (admins only, an API key may).
|
|
`content` is the body of an Rspamd settings entry (`priority`, `rcpt`,
|
|
`from`, `authenticated`, `apply` ...); active rules are handed to
|
|
Rspamd as `additional_settings_<id>`. The presets of
|
|
`GET /api/v1/get/presets/rspamd` are examples.
|
|
|
|
|
|
Messages: `settings_map_added`; `map_content_empty` (danger) when
|
|
`content` is empty; `access_denied` for non-admins. `desc` is required
|
|
by the database: without it the insert fails and the answer is empty.
|
|
operationId: addRspamdSetting
|
|
tags:
|
|
- Rspamd
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/RspamdSettingAttributes"
|
|
example:
|
|
desc: Disable all but DKIM and rate limit for authenticated users
|
|
content: |-
|
|
priority = 10;
|
|
authenticated = yes;
|
|
apply "default" {
|
|
symbols_enabled = ["DKIM_SIGNED", "RATELIMITED", "RATELIMIT_UPDATE", "RATELIMIT_CHECK"];
|
|
}
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/rsetting/{id}:
|
|
get:
|
|
summary: Get Rspamd settings rules
|
|
description: >-
|
|
Returns one rule of the Rspamd settings map, or all rules with `all`
|
|
(a list of the same objects). Admins only (an API key may); other
|
|
callers, unknown IDs and an empty map get `{}`.
|
|
operationId: getRspamdSettings
|
|
tags:
|
|
- Rspamd
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: "`all` or the ID of a rule"
|
|
schema:
|
|
type: string
|
|
example: all
|
|
responses:
|
|
"200":
|
|
description: The rule, or the list of rules for `all`
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/RspamdSetting"
|
|
- $ref: "#/components/schemas/RspamdSetting"
|
|
example:
|
|
- id: 1
|
|
desc: Disable Rspamd for example.org
|
|
content: |-
|
|
priority = 10;
|
|
rcpt = "/.*@example\.org$/";
|
|
from = "/.*/";
|
|
apply "default" {
|
|
MAILCOW_WHITE = -9999.0;
|
|
}
|
|
symbols [
|
|
"MAILCOW_WHITE"
|
|
]
|
|
active: 1
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/rsetting:
|
|
post:
|
|
summary: Edit Rspamd settings rules
|
|
description: >-
|
|
Changes rules of the Rspamd settings map (admins only, an API key may).
|
|
Only the attributes that are sent change; an empty `desc` or `content`
|
|
keeps the old value. `content` is trimmed.
|
|
|
|
|
|
Messages: `object_modified` (with all requested IDs) for every changed
|
|
rule, `settings_map_invalid` (danger) for an unknown ID,
|
|
`access_denied` for non-admins.
|
|
operationId: editRspamdSetting
|
|
tags:
|
|
- Rspamd
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: ID or list of IDs of the rules
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
attr:
|
|
type: object
|
|
properties:
|
|
desc:
|
|
type: string
|
|
description: Short description (empty = keep)
|
|
content:
|
|
type: string
|
|
description: Rule content (empty = keep)
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = the rule is handed to Rspamd, 0 = inactive (not sent = keep)
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- 1
|
|
attr:
|
|
desc: Disable Rspamd for example.org
|
|
active: "0"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/rsetting:
|
|
post:
|
|
summary: Delete Rspamd settings rules
|
|
description: >-
|
|
Deletes rules of the Rspamd settings map (admins only, an API key may).
|
|
Answers `settings_map_removed` for every ID, also for IDs that do not
|
|
exist; `access_denied` for non-admins.
|
|
operationId: deleteRspamdSettings
|
|
tags:
|
|
- Rspamd
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
description: IDs of the rules (a single ID works too)
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
type: [integer, string]
|
|
- type: [integer, string]
|
|
example:
|
|
- 1
|
|
- 2
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/rspamd-map:
|
|
post:
|
|
summary: Edit Rspamd global regex maps
|
|
description: >-
|
|
Replaces the content of global Rspamd regex maps (Configuration >
|
|
Global filters in the UI; admins only, an API key may). Each line is a
|
|
regular expression like `/^spam@example\.org$/i`, lines starting with
|
|
`#` are comments. The UI checks the expressions before it saves, the
|
|
API does not. Every map takes about a second (the file is touched
|
|
again for Rspamd to reload it).
|
|
|
|
|
|
Messages: `object_modified` per map, `global_map_invalid` (danger) for
|
|
an unknown map name, `global_map_write_error` (danger) when the file
|
|
cannot be written, `access_denied` for non-admins. A known map whose
|
|
file does not exist is not written but still answered with
|
|
`object_modified`.
|
|
operationId: editRspamdMap
|
|
tags:
|
|
- Rspamd
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: File name or list of file names of the maps; all of them get the same content
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/RspamdRegexMap"
|
|
- $ref: "#/components/schemas/RspamdRegexMap"
|
|
attr:
|
|
type: object
|
|
properties:
|
|
rspamd_map_data:
|
|
type: string
|
|
description: New content of the map (trimmed, replaces the whole file)
|
|
required:
|
|
- rspamd_map_data
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- global_smtp_from_blacklist.map
|
|
attr:
|
|
rspamd_map_data: |-
|
|
# Envelope senders to reject
|
|
/^spammer@example\.com$/i
|
|
/@spam\.example\.net$/i
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/rspamd/actions:
|
|
get:
|
|
summary: Get Rspamd action statistics
|
|
description: >-
|
|
Returns how many messages Rspamd handled with each action (from
|
|
Rspamd's `/stat`), as `[action, count]` pairs. Greylisted
|
|
messages are counted as `soft reject`. Admins only (an API key may);
|
|
other callers, or an Rspamd that does not answer, get `{}`.
|
|
operationId: getRspamdActions
|
|
tags:
|
|
- Rspamd
|
|
responses:
|
|
"200":
|
|
description: List of `[action, count]` pairs
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: array
|
|
prefixItems:
|
|
- type: string
|
|
description: Action, e.g. `reject`, `soft reject`, `rewrite subject`, `add header`, `no action`
|
|
- type: integer
|
|
description: Number of messages
|
|
minItems: 2
|
|
maxItems: 2
|
|
example:
|
|
- - reject
|
|
- 38
|
|
- - soft reject
|
|
- 1
|
|
- - rewrite subject
|
|
- 0
|
|
- - add header
|
|
- 6
|
|
- - no action
|
|
- 255
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/presets/{kind}:
|
|
get:
|
|
summary: Get Rspamd or Sieve presets
|
|
description: >-
|
|
Returns the example presets the UI offers: `rspamd` for Rspamd settings
|
|
rules (see `POST /api/v1/add/rsetting`), `sieve` for Sieve filters.
|
|
`headline` is translated into the language of the session. Admins and
|
|
domain admins (an API key may); other callers get `{}`.
|
|
operationId: getPresets
|
|
tags:
|
|
- Rspamd
|
|
- Global filters
|
|
parameters:
|
|
- name: kind
|
|
in: path
|
|
required: true
|
|
description: Kind of presets
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- rspamd
|
|
- sieve
|
|
example: rspamd
|
|
responses:
|
|
"200":
|
|
description: List of presets
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Preset"
|
|
example:
|
|
- name: preset_1
|
|
headline: Disable all but DKIM and rate limit for authenticated users
|
|
content: |-
|
|
priority = 10;
|
|
authenticated = yes;
|
|
apply "default" {
|
|
symbols_enabled = ["BCC", "DKIM_SIGNED", "RATELIMITED", "RATELIMIT_UPDATE", "RATELIMIT_CHECK", "DYN_RL_CHECK", "HISTORY_SAVE", "MILTER_HEADERS", "ARC_SIGNED"];
|
|
}
|
|
- name: preset_4
|
|
headline: Disable Rspamd for a domain
|
|
content: |-
|
|
priority = 10;
|
|
rcpt = "/.*@example.org$/";
|
|
from = "/.*/";
|
|
apply "default" {
|
|
MAILCOW_WHITE = -9999.0;
|
|
}
|
|
symbols [
|
|
"MAILCOW_WHITE"
|
|
]
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/add/global-filter:
|
|
post:
|
|
summary: Save a global Sieve filter
|
|
description: >-
|
|
Replaces the global Sieve prefilter (runs before the filters of the
|
|
mailboxes) or postfilter (runs after them) and restarts Dovecot.
|
|
Admins only (an API key may). The script is parsed first and not
|
|
saved when it has errors.
|
|
|
|
|
|
Messages: `dovecot_restart_success`, or `dovecot_restart_failed`
|
|
(warning), then `global_filter_written`; `sieve_error` (danger) with
|
|
the parser error; `invalid_filter_type` (danger);
|
|
`global_filter_write_error` (danger); `access_denied` for non-admins.
|
|
operationId: addGlobalFilter
|
|
tags:
|
|
- Global filters
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
filter_type:
|
|
type: string
|
|
enum:
|
|
- prefilter
|
|
- postfilter
|
|
description: Which global filter to replace
|
|
script_data:
|
|
type: string
|
|
description: The Sieve script (CRLF and CR line ends become LF)
|
|
required:
|
|
- filter_type
|
|
- script_data
|
|
example:
|
|
filter_type: postfilter
|
|
script_data: |-
|
|
require "fileinto";
|
|
if header :contains "X-Spam-Flag" "YES" {
|
|
fileinto "Junk";
|
|
}
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/global_filters/all:
|
|
get:
|
|
summary: Get the global Sieve filters
|
|
description: >-
|
|
Returns the global Sieve prefilter and postfilter. Admins only (an API
|
|
key may); other callers get `{}`.
|
|
operationId: getGlobalFilters
|
|
tags:
|
|
- Global filters
|
|
responses:
|
|
"200":
|
|
description: Both scripts
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/GlobalFilters"
|
|
example:
|
|
prefilter: |
|
|
# global_sieve_before script
|
|
# global_sieve_before -> user sieve_before (mailcow UI) -> user sieve_after (mailcow UI) -> global_sieve_after
|
|
postfilter: |-
|
|
# global_sieve_after script
|
|
require "fileinto";
|
|
|
|
if header :contains "X-Spam-Flag" "YES" {
|
|
fileinto "Junk";
|
|
}
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/global_filters/{filter_type}:
|
|
get:
|
|
summary: Get one global Sieve filter
|
|
description: >-
|
|
Returns the global Sieve prefilter or postfilter as a JSON string.
|
|
Admins only (an API key may); other callers and an empty script get
|
|
`{}`.
|
|
operationId: getGlobalFilter
|
|
tags:
|
|
- Global filters
|
|
parameters:
|
|
- name: filter_type
|
|
in: path
|
|
required: true
|
|
description: Which global filter
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- prefilter
|
|
- postfilter
|
|
example: prefilter
|
|
responses:
|
|
"200":
|
|
description: The Sieve script
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: string
|
|
example: |
|
|
# global_sieve_before script
|
|
# global_sieve_before -> user sieve_before (mailcow UI) -> user sieve_after (mailcow UI) -> global_sieve_after
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/quota_notification:
|
|
post:
|
|
summary: Edit quota notification settings
|
|
description: >-
|
|
Saves sender, subject and template of the mails users get when their
|
|
mailbox crosses 80 % and 95 % of its quota (admins only, an API key
|
|
may). `items` is ignored. Every call writes all three values: one that
|
|
is not sent becomes empty. The current values cannot be read through
|
|
the API.
|
|
|
|
|
|
Messages: `saved_settings`; `redis_error` (danger); `access_denied`
|
|
for non-admins.
|
|
operationId: editQuotaNotification
|
|
tags:
|
|
- Quota notifications
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: Ignored
|
|
attr:
|
|
type: object
|
|
properties:
|
|
sender:
|
|
type: string
|
|
description: Sender address (control characters and non-ASCII bytes are removed; an invalid address becomes empty)
|
|
subject:
|
|
type: string
|
|
description: Subject
|
|
html_tmpl:
|
|
type: string
|
|
description: HTML template (empty = the default template)
|
|
required:
|
|
- attr
|
|
example:
|
|
items:
|
|
- quota_notification
|
|
attr:
|
|
sender: quota-warning@example.org
|
|
subject: Quota warning
|
|
html_tmpl: ""
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/quota_notification_bcc:
|
|
post:
|
|
summary: Edit quota notification BCC of a domain
|
|
description: >-
|
|
Sets the addresses that get a copy of every quota warning of a domain
|
|
(the subject gets the username appended). Admins and domain admins of
|
|
the domain (an API key may; the domain or alias domain must exist).
|
|
`items` is ignored. The list replaces the old one; the current list
|
|
cannot be read through the API.
|
|
|
|
|
|
Messages: `saved_settings`; `goto_invalid` (danger) for an invalid
|
|
address, which is left out while the others are saved; `redis_error`
|
|
(danger); `access_denied` for an unknown or foreign domain.
|
|
operationId: editQuotaNotificationBcc
|
|
tags:
|
|
- Quota notifications
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: Ignored
|
|
attr:
|
|
type: object
|
|
properties:
|
|
domain:
|
|
type: string
|
|
description: Domain or alias domain
|
|
bcc_rcpt:
|
|
type: string
|
|
description: Addresses, separated by space, comma, semicolon or newline
|
|
active:
|
|
type: [boolean, integer, string]
|
|
description: 1 = send the copies; becomes 0 when no valid address is left
|
|
required:
|
|
- domain
|
|
required:
|
|
- attr
|
|
example:
|
|
items:
|
|
- quota_bcc
|
|
attr:
|
|
domain: example.org
|
|
bcc_rcpt: |-
|
|
postmaster@example.org
|
|
helpdesk@example.org
|
|
active: "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/admin/all:
|
|
get:
|
|
summary: Get administrators
|
|
description: >-
|
|
Lists all administrators with their details. Domain administrators are
|
|
not part of this list (see `get/domain-admin/all`). The API key itself
|
|
(account `API`) is no administrator account and is not listed.
|
|
operationId: getAdmins
|
|
tags:
|
|
- Administrators
|
|
responses:
|
|
"200":
|
|
description: The administrators, `{}` if there are none
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Admin"
|
|
example:
|
|
- username: admin
|
|
tfa_active: 1
|
|
tfa_active_int: 1
|
|
active: 1
|
|
active_int: 1
|
|
created: "2026-09-21 10:23:08"
|
|
attributes:
|
|
force_tfa: "0"
|
|
force_pw_update: "0"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/admin/{username}:
|
|
get:
|
|
summary: Get administrator
|
|
description: Details of one administrator.
|
|
operationId: getAdmin
|
|
tags:
|
|
- Administrators
|
|
parameters:
|
|
- name: username
|
|
in: path
|
|
required: true
|
|
description: Username of the administrator
|
|
schema:
|
|
type: string
|
|
example: admin
|
|
responses:
|
|
"200":
|
|
description: The administrator, `{}` if there is no administrator of this name
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Admin"
|
|
example:
|
|
username: admin
|
|
tfa_active: 0
|
|
tfa_active_int: 0
|
|
active: 1
|
|
active_int: 1
|
|
created: "2026-09-21 10:23:08"
|
|
attributes:
|
|
force_tfa: "0"
|
|
force_pw_update: "0"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/add/admin:
|
|
post:
|
|
summary: Create administrator
|
|
description: >-
|
|
Creates an administrator account with full access to mailcow.
|
|
The username is converted to lowercase; it may only contain letters,
|
|
digits, `_`, `.` and `-` and must not be used by another administrator
|
|
or domain administrator. The password must match `password2` and the
|
|
password policy.
|
|
|
|
|
|
Success: `admin_added`. Errors: `username_invalid`, `object_exists`,
|
|
`password_complexity`, `password_mismatch`.
|
|
operationId: addAdmin
|
|
tags:
|
|
- Administrators
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
description: Username (letters, digits, `_`, `.`, `-`; stored in lowercase)
|
|
password:
|
|
type: string
|
|
description: Password, must match the password policy
|
|
password2:
|
|
type: string
|
|
description: The password again
|
|
active:
|
|
type: [integer, string, boolean]
|
|
description: >-
|
|
1 = the account can log in, 0 = disabled. Missing counts as
|
|
0: send `1` for a usable account.
|
|
default: 0
|
|
required:
|
|
- username
|
|
- password
|
|
- password2
|
|
example:
|
|
username: admin2
|
|
password: "Rand0m-Passw0rd!"
|
|
password2: "Rand0m-Passw0rd!"
|
|
active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/admin:
|
|
post:
|
|
summary: Edit administrators
|
|
description: >-
|
|
Changes administrator accounts. Attributes that are not sent keep their
|
|
value, except `force_tfa` and `force_pw_update`, which are set to 0 when
|
|
they are missing. The password is only changed when `password` is not
|
|
empty. Renaming an account moves its two-factor authentication and the
|
|
sync job sources it created to the new name (FIDO2 keys stay with the
|
|
old name).
|
|
|
|
|
|
One message per account. Success: `admin_modified`. Errors:
|
|
`access_denied` (no administrator of this name), `username_invalid`
|
|
(invalid `username_new` or the name of another administrator), warning
|
|
`no_active_admin` (the last active administrator cannot be
|
|
deactivated). A password that does not match `password2` or the policy
|
|
(`password_mismatch`, `password_complexity`) stops the call.
|
|
operationId: editAdmin
|
|
tags:
|
|
- Administrators
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
items:
|
|
description: Username of the administrator, or a list of usernames
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
attr:
|
|
type: object
|
|
properties:
|
|
active:
|
|
type: [integer, string, boolean]
|
|
description: 1 = active, 0 = disabled
|
|
username_new:
|
|
type: string
|
|
description: New username (letters, digits, `_`, `.`, `-`)
|
|
password:
|
|
type: string
|
|
description: New password; empty or missing keeps the password
|
|
password2:
|
|
type: string
|
|
description: The new password again
|
|
force_tfa:
|
|
type: [integer, string, boolean]
|
|
description: 1 = the administrator must set up two-factor authentication at the next login
|
|
default: 0
|
|
force_pw_update:
|
|
type: [integer, string, boolean]
|
|
description: 1 = the administrator must change the password at the next login
|
|
default: 0
|
|
disable_tfa:
|
|
type: [integer, string, boolean]
|
|
description: >-
|
|
Present (with any value) = deactivate the two-factor
|
|
authentication of the account
|
|
required:
|
|
- items
|
|
- attr
|
|
example:
|
|
items:
|
|
- admin2
|
|
attr:
|
|
active: 1
|
|
password: "N3w-Passw0rd!"
|
|
password2: "N3w-Passw0rd!"
|
|
force_pw_update: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/delete/admin:
|
|
post:
|
|
summary: Delete administrators
|
|
description: >-
|
|
Deletes administrator accounts with their two-factor authentication
|
|
and FIDO2 keys; sync job sources they created are released.
|
|
|
|
|
|
One message per account. Success: `admin_removed`. Errors:
|
|
`username_invalid` (no administrator of this name), warning
|
|
`cannot_delete_self` (the account of the current login, never the case
|
|
for an API key).
|
|
operationId: deleteAdmin
|
|
tags:
|
|
- Administrators
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
description: Usernames of the administrators
|
|
items:
|
|
type: string
|
|
example:
|
|
- admin2
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/get/passwordpolicy:
|
|
get:
|
|
summary: Get password policy
|
|
description: >-
|
|
The password policy for mailboxes, administrators and domain
|
|
administrators. Any further path segment except `html` gives the same
|
|
answer.
|
|
operationId: getPasswordPolicy
|
|
tags:
|
|
- Password policy
|
|
responses:
|
|
"200":
|
|
description: The policy
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/PasswordPolicy"
|
|
example:
|
|
length: "8"
|
|
chars: "1"
|
|
special_chars: "0"
|
|
lowerupper: "1"
|
|
numbers: "1"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/get/passwordpolicy/html:
|
|
get:
|
|
summary: Get password policy as HTML
|
|
description: >-
|
|
The password policy as an HTML snippet in the default language, as the
|
|
mailcow UI shows it below password fields.
|
|
operationId: getPasswordPolicyHtml
|
|
tags:
|
|
- Password policy
|
|
responses:
|
|
"200":
|
|
description: The HTML snippet as a JSON string
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: string
|
|
example: <p class="help-block small">- Minimum password length is 8<br>- Must contain at least one alphabetic character<br>- Must contain lowercase and uppercase characters<br>- Must contain at least one number</p>
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
/api/v1/edit/passwordpolicy:
|
|
post:
|
|
summary: Edit password policy
|
|
description: >-
|
|
Changes the password policy; attributes that are not sent keep their
|
|
value. The policy is checked when a password is set, existing passwords
|
|
are not affected. `items` is not used.
|
|
|
|
|
|
Success: `password_policy_saved`.
|
|
operationId: editPasswordPolicy
|
|
tags:
|
|
- Password policy
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
attr:
|
|
type: object
|
|
properties:
|
|
length:
|
|
type: [integer, string]
|
|
description: Minimum length; values below 3 keep the current length
|
|
chars:
|
|
type: [integer, string, boolean]
|
|
description: 1 = at least one letter
|
|
lowerupper:
|
|
type: [integer, string, boolean]
|
|
description: 1 = lowercase and uppercase letters
|
|
special_chars:
|
|
type: [integer, string, boolean]
|
|
description: 1 = at least one character that is no letter or digit
|
|
numbers:
|
|
type: [integer, string, boolean]
|
|
description: 1 = at least one digit
|
|
required:
|
|
- attr
|
|
example:
|
|
attr:
|
|
length: 12
|
|
chars: 1
|
|
lowerupper: 1
|
|
special_chars: 0
|
|
numbers: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/reset-password-notification:
|
|
post:
|
|
summary: Edit password reset e-mail
|
|
description: >-
|
|
Sets sender, subject and templates of the e-mail a mailbox user gets
|
|
to reset a forgotten password (sent to the recovery address of the
|
|
mailbox). All four values are replaced: a missing value is saved as
|
|
empty; without both templates the default templates are used.
|
|
Password reset is only offered while sender and subject are set.
|
|
Subject and templates may use the placeholders `{{username}}`,
|
|
`{{username2}}` (recovery address), `{{date}}`, `{{token_lifetime}}`
|
|
(minutes), `{{hostname}}` and `{{link}}`. `items` is not used.
|
|
|
|
|
|
Success: `saved_settings`.
|
|
operationId: editPasswordResetNotification
|
|
tags:
|
|
- Password policy
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
attr:
|
|
type: object
|
|
properties:
|
|
from:
|
|
type: string
|
|
description: Sender address; an invalid address is saved as empty
|
|
subject:
|
|
type: string
|
|
description: Subject
|
|
text_tmpl:
|
|
type: string
|
|
description: Plain text template
|
|
html_tmpl:
|
|
type: string
|
|
description: HTML template (the text template becomes its alternative part)
|
|
required:
|
|
- attr
|
|
example:
|
|
attr:
|
|
from: noreply@example.org
|
|
subject: Reset your password
|
|
text_tmpl: "Hello {{username}}, open {{link}} within {{token_lifetime}} minutes to set a new password."
|
|
html_tmpl: "<p>Hello {{username}},</p><p><a href=\"{{link}}\">Set a new password</a> within {{token_lifetime}} minutes.</p>"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/app_links:
|
|
post:
|
|
summary: Edit app links
|
|
description: >-
|
|
Replaces the custom links of the "Apps" menu. The links are sent as
|
|
four lists of equal length, one entry per link; if the lengths differ,
|
|
nothing is saved but `app_links` is reported anyway. An empty list
|
|
removes all custom links. The links of mailcow itself (SOGo, ...) are
|
|
set in vars.local.inc.php and are not affected. `items` is not used.
|
|
|
|
|
|
Success: `app_links`. Error: `demo_mode_enabled`.
|
|
operationId: editAppLinks
|
|
tags:
|
|
- UI customization
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
attr:
|
|
type: object
|
|
properties:
|
|
app:
|
|
type: array
|
|
description: Names of the links
|
|
items:
|
|
type: string
|
|
href:
|
|
type: array
|
|
description: URLs shown on the login page and to users without `user_href`
|
|
items:
|
|
type: string
|
|
user_href:
|
|
type: array
|
|
description: >-
|
|
URLs for logged-in accounts, `%u` is replaced with the
|
|
username; empty = `href`
|
|
items:
|
|
type: string
|
|
hide:
|
|
type: array
|
|
description: >-
|
|
Per link: `"0"` or `0` shows it on the login page, any
|
|
other value (also `false`) hides it there
|
|
items:
|
|
type: [string, integer, boolean]
|
|
required:
|
|
- attr
|
|
example:
|
|
attr:
|
|
app:
|
|
- Wiki
|
|
- Webmail (Roundcube)
|
|
href:
|
|
- https://wiki.example.org
|
|
- https://mail.example.org/rc/
|
|
user_href:
|
|
- https://wiki.example.org
|
|
- https://mail.example.org/rc/?_user=%u
|
|
hide:
|
|
- "0"
|
|
- "1"
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/custom_login:
|
|
post:
|
|
summary: Edit login page options
|
|
description: >-
|
|
Sets the options of the login pages. All four options are replaced: a
|
|
missing option counts as 0. `items` is not used.
|
|
|
|
|
|
Success: `custom_login_modified`. Error: `demo_mode_enabled`.
|
|
operationId: editCustomLogin
|
|
tags:
|
|
- UI customization
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
attr:
|
|
type: object
|
|
properties:
|
|
hide_user_quicklink:
|
|
type: [integer, string, boolean]
|
|
description: 1 = hide the link to the user login page
|
|
default: 0
|
|
hide_domainadmin_quicklink:
|
|
type: [integer, string, boolean]
|
|
description: 1 = hide the link to the domain administrator login page
|
|
default: 0
|
|
hide_admin_quicklink:
|
|
type: [integer, string, boolean]
|
|
description: 1 = hide the link to the administrator login page
|
|
default: 0
|
|
force_sso:
|
|
type: [integer, string, boolean]
|
|
description: >-
|
|
1 = with an OIDC identity provider configured, show only
|
|
the Single Sign-On button instead of the mailcow login
|
|
form
|
|
default: 0
|
|
required:
|
|
- attr
|
|
example:
|
|
attr:
|
|
hide_user_quicklink: 0
|
|
hide_domainadmin_quicklink: 1
|
|
hide_admin_quicklink: 1
|
|
force_sso: 0
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/ip_check:
|
|
post:
|
|
summary: Edit IP check
|
|
description: >-
|
|
Opt-in for the IP check of the dashboard, which asks the third party
|
|
services ipv4.mailcow.email and ipv6.mailcow.email for the public
|
|
addresses of the server. `items` is not used.
|
|
|
|
|
|
Success: `ip_check_opt_in_modified`. Error: `demo_mode_enabled`.
|
|
operationId: editIpCheck
|
|
tags:
|
|
- UI customization
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
attr:
|
|
type: object
|
|
properties:
|
|
ip_check_opt_in:
|
|
type: [integer, string, boolean]
|
|
description: 1/true = enabled; anything else or missing = disabled
|
|
default: 0
|
|
required:
|
|
- attr
|
|
example:
|
|
attr:
|
|
ip_check_opt_in: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/ui_texts:
|
|
post:
|
|
summary: Edit UI texts
|
|
description: >-
|
|
Sets the texts of the mailcow UI. All values are replaced: a missing
|
|
value is saved as empty, which means the default for the three names.
|
|
`items` is not used.
|
|
|
|
|
|
Success: `ui_texts`. Error: `demo_mode_enabled`.
|
|
operationId: editUiTexts
|
|
tags:
|
|
- UI customization
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
attr:
|
|
type: object
|
|
properties:
|
|
title_name:
|
|
type: string
|
|
description: Title of the browser window (plain text); empty = "<hostname> - mail UI"
|
|
main_name:
|
|
type: string
|
|
description: Name shown on the start page (plain text); empty = "<hostname> - mail UI"
|
|
apps_name:
|
|
type: string
|
|
description: Name of the "Apps" menu (plain text); empty = "Apps"
|
|
help_text:
|
|
type: string
|
|
description: Help text below the login form (HTML)
|
|
ui_footer:
|
|
type: string
|
|
description: Footer of every page (HTML)
|
|
ui_announcement_text:
|
|
type: string
|
|
description: Announcement for all logged-in accounts and on the login page (HTML)
|
|
ui_announcement_type:
|
|
type: string
|
|
enum:
|
|
- info
|
|
- warning
|
|
- danger
|
|
description: Style of the announcement; other values are saved as empty
|
|
ui_announcement_active:
|
|
type: [integer, string, boolean]
|
|
description: Not empty and not 0 = show the announcement
|
|
default: 0
|
|
required:
|
|
- attr
|
|
example:
|
|
attr:
|
|
title_name: Example Mail
|
|
main_name: Example Mail
|
|
apps_name: Apps
|
|
help_text: "Questions? Write to <a href=\"mailto:support@example.org\">support@example.org</a>."
|
|
ui_footer: "<a href=\"https://example.org/imprint\">Imprint</a>"
|
|
ui_announcement_text: Maintenance on Saturday from 8 to 10 am.
|
|
ui_announcement_type: warning
|
|
ui_announcement_active: 1
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
/api/v1/edit/ui_theme:
|
|
post:
|
|
summary: Edit UI theme
|
|
description: >-
|
|
Selects the theme of the mailcow UI. Themes are folders
|
|
`data/web/css/themes/<name>/` with a `theme.css`. `items` is not used.
|
|
|
|
|
|
Success: `ui_theme_modified`. Errors: `ui_theme_invalid` (no theme of
|
|
this name), `demo_mode_enabled`.
|
|
operationId: editUiTheme
|
|
tags:
|
|
- UI customization
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
attr:
|
|
type: object
|
|
properties:
|
|
ui_theme:
|
|
description: >-
|
|
Folder name of the theme; empty or missing = the default
|
|
theme. A list counts with its first entry.
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
required:
|
|
- attr
|
|
example:
|
|
attr:
|
|
ui_theme: servercow
|
|
responses:
|
|
"200":
|
|
$ref: "#/components/responses/WriteResult"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"403":
|
|
$ref: "#/components/responses/Forbidden"
|
|
tags:
|
|
- name: Domains
|
|
description: >-
|
|
Domains, alias domains, domain templates, MTA-STS policies and
|
|
domain-wide footers
|
|
- name: Domain antispam policies
|
|
description: Sender allow lists (whitelists) and deny lists (blacklists) of domains
|
|
- name: Mailboxes
|
|
description: Mailboxes, their templates, tags, ACLs and logins
|
|
- name: Aliases
|
|
description: You can manage aliases
|
|
- name: Sync jobs
|
|
description: Using Syncjobs you can sync your mails with other email servers
|
|
- name: Logs
|
|
description: Logs of the mailcow containers and the UI
|
|
- name: Queue Manager
|
|
description: Manage the postfix mail queue
|
|
- name: Quarantine
|
|
description: Check what emails went to quarantine
|
|
- name: Fail2Ban
|
|
description: Manage the Netfilter fail2ban options
|
|
- name: DKIM
|
|
description: Generate, import, copy and delete DKIM keys
|
|
- name: Domain admin
|
|
description: Domain administrators, their domains and ACLs
|
|
- name: Single Sign-On
|
|
description: Login tokens for domain administrators
|
|
- name: Address Rewriting
|
|
description: BCC maps and recipient maps
|
|
- name: Outgoing TLS Policy Map Overrides
|
|
description: TLS policies for outgoing connections to single destinations
|
|
- name: oAuth Clients
|
|
description: Clients that use mailcow as OAuth2 server
|
|
- name: API Keys
|
|
description: API keys; service keys from mailcow.conf are read-only
|
|
- name: Groups
|
|
description: Mailbox groups (distribution lists, send-as rights, templates)
|
|
- name: Routing
|
|
description: Sender-dependent transports (relay hosts) and transport maps for outgoing mail
|
|
- name: Resources
|
|
description: Bookable resources (rooms, equipment, groups) for SOGo
|
|
- name: App Passwords
|
|
description: Separate passwords of a mailbox for single clients and protocols
|
|
- name: Status
|
|
description: Containers, mail storage, host and version
|
|
- name: Ratelimits
|
|
description: Edit domain ratelimits
|
|
- name: Cross-Origin Resource Sharing (CORS)
|
|
description: Origins and methods that may call the API from a browser
|
|
- name: Identity Provider
|
|
description: >-
|
|
External Identity Provider (Keycloak, OpenID Connect, LDAP): settings,
|
|
identity sync and links of mailboxes
|
|
- name: Mailbox user settings
|
|
description: >-
|
|
Settings a mailbox user changes on its own page (with the matching user
|
|
ACL): time-limited aliases, spam score, TLS policy, tagged mail,
|
|
Pushover. API keys can change them for any mailbox and must name the
|
|
mailbox; a mailbox user only for its own.
|
|
- name: Mailbox filters
|
|
description: Sieve filters of mailboxes, managed by admins and domain admins
|
|
- name: Mailbox antispam policies
|
|
description: Sender allow and deny lists of mailboxes
|
|
- name: Forwarding Hosts
|
|
description: >-
|
|
Hosts whose incoming mail is accepted unconditionally, e.g. servers that
|
|
forward mail to mailcow
|
|
- name: Rspamd
|
|
description: Rspamd settings rules, global regex maps, presets and statistics
|
|
- name: Global filters
|
|
description: Global Sieve filters that run before and after the filters of the mailboxes, Sieve presets
|
|
- name: Quota notifications
|
|
description: Mails to users whose mailbox is nearly full
|
|
- name: Administrators
|
|
description: Administrator accounts
|
|
- name: Password policy
|
|
description: Password rules and the password reset e-mail
|
|
- name: UI customization
|
|
description: Texts, links, login page and theme of the mailcow UI
|