The web administration supports for now the CRUD operations on the domains, the users, their mailboxes and their quotas, managing mail repositories, performing cassandra migrations, and much more, as described in the following sections.
WARNING: This API allow authentication only via the use of JWT. If not configured with JWT, an administrator should ensure an attacker can not use this API.
By the way, some endpoints are not filtered by authentication. Those endpoints are not related to data stored in James, for example: Swagger documentation & James health checks.
Please also note webadmin is only enabled with Guice. You can not use it when using James with Spring, as the required injections are not implemented.
In case of any error, the system will return an error message which is json format like this:
{
statusCode: <error_code>,
type: <error_type>,
message: <the_error_message>
cause: <the_detail_message_from_throwable>
}
Also be aware that, in case things go wrong, all endpoints might return a 500 internal error (with a JSON body formatted as exposed above). To avoid information duplication, this is ommited on endpoint specific documentation.
Finally, please note that in case of a malformed URL the 400 bad request response will contain an HTML body.
This endpoint is simple for now and is just returning the http status code corresponding to the state of checks (see below). The user has to check in the logs in order to have more information about failing checks.
curl -XGET http://ip:port/healthcheck
Will return a list of healthChecks execution result, with an aggregated result:
{
"status": "healthy",
"checks": [
{
"componentName": "Cassandra backend",
"escapedComponentName": "Cassandra%20backend",
"status": "healthy"
"cause": null
}
]
}
status field can be:
Supported health checks include:
Cassandra backend: Cassandra storage. Included in Cassandra Guice based products.
OpenSearch Backend: OpenSearch storage. Included in Cassandra Guice based products.
EventDeadLettersHealthCheck: Included in all Guice products.
Guice application lifecycle: included in all Guice products.
JPA Backend: JPA storage. Included in JPA Guice based products.
MailReceptionCheck We rely on a configured user, send an email to him and assert that the email is well received, and can be read within the given configured period. Unhealthy means that the email could not be received before reacing the timeout.
MessageFastViewProjection: included in memory and Cassandra based Guice products.
Health check of the component storing JMAP properties which are fast to retrieve.
Those properties are computed in advance from messages and persisted in order to archive a better performance.
There are some latencies between a source update and its projections updates.
Incoherency problems arise when reads are performed in this time-window.
We piggyback the projection update on missed JMAP read in order to decrease the outdated time window for a given entry.
The health is determined by the ratio of missed projection reads. (lower than 10% causes degraded
)
RabbitMQ backend: RabbitMQ messaging. Included in Distributed Guice based products.
Response codes:
Performs a health check for the given component. The component is referenced by its URL encoded name.
curl -XGET http://ip:port/healthcheck/checks/Cassandra%20backend
Will return the component's name, the component's escaped name, the health status and a cause.
{
"componentName": "Cassandra backend",
"escapedComponentName": "Cassandra%20backend",
"status": "healthy"
"cause": null
}
Response codes:
This endpoint lists all the available health checks.
curl -XGET http://ip:port/healthcheck/checks
Will return the list of all available health checks.
[
{
"componentName": "Cassandra backend",
"escapedComponentName": "Cassandra%20backend"
}
]
Response codes:
curl -XPUT http://ip:port/domains/domainToBeCreated
Resource name domainToBeCreated:
Response codes:
curl -XDELETE http://ip:port/domains/{domainToBeDeleted}
Note: Deletion of an auto-detected domain, default domain or of an auto-detected ip is not supported. We encourage you instead to review your domain list configuration.
Response codes:
curl -XGET http://ip:port/domains/{domainName}
Response codes:
curl -XGET http://ip:port/domains
Possible response:
["domain1", "domain2"]
Response codes:
curl -XGET http://ip:port/domains/destination.domain.tld/aliases
Possible response:
[
{"source": "source1.domain.tld"},
{"source": "source2.domain.tld"}
]
When sending an email to an email address having source1.domain.tld
or source2.domain.tld
as a domain part (example: user@source1.domain.tld
), then
the domain part will be rewritten into destination.domain.tld (so into user@destination.domain.tld
).
Response codes:
To create a domain alias execute the following query:
curl -XPUT http://ip:port/domains/destination.domain.tld/aliases/source.domain.tld
When sending an email to an email address having source.domain.tld
as a domain part (example: user@source.domain.tld
), then
the domain part will be rewritten into destination.domain.tld
(so into user@destination.domain.tld
).
Response codes:
source.domain.tld
or destination.domain.tld
have an invalid syntaxsource, domain
and destination domain
are the samesource.domain.tld
are not part of handled domains.Be aware that no checks to find possible loops that would result of this creation will be performed.
To delete a domain alias execute the following query:
curl -XDELETE http://ip:port/domains/destination.domain.tld/aliases/source.domain.tld
When sending an email to an email address having source.domain.tld
as a domain part (example: user@source.domain.tld
), then
the domain part will be rewritten into destination.domain.tld
(so into user@destination.domain.tld
).
Response codes:
source.domain.tld
or destination.domain.tld have an invalid syntaxsource.domain.tld
are not part of handled domains.curl -XPOST http://ip:port/domains/{domainToBeUsed}?action=deleteData
Would create a task that deletes data of all users of the domain.
More details about endpoints returning a task.
Response codes:
The scheduled task will have the following type DeleteUsersDataOfDomainTask
and the following additionalInformation
:
{
"type": "DeleteUsersDataOfDomainTask",
"domain": "domain.tld",
"successfulUsersCount": 2,
"failedUsersCount": 1,
"failedUsers": ["faileduser@domain.tld"],
"timestamp": "2023-05-22T08:52:47.076261Z"
}
Notes: failedUsers
only lists maximum 100 failed users.
From
headers for a given usercurl -XPUT http://ip:port/users/usernameToBeUsed \
-d '{"password":"passwordToBeUsed"}' \
-H "Content-Type: application/json"
Resource name usernameToBeUsed representing valid users, hence it should match the criteria at User Repositories documentation
Response codes:
Note: If the user exists already, its password cannot be updated using this. If you want to update a user's password, please have a look at Update a user password.
curl -XPUT http://ip:port/users/usernameToBeUsed?force \
-d '{"password":"passwordToBeUsed"}' \
-H "Content-Type: application/json"
Response codes:
This also can be used to create a new user.
curl -XHEAD http://ip:port/users/usernameToBeUsed
Resource name “usernameToBeUsed” represents a valid user, hence it should match the criteria at User Repositories documentation
Response codes:
Same than Create, but a user need to exist.
If the user do not exist, then it will be created.
curl -XDELETE http://ip:port/users/{userToBeDeleted}
Response codes:
curl -XGET http://ip:port/users
The answer looks like:
[{"username":"username@domain-jmapauthentication.tld"},{"username":"username@domain.tld"}]
Response codes:
From
headers for a given usercurl -XGET http://ip:port/users/givenUser/allowedFromHeaders
The answer looks like:
["user@domain.tld","alias@domain.tld"]
Response codes:
curl -XPUT http://ip:port/users/baseUser/authorizedUsers/delegatedUser
Response codes:
Note: Delegation is only available on top of Cassandra products and not implemented yet on top of JPA backends.
curl -XDELETE http://ip:port/users/baseUser/authorizedUsers/delegatedUser
Response codes:
Note: Delegation is only available on top of Cassandra products and not implemented yet on top of JPA backends.
curl -XGET http://ip:port/users/baseUser/authorizedUsers
The answer looks like:
["alice@domain.tld","bob@domain.tld"]
Response codes:
Note: Delegation is only available on top of Cassandra products and not implemented yet on top of JPA backends.
curl -XDELETE http://ip:port/users/baseUser/authorizedUsers
Response codes:
Note: Delegation is only available on top of Cassandra products and not implemented yet on top of JPA backends.
curl -XPOST http://ip:port/users/oldUser/rename/newUser?action=rename
Would migrate account data from oldUser
to newUser
.
More details about endpoints returning a task.
Implemented migration steps are:
ForwardUsernameChangeTaskStep
: creates forward from old user to new user and migrates existing forwardsFilterUsernameChangeTaskStep
: migrates users filtering rulesDelegationUsernameChangeTaskStep
: migrates delegations where the impacted user is either delegatee or delegatorMailboxUsernameChangeTaskStep
: migrates mailboxes belonging to the old user to the account of the new user. It also
migrates user's mailbox subscriptions.ACLUsernameChangeTaskStep
: migrates ACLs on mailboxes the migrated user has access to and updates subscriptions accordingly.QuotaUsernameChangeTaskStep
: migrates quotas user from old user to new user.
Response codes:force
query parameter.The fromStep
query parameter allows skipping previous steps, allowing to resume the username change from a failed step.
The scheduled task will have the following type UsernameChangeTask
and the following additionalInformation
:
{
"type": "UsernameChangeTask",
"oldUser": "jessy.jones@domain.tld",
"newUser": "jessy.smith@domain.tld",
"status": {
"A": "DONE",
"B": "FAILED",
"C": "ABORTED"
},
"fromStep": null,
"timestamp": "2023-02-17T02:54:01.246477Z"
}
Valid status includes:
SKIPPED
: bypassed via fromStep
settingWAITING
: Awaits executionIN_PROGRESS
: Currently executedFAILED
: Error encountered while executing this step. Check the logs.ABORTED
: Won't be executed because of previous step failures.curl -XPOST http://ip:port/users/usernameToBeUsed?action=deleteData
Would create a task that deletes data of the user.
More details about endpoints returning a task.
Implemented deletion steps are:
RecipientRewriteTableUserDeletionTaskStep
: deletes all rewriting rules related to this user.FilterUserDeletionTaskStep
: deletes all filters belonging to the user.DelegationUserDeletionTaskStep
: deletes all delegations from / to the user.MailboxUserDeletionTaskStep
: deletes mailboxes of this user, all ACLs of this user, as well as his subscriptions.WebPushUserDeletionTaskStep
: deletes push data registered for this user.IdentityUserDeletionTaskStep
: deletes identities registered for this user.VacationUserDeletionTaskStep
: deletes vacations registered for this user.Response codes:
The fromStep
query parameter allows skipping previous steps, allowing to resume the user data deletion from a failed step.
The scheduled task will have the following type DeleteUserDataTask
and the following additionalInformation
:
{
"type": "DeleteUserDataTask",
"username": "jessy.jones@domain.tld",
"status": {
"A": "DONE",
"B": "FAILED",
"C": "ABORTED"
},
"fromStep": null,
"timestamp": "2023-02-17T02:54:01.246477Z"
}
Valid status includes:
SKIPPED
: bypassed via fromStep
settingWAITING
: Awaits executionIN_PROGRESS
: Currently executedFAILED
: Error encountered while executing this step. Check the logs.ABORTED
: Won't be executed because of previous step failures.curl -XGET http://ip:port/users/{baseUser}/identities?default=true
API to get the list of identities of a user
The response will look like:
[
{
"name":"identity name 1",
"email":"bob@domain.tld",
"id":"4c039533-75b9-45db-becc-01fb0e747aa8",
"mayDelete":true,
"textSignature":"textSignature 1",
"htmlSignature":"htmlSignature 1",
"sortOrder":1,
"bcc":[
{
"emailerName":"bcc name 1",
"mailAddress":"bcc1@domain.org"
}
],
"replyTo":[
{
"emailerName":"reply name 1",
"mailAddress":"reply1@domain.org"
}
]
}
]
Query parameters:
default=true
Response codes:
API to create a new JMAP user identity
curl -XPOST http://ip:port/users/{username}/identities \
-d '{
"name": "Bob",
"email": "bob@domain.tld",
"mayDelete": true,
"htmlSignature": "a html signature",
"textSignature": "a text signature",
"bcc": [{
"email": "boss2@domain.tld",
"name": "My Boss 2"
}],
"replyTo": [{
"email": "boss@domain.tld",
"name": "My Boss"
}],
"sortOrder": 0
}' \
-H "Content-Type: application/json"
Response codes:
Resource name username
represents a valid user
API to update an exist JMAP user identity
curl -XPUT http://ip:port/users/{username}/identities/{identityId} \
-d '{
"name": "Bob",
"htmlSignature": "a html signature",
"textSignature": "a text signature",
"bcc": [{
"email": "boss2@domain.tld",
"name": "My Boss 2"
}],
"replyTo": [{
"email": "boss@domain.tld",
"name": "My Boss"
}],
"sortOrder": 1
}' \
-H "Content-Type: application/json"
Response codes:
Resource name username
represents a valid user.
Resource name identityId
represents a exist user identity
Several actions can be performed on the server mailboxes.
Request pattern is:
curl -XPOST /mailboxes?action={action1},...
More details about endpoints returning a task.
Response codes:
The kind of task scheduled depends on the action parameter. See below for details.
This task is only available on top of Guice Cassandra products.
curl -XPOST /mailboxes?task=SolveInconsistencies
Will schedule a task for fixing inconsistencies for the mailbox deduplicated object stored in Cassandra.
More details about endpoints returning a task.
The I-KNOW-WHAT-I-M-DOING
header is mandatory (you can read more information about it in the warning section below).
The scheduled task will have the following type solve-mailbox-inconsistencies
and the following additionalInformation
:
{
"type":"solve-mailbox-inconsistencies",
"processedMailboxEntries": 3,
"processedMailboxPathEntries": 3,
"fixedInconsistencies": 2,
"errors": 1,
"conflictingEntries":[{
"mailboxDaoEntry":{
"mailboxPath":"#private:user:mailboxName",
"mailboxId":"464765a0-e4e7-11e4-aba4-710c1de3782b"
}," +
"mailboxPathDaoEntry":{
"mailboxPath":"#private:user:mailboxName2",
"mailboxId":"464765a0-e4e7-11e4-aba4-710c1de3782b"
}
}]
}
Note that conflicting entry inconsistencies will not be fixed and will require to explicitly use ghost mailbox endpoint in order to merge the conflicting mailboxes and prevent any message loss.
WARNING: this task can cancel concurrently running legitimate user operations upon dirty read. As such this task should be run offline.
A dirty read is when data is read between the two writes of the denormalization operations (no isolation).
In order to ensure being offline, stop the traffic on SMTP, JMAP and IMAP ports, for example via re-configuration or firewall rules.
Due to all of those risks, a I-KNOW-WHAT-I-M-DOING
header should be positioned to ALL-SERVICES-ARE-OFFLINE
in order
to prevent accidental calls.
This task is only available on top of Guice Cassandra products.
curl -XPOST /mailboxes?task=RecomputeMailboxCounters
Will recompute counters (unseen & total count) for the mailbox object stored in Cassandra.
Cassandra maintains a per mailbox projection for message count and unseen message count. As with any projection, it can go out of sync, leading to inconsistent results being returned to the client.
More details about endpoints returning a task.
The scheduled task will have the following type recompute-mailbox-counters
and the following additionalInformation
:
{
"type":"recompute-mailbox-counters",
"processedMailboxes": 3,
"failedMailboxes": ["464765a0-e4e7-11e4-aba4-710c1de3782b"]
}
Note that conflicting inconsistencies entries will not be fixed and will require to explicitly use ghost mailbox endpoint in order to merge the conflicting mailboxes and prevent any message loss.
WARNING: this task do not take into account concurrent modifications upon a single mailbox counter recomputation. Rerunning the task will eventually provide the consistent result. As such we advise to run this task offline.
In order to ensure being offline, stop the traffic on SMTP, JMAP and IMAP ports, for example via re-configuration or firewall rules.
trustMessageProjection
query parameter can be set to true
. Content of messageIdTable
(listing messages by their
mailbox context) table will be trusted and not compared against content of imapUidTable
table (listing messages by their
messageId mailbox independent identifier). This will result in a better performance running the
task at the cost of safety in the face of message denormalization inconsistencies.
Defaults to false, which generates additional checks. You can read this ADR to better understand the message projection and how it can become inconsistent.
This action is only available for backends supporting JMAP protocol.
Message fast view projection stores message properties expected to be fast to fetch but are actually expensive to compute, in order for GetMessages operation to be fast to execute for these properties.
These projection items are asynchronously computed on mailbox events.
You can force the full projection recomputation by calling the following endpoint:
curl -XPOST /mailboxes?task=recomputeFastViewProjectionItems
Will schedule a task for recomputing the fast message view projection for all mailboxes.
More details about endpoints returning a task.
An admin can specify the concurrency that should be used when running the task:
messagesPerSecond
rate at which messages should be processed, per second. Defaults to 10.This optional parameter must have a strictly positive integer as a value and be passed as query parameters.
Example:
curl -XPOST /mailboxes?task=recomputeFastViewProjectionItems&messagesPerSecond=20
The scheduled task will have the following type RecomputeAllFastViewProjectionItemsTask
and the following additionalInformation
:
{
"type":"RecomputeAllPreviewsTask",
"processedUserCount": 3,
"processedMessageCount": 3,
"failedUserCount": 2,
"failedMessageCount": 1,
"runningOptions": {
"messagesPerSecond":20
}
}
Response codes:
Email query view is an optional projection to offload common JMAP Email/query
requests used for listing mails on Cassandra
and not on the search index thus improving the overall reliability / performance on this operation.
These projection items are asynchronously computed on mailbox events.
You can populate this projection with the following request:
curl -XPOST /mailboxes?task=populateEmailQueryView
Will schedule a task for recomputing the fast message view projection for all mailboxes.
More details about endpoints returning a task.
An admin can specify the concurrency that should be used when running the task:
messagesPerSecond
rate at which messages should be processed, per second. Defaults to 10.This optional parameter must have a strictly positive integer as a value and be passed as query parameters.
Example:
curl -XPOST /mailboxes?task=populateEmailQueryView&messagesPerSecond=20
The scheduled task will have the following type
PopulateEmailQueryViewTask
and the following
additionalInformation
:
{
"type":"PopulateEmailQueryViewTask",
"processedUserCount": 3,
"processedMessageCount": 3,
"failedUserCount": 2,
"failedMessageCount": 1,
"runningOptions": {
"messagesPerSecond":20
}
}
Response codes:
These tasks are only available on top of Guice Cassandra products or Guice JPA products. They are not part of Memory Guice product.
Be also aware of the limits of this API:
Warning: During the re-indexing, the result of search operations might be altered.
Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events), concurrent changes done during the reIndexing might be ignored.
The following actions can be performed:
curl -XPOST http://ip:port/mailboxes?task=reIndex
Will schedule a task for reIndexing all the mails stored on this James server.
More details about endpoints returning a task.
An admin can specify the concurrency that should be used when running the task:
messagesPerSecond
rate at which messages should be processed per second. Default is 50.This optional parameter must have a strictly positive integer as a value and be passed as query parameter.
An admin can also specify the reindexing mode it wants to use when running the task:
mode
the reindexing mode used. There are 2 modes for the moment:
rebuildAll
allows to rebuild all indexes. It drops indexed entries prior reindexing. This is the default mode.rebuildAllNoCleanup
allows to rebuild all indexes. It skips the cleanup phase thus will not remove evicted entries
upon reindex. However it yields better performances on a known to be empty index.fixOutdated
will check for outdated indexed document and reindex only those.This optional parameter must be passed as query parameter.
It's good to note as well that there is a limitation with the fixOutdated
mode. As we first collect metadata of
stored messages to compare them with the ones in the index, a failed expunged
operation might not be well corrected
(as the message might not exist anymore but still be indexed).
Example:
curl -XPOST http://ip:port/mailboxes?task=reIndex&messagesPerSecond=200&mode=rebuildAll
The scheduled task will have the following type full-reindexing
and the following additionalInformation
:
{
"type":"full-reindexing",
"runningOptions":{
"messagesPerSecond":200,
"mode":"REBUILD_ALL"
},
"successfullyReprocessedMailCount":18,
"failedReprocessedMailCount": 3,
"mailboxFailures": ["12", "23" ],
"messageFailures": [
{
"mailboxId": "1",
"uids": [1, 36]
}]
}
Will schedule a task for reIndexing all the mails which had failed to be indexed from the ReIndexingAllMails task.
Given bbdb69c9-082a-44b0-a85a-6e33e74287a5
being a taskId
generated for a reIndexing tasks
curl -XPOST 'http://ip:port/mailboxes?task=reIndex&reIndexFailedMessagesOf=bbdb69c9-082a-44b0-a85a-6e33e74287a5'
More details about endpoints returning a task.
An admin can specify the concurrency that should be used when running the task:
messagesPerSecond
rate at which messages should be processed per second. Default is 50.This optional parameter must have a strictly positive integer as a value and be passed as query parameter.
An admin can also specify the reindexing mode it wants to use when running the task:
mode
the reindexing mode used. There are 2 modes for the moment:
rebuildAll
allows to rebuild all indexes. It drops indexed entries prior reindexing. This is the default mode.rebuildAllNoCleanup
allows to rebuild all indexes. It skips the cleanup phase thus will not remove evicted entries
upon reindex. However it yields better performances on a known to be empty index.fixOutdated
will check for outdated indexed document and reindex only those.This optional parameter must be passed as query parameter.
It's good to note as well that there is a limitation with the fixOutdated
mode. As we first collect metadata of
stored messages to compare them with the ones in the index, a failed expunged
operation might not be well corrected
(as the message might not exist anymore but still be indexed).
Example:
curl -XPOST http://ip:port/mailboxes?task=reIndex&reIndexFailedMessagesOf=bbdb69c9-082a-44b0-a85a-6e33e74287a5&messagesPerSecond=200&mode=rebuildAll
The scheduled task will have the following type error-recovery-indexation
and the following additionalInformation
:
{
"type":"error-recovery-indexation"
"runningOptions":{
"messagesPerSecond":200,
"mode":"REBUILD_ALL"
},
"successfullyReprocessedMailCount":18,
"failedReprocessedMailCount": 3,
"mailboxFailures": ["12", "23" ],
"messageFailures": [{
"mailboxId": "1",
"uids": [1, 36]
}]
}
Will schedule a task for creating all the missing parent mailboxes in a hierarchical mailbox tree, which is the result of a partially failed rename operation of a child mailbox.
curl -XPOST 'http://ip:port/mailboxes?task=createMissingParents'
More details about endpoints returning a task.
Response codes:
The scheduled task will have the following type createMissingParents
and the following additionalInformation
:
{
"type":"createMissingParents"
"created": ["1", "2" ],
"totalCreated": 2,
"failures": [],
"totalFailure": 0
}
This task is only available on top of Guice Cassandra products or Guice JPA products. It is not part of Memory Guice product.
curl -XPOST http://ip:port/mailboxes/{mailboxId}?task=reIndex
Will schedule a task for reIndexing all the mails in one mailbox.
Note that ‘mailboxId’ path parameter needs to be a (implementation dependent) valid mailboxId.
More details about endpoints returning a task.
An admin can specify the concurrency that should be used when running the task:
messagesPerSecond
rate at which messages should be processed per second. Default is 50.This optional parameter must have a strictly positive integer as a value and be passed as query parameter.
An admin can also specify the reindexing mode it wants to use when running the task:
mode
the reindexing mode used. There are 2 modes for the moment:
rebuildAll
allows to rebuild all indexes. It drops indexed entries prior reindexing. This is the default mode.rebuildAllNoCleanup
allows to rebuild all indexes. It skips the cleanup phase thus will not remove evicted entries
upon reindex. However it yields better performances on a known to be empty index.fixOutdated
will check for outdated indexed document and reindex only those.This optional parameter must be passed as query parameter.
It's good to note as well that there is a limitation with the fixOutdated
mode. As we first collect metadata of
stored messages to compare them with the ones in the index, a failed expunged
operation might not be well corrected
(as the message might not exist anymore but still be indexed).
Example:
curl -XPOST http://ip:port/mailboxes/{mailboxId}?task=reIndex&messagesPerSecond=200&mode=fixOutdated
Response codes:
The scheduled task will have the following type mailbox-reindexing
and the following additionalInformation
:
{
"type":"mailbox-reindexing",
"runningOptions":{
"messagesPerSecond":200,
"mode":"FIX_OUTDATED"
},
"mailboxId":"{mailboxId}",
"successfullyReprocessedMailCount":18,
"failedReprocessedMailCount": 3,
"mailboxFailures": ["12"],
"messageFailures": [
{
"mailboxId": "1",
"uids": [1, 36]
}]
}
Warning: During the re-indexing, the result of search operations might be altered.
Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events), concurrent changes done during the reIndexing might be ignored.
This task is only available on top of Guice Cassandra products or Guice JPA products. It is not part of Memory Guice product.
curl -XPOST http://ip:port/mailboxes/{mailboxId}/uid/{uid}?task=reIndex
Will schedule a task for reIndexing a single email.
Note that ‘mailboxId’ path parameter needs to be a (implementation dependent) valid mailboxId.
More details about endpoints returning a task.
Response codes:
The scheduled task will have the following type message-reindexing
and the following additionalInformation
:
{
"mailboxId":"{mailboxId}",
"uid":18
}
Warning: During the re-indexing, the result of search operations might be altered.
Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
This task is only available on top of Guice Cassandra products or Guice JPA products. It is not part of Memory Guice product.
curl -XPOST http://ip:port/messages/{messageId}?task=reIndex
Will schedule a task for reIndexing a single email in all the mailboxes containing it.
Note that ‘messageId’ path parameter needs to be a (implementation dependent) valid messageId.
More details about endpoints returning a task.
Response codes:
The scheduled task will have the following type messageId-reindexing
and the following additionalInformation
:
{
"messageId":"18"
}
Warning: During the re-indexing, the result of search operations might be altered.
This task is only available on top of Guice Cassandra products.
curl -XPOST /messages?task=SolveInconsistencies
Will schedule a task for fixing message inconsistencies created by the message denormalization process.
Messages are denormalized and stored in separated data tables in Cassandra, so they can be accessed by their unique identifier or mailbox identifier & local mailbox identifier through different protocols.
Failure in the denormalization process will lead to inconsistencies, for example:
BOB receives a message
The denormalization process fails
BOB can read the message via JMAP
BOB cannot read the message via IMAP
BOB marks a message as SEEN
The denormalization process fails
The message is SEEN via JMAP
The message is UNSEEN via IMAP
More details about endpoints returning a task.
An admin can specify the concurrency that should be used when running the task:
messagesPerSecond
rate of messages to be processed per second. Default is 100.This optional parameter must have a strictly positive integer as a value and be passed as query parameter.
An admin can also specify the reindexing mode it wants to use when running the task:
mode
the reindexing mode used. There are 2 modes for the moment:
rebuildAll
allows to rebuild all indexes. It drops indexed entries prior reindexing. This is the default mode.rebuildAllNoCleanup
allows to rebuild all indexes. It skips the cleanup phase thus will not remove evicted entries
upon reindex. However it yields better performances on a known to be empty index.fixOutdated
will check for outdated indexed document and reindex only those.This optional parameter must be passed as query parameter.
It's good to note as well that there is a limitation with the fixOutdated
mode. As we first collect metadata of
stored messages to compare them with the ones in the index, a failed expunged
operation might not be well corrected
(as the message might not exist anymore but still be indexed).
Example:
curl -XPOST /messages?task=SolveInconsistencies&messagesPerSecond=200&mode=rebuildAll
Response codes:
The scheduled task will have the following type solve-message-inconsistencies
and the following additionalInformation
:
{
"type":"solve-message-inconsistencies",
"timestamp":"2007-12-03T10:15:30Z",
"processedImapUidEntries": 2,
"processedMessageIdEntries": 1,
"addedMessageIdEntries": 1,
"updatedMessageIdEntries": 0,
"removedMessageIdEntries": 1,
"runningOptions":{
"messagesPerSecond": 200,
"mode":"REBUILD_ALL"
},
"fixedInconsistencies": [
{
"mailboxId": "551f0580-82fb-11ea-970e-f9c83d4cf8c2",
"messageId": "d2bee791-7e63-11ea-883c-95b84008f979",
"uid": 1
},
{
"mailboxId": "551f0580-82fb-11ea-970e-f9c83d4cf8c2",
"messageId": "d2bee792-7e63-11ea-883c-95b84008f979",
"uid": 2
}
],
"errors": [
{
"mailboxId": "551f0580-82fb-11ea-970e-f9c83d4cf8c2",
"messageId": "ffffffff-7e63-11ea-883c-95b84008f979",
"uid": 3
}
]
}
User actions concurrent to the inconsistency fixing task could result in concurrency issues. New inconsistencies could be created.
However the source of truth will not be impacted, hence rerunning the task will eventually fix all issues.
This task could be run safely online and can be scheduled on a recurring basis outside of peak traffic by an admin to ensure Cassandra message consistency.
curl -XPUT http://ip:port/users/{usernameToBeUsed}/mailboxes/{mailboxNameToBeCreated}
Resource name usernameToBeUsed
should be an existing user
Resource name mailboxNameToBeCreated
should not be empty, nor contain % *
characters, nor starting with #
.
Response codes:
force
query parameter.To create nested mailboxes, for instance a work mailbox inside the INBOX mailbox, people should use the . separator. The sample query is:
curl -XDELETE http://ip:port/users/{usernameToBeUsed}/mailboxes/INBOX.work
curl -XDELETE http://ip:port/users/{usernameToBeUsed}/mailboxes/{mailboxNameToBeDeleted}
Resource name usernameToBeUsed
should be an existing user
Resource name mailboxNameToBeDeleted
should not be empty
Response codes:
force
query parameter.curl -XGET http://ip:port/users/{usernameToBeUsed}/mailboxes/{mailboxNameToBeTested}
Resource name usernameToBeUsed
should be an existing user
Resource name mailboxNameToBeTested
should not be empty
Response codes:
curl -XGET http://ip:port/users/{usernameToBeUsed}/mailboxes
The answer looks like:
[{"mailboxName":"INBOX"},{"mailboxName":"outbox"}]
Resource name usernameToBeUsed
should be an existing user
Response codes:
force
query parameter.curl -XDELETE http://ip:port/users/{usernameToBeUsed}/mailboxes
Resource name usernameToBeUsed
should be an existing user
Response codes:
force
query parameter.curl -XPOST http://ip:port/users/{usernameToBeUsed}/mailboxes?action=export
Resource name usernameToBeUsed
should be an existing user
Response codes:
The scheduled task will have the following type MailboxesExportTask
and the following additionalInformation
:
{
"type":"MailboxesExportTask",
"timestamp":"2007-12-03T10:15:30Z",
"username": "user",
"stage": "STARTING"
}
curl -XPOST http://ip:port/users/{usernameToBeUsed}/mailboxes?task=reIndex
Will schedule a task for reIndexing all the mails in “user@domain.com” mailboxes (encoded above).
More details about endpoints returning a task.
An admin can specify the concurrency that should be used when running the task:
messagesPerSecond
rate at which messages should be processed per second. Default is 50.This optional parameter must have a strictly positive integer as a value and be passed as query parameter.
An admin can also specify the reindexing mode it wants to use when running the task:
mode
the reindexing mode used. There are 2 modes for the moment:
rebuildAll
allows to rebuild all indexes. It drops indexed entries prior reindexing. This is the default mode.rebuildAllNoCleanup
allows to rebuild all indexes. It skips the cleanup phase thus will not remove evicted entries
upon reindex. However it yields better performances on a known to be empty index.fixOutdated
will check for outdated indexed document and reindex only those.This optional parameter must be passed as query parameter.
It's good to note as well that there is a limitation with the fixOutdated
mode. As we first collect metadata of
stored messages to compare them with the ones in the index, a failed expunged
operation might not be well corrected
(as the message might not exist anymore but still be indexed).
Example:
curl -XPOST http://ip:port/users/{usernameToBeUsed}/mailboxes?task=reIndex&messagesPerSecond=200&mode=fixOutdated
Response codes:
The scheduled task will have the following type user-reindexing
and the following additionalInformation
:
{
"type":"user-reindexing",
"runningOptions":{
"messagesPerSecond":200,
"mode":"FIX_OUTDATED"
},
"user":"user@domain.com",
"successfullyReprocessedMailCount":18,
"failedReprocessedMailCount": 3,
"mailboxFailures": ["12", "23" ],
"messageFailures": [
{
"mailboxId": "1",
"uids": [1, 36]
}]
}
Warning: During the re-indexing, the result of search operations might be altered.
Warning: Canceling this task should be considered unsafe as it will leave the currently reIndexed mailbox as partially indexed.
Warning: While we have been trying to reduce the inconsistency window to a maximum (by keeping track of ongoing events), concurrent changes done during the reIndexing might be ignored.
curl -XGET http://ip:port/users/{usernameToBeUsed}/mailboxes/{mailboxName}/messageCount
Will return the total count of messages within the mailbox of that user.
Resource name usernameToBeUsed
should be an existing user.
Resource name mailboxName
should not be empty, nor contain % *
characters, nor starting with #
.
Response codes:
usernameToBeUsed
or mailboxName
does not exit'curl -XGET http://ip:port/users/{usernameToBeUsed}/mailboxes/{mailboxName}/unseenMessageCount
Will return the total count of unseen messages within the mailbox of that user.
Resource name usernameToBeUsed
should be an existing user.
Resource name mailboxName
should not be empty, nor contain % *
characters, nor starting with #
.
Response codes:
usernameToBeUsed
or mailboxName
does not exit'curl -XDELETE http://ip:port/users/{usernameToBeUsed}/mailboxes/{mailboxName}/messages
Will schedule a task for clearing all the mails in mailboxName
mailbox of usernameToBeUsed
.
More details about endpoints returning a task.
Resource name usernameToBeUsed
should be an existing user.
Resource name mailboxName
should not be empty, nor contain % *
characters, nor starting with #
.
Response codes:
username
or mailboxName
does not exitThe scheduled task will have the following type ClearMailboxContentTask
and
the following additionalInformation
:
{
"mailboxName": "mbx1",
"messagesFailCount": 9,
"messagesSuccessCount": 10,
"timestamp": "2007-12-03T10:15:30Z",
"type": "ClearMailboxContentTask",
"username": "bob@domain.tld"
}
curl -XPOST http://ip:port/users/{usernameToBeUsed}/mailboxes?task=subscribeAll
Will schedule a task for subscribing a user to all of its mailboxes.
More details about endpoints returning a task.
Most users are unaware of what an IMAP subscription is, nor how they can manage it. If the subscription list gets out of sync with the mailbox list, it could result in downgraded user experience (see MAILBOX-405). This task allow to reset the subscription list to the mailbox list on a per user basis thus working around the aforementioned issues.
Response codes:
The scheduled task will have the following type SubscribeAllTask
and the following additionalInformation
:
{
"type":"SubscribeAllTask",
"username":"user@domain.com",
"subscribedCount":18,
"unsubscribedCount": 3
}
This action is only available for backends supporting JMAP protocol.
Message fast view projection stores message properties expected to be fast to fetch but are actually expensive to compute, in order for GetMessages operation to be fast to execute for these properties.
These projection items are asynchronously computed on mailbox events.
You can force the full projection recomputation by calling the following endpoint:
curl -XPOST /users/{usernameToBeUsed}/mailboxes?task=recomputeFastViewProjectionItems
Will schedule a task for recomputing the fast message view projection for all mailboxes of usernameToBeUsed
.
More details about endpoints returning a task.
An admin can specify the concurrency that should be used when running the task:
messagesPerSecond
rate at which messages should be processed, per second. Defaults to 10.This optional parameter must have a strictly positive integer as a value and be passed as query parameters.
Example:
curl -XPOST /mailboxes?task=recomputeFastViewProjectionItems&messagesPerSecond=20
The scheduled task will have the following type RecomputeUserFastViewProjectionItemsTask
and the following additionalInformation
:
{
"type":"RecomputeUserFastViewProjectionItemsTask",
"username": "{usernameToBeUsed}",
"processedMessageCount": 3,
"failedMessageCount": 1,
"runningOptions": {
"messagesPerSecond":20
}
}
Response codes:
You can force the reset of the Cassandra filtering projection by calling the following endpoint:
curl -XPOST /mailboxes?task=populateFilteringProjection
Will schedule a task.
More details about endpoints returning a task.
The scheduled task will have the following type
PopulateFilteringProjectionTask
and the following
additionalInformation
:
"type":"RecomputeAllPreviewsTask",
"processedUserCount": 3,
"failedUserCount": 2
}
Response codes:
curl -XGET http://ip:port/quota/users/{usernameToBeUsed}
Resource name usernameToBeUsed
should be an existing user
The answer is the details of the quota of that user.
{
"global": {
"count":252,
"size":242
},
"domain": {
"count":152,
"size":142
},
"user": {
"count":52,
"size":42
},
"computed": {
"count":52,
"size":42
},
"occupation": {
"size":13,
"count":21,
"ratio": {
"size":0.25,
"count":0.5,
"max":0.5
}
}
}
global
entry represent the quota limit allowed on this James server.domain
entry represent the quota limit allowed for the user of that domain.user
entry represent the quota limit allowed for this specific user.computed
entry represent the quota limit applied for this user, resolved from the upper values.occupation
entry represent the occupation of the quota for this user. This includes used count and size as well as occupation ratio (used / limit).Note that quota
object can contain a fixed value, an empty value (null) or an unlimited value (-1):
{"count":52,"size":42}
{"count":null,"size":null}
{"count":52,"size":-1}
Response codes:
curl -XPUT http://ip:port/quota/users/{usernameToBeUsed}
Resource name usernameToBeUsed
should be an existing user
The body can contain a fixed value, an empty value (null) or an unlimited value (-1):
{"count":52,"size":42}
{"count":null,"size":null}
{"count":52,"size":-1}
Response codes:
curl -XGET http://ip:port/quota/users/{usernameToBeUsed}/count
Resource name usernameToBeUsed
should be an existing user
The answer looks like:
52
Response codes:
curl -XPUT http://ip:port/quota/users/{usernameToBeUsed}/count
Resource name usernameToBeUsed
should be an existing user
The body can contain a fixed value or an unlimited value (-1):
52
Response codes:
curl -XDELETE http://ip:port/quota/users/{usernameToBeUsed}/count
Resource name usernameToBeUsed
should be an existing user
Response codes:
curl -XGET http://ip:port/quota/users/{usernameToBeUsed}/size
Resource name usernameToBeUsed
should be an existing user
The answer looks like:
52
Response codes:
curl -XPUT http://ip:port/quota/users/{usernameToBeUsed}/size
Resource name usernameToBeUsed
should be an existing user
The body can contain a fixed value or an unlimited value (-1):
52
Response codes:
curl -XDELETE http://ip:port/quota/users/{usernameToBeUsed}/size
Resource name usernameToBeUsed
should be an existing user
Response codes:
curl -XGET 'http://ip:port/quota/users?minOccupationRatio=0.8&maxOccupationRatio=0.99&limit=100&offset=200&domain=domain.com'
Will return:
[
{
"username":"user@domain.com",
"detail": {
"global": {
"count":252,
"size":242
},
"domain": {
"count":152,
"size":142
},
"user": {
"count":52,
"size":42
},
"computed": {
"count":52,
"size":42
},
"occupation": {
"size":48,
"count":21,
"ratio": {
"size":0.9230,
"count":0.5,
"max":0.9230
}
}
}
},
...
]
Where:
Please note that users are alphabetically ordered on username.
The response is a list of usernames, with attached quota details as defined here.
Response codes:
This task is available on top of Cassandra & JPA products.
curl -XPOST /quota/users?task=RecomputeCurrentQuotas
Will recompute current quotas (count and size) for all users stored in James.
James maintains per quota a projection for current quota count and size. As with any projection, it can go out of sync, leading to inconsistent results being returned to the client.
More details about endpoints returning a task.
An admin can specify the concurrency that should be used when running the task:
usersPerSecond
rate at which users quotas should be reprocessed, per second. Defaults to 1.This optional parameter must have a strictly positive integer as a value and be passed as query parameters.
An admin can select which quota component he wants to recompute:
quotaComponent
component whose quota need to be reprocessed. It could be one of values: MAILBOX, SIEVE, JMAP_UPLOADS.The admin could select several quota components. If he does not select, quotas of all components would be recomputed.
Example:
curl -XPOST /quota/users?task=RecomputeCurrentQuotas&usersPerSecond=20"aComponent=MAILBOX"aComponent=JMAP_UPLOADS
The scheduled task will have the following type recompute-current-quotas
and the following additionalInformation
:
{
"type":"recompute-current-quotas",
"recomputeSingleQuotaComponentResults": [
{
"quotaComponent": "MAILBOX",
"processedIdentifierCount": 3,
"failedIdentifiers": ["#private&bob@localhost"]
},
{
"quotaComponent": "JMAP_UPLOADS",
"processedIdentifierCount": 3,
"failedIdentifiers": ["bob@localhost"]
}
],
"runningOptions": {
"usersPerSecond":20
}
}
WARNING: this task do not take into account concurrent modifications upon a single current quota recomputation. Rerunning the task will eventually provide the consistent result.
curl -XGET http://ip:port/quota/domains/{domainToBeUsed}
Resource name domainToBeUsed
should be an existing domain. For example:
curl -XGET http://ip:port/quota/domains/james.org
The answer will detail the default quota applied to users belonging to that domain:
{
"global": {
"count":252,
"size":null
},
"domain": {
"count":null,
"size":142
},
"computed": {
"count":252,
"size":142
}
}
global
entry represents the quota limit defined on this James server by default.domain
entry represents the quota limit allowed for the user of that domain by default.computed
entry represents the quota limit applied for the users of that domain, by default, resolved from the upper values.Note that quota
object can contain a fixed value, an empty value (null) or an unlimited value (-1):
{"count":52,"size":42}
{"count":null,"size":null}
{"count":52,"size":-1}
Response codes:
curl -XPUT http://ip:port/quota/domains/{domainToBeUsed}
Resource name domainToBeUsed
should be an existing domain.
The body can contain a fixed value, an empty value (null) or an unlimited value (-1):
{"count":52,"size":42}
{"count":null,"size":null}
{"count":52,"size":-1}
Response codes:
curl -XGET http://ip:port/quota/domains/{domainToBeUsed}/count
Resource name domainToBeUsed
should be an existing domain.
The answer looks like:
52
Response codes:
curl -XPUT http://ip:port/quota/domains/{domainToBeUsed}/count
Resource name domainToBeUsed
should be an existing domain.
The body can contain a fixed value or an unlimited value (-1):
52
Response codes:
curl -XDELETE http://ip:port/quota/domains/{domainToBeUsed}/count
Resource name domainToBeUsed
should be an existing domain.
Response codes:
curl -XGET http://ip:port/quota/domains/{domainToBeUsed}/size
Resource name domainToBeUsed
should be an existing domain.
The answer looks like:
52
Response codes:
curl -XPUT http://ip:port/quota/domains/{domainToBeUsed}/size
Resource name domainToBeUsed
should be an existing domain.
The body can contain a fixed value or an unlimited value (-1):
52
Response codes:
curl -XDELETE http://ip:port/quota/domains/{domainToBeUsed}/size
Resource name domainToBeUsed
should be an existing domain.
Response codes:
curl -XGET http://ip:port/quota
The answer is the details of the global quota.
{
"count":252,
"size":242
}
Note that quota
object can contain a fixed value, an empty value (null) or an unlimited value (-1):
{"count":52,"size":42}
{"count":null,"size":null}
{"count":52,"size":-1}
Response codes:
curl -XPUT http://ip:port/quota
The body can contain a fixed value, an empty value (null) or an unlimited value (-1):
{"count":52,"size":42}
{"count":null,"size":null}
{"count":52,"size":-1}
Response codes:
curl -XGET http://ip:port/quota/count
Resource name usernameToBeUsed should be an existing user
The answer looks like:
52
Response codes:
curl -XPUT http://ip:port/quota/count
The body can contain a fixed value or an unlimited value (-1):
52
Response codes:
curl -XDELETE http://ip:port/quota/count
Response codes:
curl -XGET http://ip:port/quota/size
The answer looks like:
52
Response codes:
curl -XPUT http://ip:port/quota/size
The body can contain a fixed value or an unlimited value (-1):
52
Response codes:
curl -XDELETE http://ip:port/quota/size
Response codes:
The DropList, also known as the mail blacklist, is a collection of domains and email addresses that are denied from sending emails within the system.
Owner scopes:
global
: contains entries that are blocked across all domains and addresses within the system.
Entries in the global owner scope apply universally and affect all users and domains.domain
: each domain can have its own droplist, which contains entries specific to that domain.user
: allow to customize personalized droplist of blocked domains and email addresses.The deniedEntityType
query parameter is optional and can take the values domain
or address
.
curl -XGET http://ip:port/droplist/global?deniedEntityType=null|domain|address
curl -XGET http://ip:port/droplist/domain/target.com?deniedEntityType=null|domain|address
curl -XGET http://ip:port/droplist/user/tagret@target.com?deniedEntityType=null|domain|address
The answer looks like:
[ "evil.com", "devil.com", "bad_guy@crime.com", "hacker@murder.org" ]
Response codes:
owner scope
or deniedEntityType
curl -XHEAD http://ip:port/droplist/global/attacker@evil.com
curl -XHEAD http://ip:port/droplist/global/evil.com
curl -XHEAD http://ip:port/droplist/domain/target.com/attacker@evil.com
curl -XHEAD http://ip:port/droplist/domain/target.com/evil.com
curl -XHEAD http://ip:port/droplist/user/target@target.com/attacker@evil.com
curl -XHEAD http://ip:port/droplist/user/target@target.com/evil.com
Response codes:
The denied entity must be a valid email address or domain.
curl -XPUT http://ip:port/droplist/global/attacker@evil.com
curl -XPUT http://ip:port/droplist/global/evil.com
curl -XPUT http://ip:port/droplist/domain/target.com/attacker@evil.com
curl -XPUT http://ip:port/droplist/domain/target.com/evil.com
curl -XPUT http://ip:port/droplist/user/target@target.com/attacker@evil.com
curl -XPUT http://ip:port/droplist/user/target@target.com/evil.com
Response codes:
curl -XDELETE http://ip:port/droplist/global/attacker@evil.com
curl -XDELETE http://ip:port/droplist/global/evil.com
curl -XDELETE http://ip:port/droplist/domain/target.com/attacker@evil.com
curl -XDELETE http://ip:port/droplist/domain/target.com/evil.com
curl -XDELETE http://ip:port/droplist/user/target@target.com/attacker@evil.com
curl -XDELETE http://ip:port/droplist/user/target@target.com/evil.com
Response codes:
Cassandra upgrades implies the creation of a new table. Thus restarting James is needed, as new tables are created on restart.
Once done, we ship code that tries to read from new tables, and if not possible backs up to old tables. You can thus safely run without running additional migrations.
On the fly migration can be enabled. However, one might want to force the migration in a controlled fashion, and update automatically current schema version used (assess in the database old versions is no more used, as the corresponding tables are empty). Note that this process is safe: we ensure the service is not running concurrently on this James instance, that it does not bump version upon partial failures, that race condition in version upgrades will be idempotent, etc…
These schema updates can be triggered by webadmin using the Cassandra backend.
Note that currently the progress can be tracked by logs.
curl -XGET http://ip:port/cassandra/version
Will return:
{"version": 2}
Where the number corresponds to the current schema version of the database you are using.
Response codes:
curl -XGET http://ip:port/cassandra/version/latest
Will return:
{"version": 3}
Where the number corresponds to the latest available schema version of the database you are using. This means you can be migrating to this schema version.
Response codes:
curl -XPOST -H "Content-Type: application/json http://ip:port/cassandra/version/upgrade -d '3'
Will schedule the run of the migrations you need to reach schema version 3.
More details about endpoints returning a task.
Response codes:
taskId
is returned.Note that several calls to this endpoint will be run in a sequential pattern.
If the server restarts during the migration, the migration is silently aborted.
The scheduled task will have the following type cassandra-migration
and the following additionalInformation
:
{"targetVersion":3}
curl -XPOST http://ip:port/cassandra/version/upgrade/latest
Will schedule the run of the migrations you need to reach the latest schema version.
More details about endpoints returning a task.
Response codes:
taskId
is returned.Note that several calls to this endpoint will be run in a sequential pattern.
If the server restarts during the migration, the migration is silently aborted.
The scheduled task will have the following type cassandra-migration
and the following additionalInformation
:
{"toVersion":2}
This is a temporary workaround for the Ghost mailbox bug encountered using the Cassandra backend, as described in MAILBOX-322.
You can use the mailbox merging feature in order to merge the old “ghosted” mailbox with the new one.
curl -XPOST http://ip:port/cassandra/mailbox/merging \
-d '{"mergeOrigin":"{id1}", "mergeDestination":"{id2}"}' \
-H "Content-Type: application/json"
Will scedule a task for :
id1
mailboxid2
mailboxMore details about endpoints returning a task.
Response codes:
The scheduled task will have the following type mailbox-merging
and the following additionalInformation
:
{
"oldMailboxId":"5641376-02ed-47bd-bcc7-76ff6262d92a",
"newMailboxId":"4555159-52ae-895f-ccb7-586a4412fb50",
"totalMessageCount": 1,
"messageMovedCount": 1,
"messageFailedCount": 0
}
You can use webadmin to define address groups.
When a specific email is sent to the group mail address, every group member will receive it.
Note that the group mail address is virtual: it does not correspond to an existing user.
This feature uses Recipients rewrite table and requires the RecipientRewriteTable mailet to be configured.
Note that email addresses are restricted to ASCII character set. Mail addresses not matching this criteria will be rejected.
curl -XGET http://ip:port/address/groups
Will return the groups as a list of JSON Strings representing mail addresses. For instance:
["group1@domain.com", "group2@domain.com"]
Response codes:
curl -XGET http://ip:port/address/groups/group@domain.com
Will return the group members as a list of JSON Strings representing mail addresses. For instance:
["member1@domain.com", "member2@domain.com"]
Response codes:
curl -XPUT http://ip:port/address/groups/group@domain.com/member@domain.com
Will add member@domain.com to group@domain.com, creating the group if needed
Response codes:
curl -XDELETE http://ip:port/address/groups/group@domain.com/member@domain.com
Will remove member@domain.com from group@domain.com, removing the group if group is empty after deletion
Response codes:
You can use webadmin to define address forwards.
When a specific email is sent to the base mail address, every forward destination addresses will receive it.
Please note that the base address can be optionaly part of the forward destination. In that case, the base recipient also receive a copy of the mail. Otherwise he is ommitted.
Forwards can be defined for existing users. It then defers from “groups”.
This feature uses Recipients rewrite table and requires the RecipientRewriteTable mailet to be configured.
Note that email addresses are restricted to ASCII character set. Mail addresses not matching this criteria will be rejected.
curl -XGET http://ip:port/address/forwards
Will return the users having forwards configured as a list of JSON Strings representing mail addresses. For instance:
["user1@domain.com", "user2@domain.com"]
Response codes:
curl -XGET http://ip:port/address/forwards/user@domain.com
Will return the destination addresses of this forward as a list of JSON Strings representing mail addresses. For instance:
[
{"mailAddress":"destination1@domain.com"},
{"mailAddress":"destination2@domain.com"}
]
Response codes:
curl -XPUT http://ip:port/address/forwards/user@domain.com/targets/destination@domain.com
Will add destination@domain.com to user@domain.com, creating the forward if needed
Response codes:
curl -XDELETE http://ip:port/address/forwards/user@domain.com/targets/destination@domain.com
Will remove destination@domain.com from user@domain.com, removing the forward if forward is empty after deletion
Response codes:
You can use webadmin to define aliases for an user.
When a specific email is sent to the alias address, the destination address of the alias will receive it.
Aliases can be defined for existing users.
This feature uses Recipients rewrite table and requires the RecipientRewriteTable mailet to be configured.
Note that email addresses are restricted to ASCII character set. Mail addresses not matching this criteria will be rejected.
curl -XGET http://ip:port/address/aliases
Will return the users having aliases configured as a list of JSON Strings representing mail addresses. For instance:
["user1@domain.com", "user2@domain.com"]
Response codes:
curl -XGET http://ip:port/address/aliases/user@domain.com
Will return the aliases of this user as a list of JSON Strings representing mail addresses. For instance:
[
{"source":"alias1@domain.com"},
{"source":"alias2@domain.com"}
]
Response codes:
curl -XPUT http://ip:port/address/aliases/user@domain.com/sources/alias@domain.com
Will add alias@domain.com to user@domain.com, creating the alias if needed
Response codes:
curl -XDELETE http://ip:port/address/aliases/user@domain.com/sources/alias@domain.com
Will remove alias@domain.com from user@domain.com, removing the alias if needed
Response codes:
You can use webadmin to define domain mappings.
Given a configured source (from) domain and a destination (to) domain, when an email is sent to an address belonging to the source domain, then the domain part of this address is overwritten, the destination domain is then used. A source (from) domain can have many destination (to) domains.
For example: with a source domain james.apache.org
maps to two destination domains james.org
and apache-james.org
, when a mail is sent to admin@james.apache.org
, then it will be routed to admin@james.org
and admin@apache-james.org
This feature uses Recipients rewrite table and requires the RecipientRewriteTable mailet to be configured.
Note that email addresses are restricted to ASCII character set. Mail addresses not matching this criteria will be rejected.
curl -XGET http://ip:port/domainMappings
Will return all configured domain mappings
{
"firstSource.org" : ["firstDestination.com", "secondDestination.net"],
"secondSource.com" : ["thirdDestination.com", "fourthDestination.net"],
}
Response codes:
curl -XGET http://ip:port/domainMappings/sourceDomain.tld
With sourceDomain.tld
as the value passed to fromDomain
resource name, the API will return all destination domains configured to that domain
["firstDestination.com", "secondDestination.com"]
Response codes:
fromDomain
resource name is invalidfromDomain
resource name is not foundcurl -XPUT http://ip:port/domainMappings/sourceDomain.tld
Body:
destination.tld
With sourceDomain.tld
as the value passed to fromDomain
resource name, the API will add a destination domain specified in the body to that domain
Response codes:
fromDomain
resource name is invalidBe aware that no checks to find possible loops that would result of this creation will be performed.
curl -XDELETE http://ip:port/domainMappings/sourceDomain.tld
Body:
destination.tld
With sourceDomain.tld
as the value passed to fromDomain
resource name, the API will remove a destination domain specified in the body mapped to that domain
Response codes:
fromDomain
resource name is invalidYou can use webadmin to create regex mappings.
A regex mapping contains a mapping source and a Java Regular Expression (regex) in String as the mapping value. Everytime, if a mail containing a recipient matched with the mapping source, then that mail will be re-routed to a new recipient address which is re written by the regex.
This feature uses Recipients rewrite table and requires the RecipientRewriteTable API to be configured.
POST /mappings/regex/mappingSource/targets/regex
Where:
mappingSource
is the path parameter represents for the Regex Mapping mapping sourceregex
is the path parameter represents for the Regex Mapping regexThe route will add a regex mapping made from mappingSource
and regex
to RecipientRewriteTable.
Example:
curl -XPOST http://ip:port/mappings/regex/james@domain.tld/targets/james@.*:james-intern@james.org
Response codes:
mappingSource
path parameter.regex
path parameter.Be aware that no checks to find possible loops that would result of this creation will be performed.
DELETE /mappings/regex/{mappingSource}/targets/{regex}
Where:
mappingSource
is the path parameter representing the Regex Mapping mapping sourceregex
is the path parameter representing the Regex Mapping regexThe route will remove the regex mapping made from regex
from the mapping source mappingSource
to RecipientRewriteTable.
Example:
curl -XDELETE http://ip:port/mappings/regex/james@domain.tld/targets/[O_O]:james-intern@james.org
Response codes:
mappingSource
path parameter.regex
path parameter.You can use webadmin to define address mappings.
When a specific email is sent to the base mail address, every destination addresses will receive it.
This feature uses Recipients rewrite table and requires the RecipientRewriteTable mailet to be configured.
Note that email addresses are restricted to ASCII character set. Mail addresses not matching this criteria will be rejected.
Please use address mappings with caution, as it's not a typed address. If you know the type of your address (forward, alias, domain, group, etc), prefer using the corresponding routes to those types.
Here are the following actions available on address mappings:
curl -XGET http://ip:port/mappings
Get all mappings from the Recipients rewrite table Supported mapping types are the following:
Response body:
{
"alias@domain.tld": [
{
"type": "Alias",
"mapping": "user@domain.tld"
},
{
"type": "Group",
"mapping": "group-user@domain.tld"
}
],
"aliasdomain.tld": [
{
"type": "Domain",
"mapping": "realdomain.tld"
}
],
"group@domain.tld": [
{
"type": "Address",
"mapping": "user@domain.tld"
}
]
}
Response code:
curl -XPOST http://ip:port/mappings/address/{mappingSource}/targets/{destinationAddress}
Add an address mapping to the Recipients rewrite table Mapping source is the value of {mappingSource} Mapping destination is the value of {destinationAddress} Type of mapping destination is Address
Response codes:
curl -XDELETE http://ip:port/mappings/address/{mappingSource}/targets/{destinationAddress}
mappingSource
destinationAddress
Response codes:
This endpoint allows receiving all mappings of a corresponding user.
curl -XGET http://ip:port/mappings/user/{userAddress}
Return all mappings of a user where:
userAddress
: is the selected userResponse body:
[
{
"type": "Address",
"mapping": "user123@domain.tld"
},
{
"type": "Alias",
"mapping": "aliasuser123@domain.tld"
},
{
"type": "Group",
"mapping": "group123@domain.tld"
}
]
Response codes:
curl -XPUT http://ip:port/mailRepositories/{encodedPathOfTheRepository}?protocol={someProtocol}
Resource name encodedPathOfTheRepository
should be the resource path of the created mail repository. Example:
curl -XPUT http://ip:port/mailRepositories/mailRepo?protocol=file
Response codes:
curl -XGET http://ip:port/mailRepositories
The answer looks like:
[
{
"repository": "var/mail/error/",
"path": "var%2Fmail%2Ferror%2F"
},
{
"repository": "var/mail/relay-denied/",
"path": "var%2Fmail%2Frelay-denied%2F"
},
{
"repository": "var/mail/spam/",
"path": "var%2Fmail%2Fspam%2F"
},
{
"repository": "var/mail/address-error/",
"path": "var%2Fmail%2Faddress-error%2F"
}
]
You can use id
, the encoded URL of the repository, to access it in later requests.
Response codes:
curl -XGET http://ip:port/mailRepositories/{encodedPathOfTheRepository}
Resource name encodedPathOfTheRepository
should be the resource path of an existing mail repository. Example:
curl -XGET http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F
The answer looks like:
{
"repository": "var/mail/error/",
"path": "mail%2Ferror%2F",
"size": 243
}
Response codes:
curl -XGET http://ip:port/mailRepositories/{encodedPathOfTheRepository}/mails
Resource name encodedPathOfTheRepository
should be the resource path of an existing mail repository. Example:
curl -XGET http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F/mails
The answer will contains all mailKey contained in that repository.
[
"mail-key-1",
"mail-key-2",
"mail-key-3"
]
Note that this can be used to read mail details.
You can pass additional URL parameters to this call in order to limit the output:
Example:
curl -XGET 'http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F/mails?limit=100&offset=500'
Response codes:
curl -XGET http://ip:port/mailRepositories/{encodedPathOfTheRepository}/mails/mailKey
Resource name encodedPathOfTheRepository
should be the resource path of an existing mail repository. Resource name mailKey
should be the key of a mail stored in that repository. Example:
curl -XGET http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F/mails/mail-key-1
If the Accept header in the request is “application/json”, then the response looks like:
{
"name": "mail-key-1",
"sender": "sender@domain.com",
"recipients": ["recipient1@domain.com", "recipient2@domain.com"],
"state": "address-error",
"error": "A small message explaining what happened to that mail...",
"remoteHost": "111.222.333.444",
"remoteAddr": "127.0.0.1",
"lastUpdated": null
}
If the Accept header in the request is “message/rfc822”, then the response will be the eml file itself.
Additional query parameter additionalFields
add the existing information
to the response for the supported values (only work with “application/json” Accept header):
curl -XGET http://ip:port/mailRepositories/file%3A%2F%2Fvar%2Fmail%2Ferror%2F/mails/mail-key-1?additionalFields=attributes,headers,textBody,htmlBody,messageSize,perRecipientsHeaders
Give the following kind of response:
{
"name": "mail-key-1",
"sender": "sender@domain.com",
"recipients": ["recipient1@domain.com", "recipient2@domain.com"],
"state": "address-error",
"error": "A small message explaining what happened to that mail...",
"remoteHost": "111.222.333.444",
"remoteAddr": "127.0.0.1",
"lastUpdated": null,
"attributes": {
"name2": "value2",
"name1": "value1"
},
"perRecipientsHeaders": {
"third@party": {
"headerName1": [
"value1",
"value2"
],
"headerName2": [
"value3",
"value4"
]
}
},
"headers": {
"headerName4": [
"value6",
"value7"
],
"headerName3": [
"value5",
"value8"
]
},
"textBody": "My body!!",
"htmlBody": "My <em>body</em>!!",
"messageSize": 42424242
}
Response codes:
curl -XDELETE http://ip:port/mailRepositories/{encodedPathOfTheRepository}/mails/mailKey
Resource name encodedPathOfTheRepository
should be the resource path of an existing mail repository. Resource name mailKey
should be the key of a mail stored in that repository. Example:
curl -XDELETE http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F/mails/mail-key-1
Response codes:
curl -XDELETE http://ip:port/mailRepositories/{encodedPathOfTheRepository}/mails
Resource name encodedPathOfTheRepository
should be the resource path of an existing mail repository. Example:
curl -XDELETE http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F/mails
More details about endpoints returning a task.
Response codes:
The scheduled task will have the following type clear-mail-repository
and the following additionalInformation
:
{
"mailRepositoryPath":"var/mail/error/",
"initialCount": 243,
"remainingCount": 17
}
Sometime, you want to re-process emails stored in a mail repository. For instance, you can make a configuration error, or there can be a James bug that makes processing of some mails fail. Those mail will be stored in a mail repository. Once you solved the problem, you can reprocess them.
To reprocess mails from a repository:
curl -XPATCH http://ip:port/mailRepositories/{encodedPathOfTheRepository}/mails?action=reprocess
Resource name encodedPathOfTheRepository
should be the resource path of an existing mail repository. Example:
For instance:
curl -XPATCH http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F/mails?action=reprocess
Additional query parameters are supported:
queue
allows you to target the mail queue you want to enqueue the mails in. Defaults to spool
.processor
allows you to overwrite the state of the reprocessing mails, and thus select the processors they will start their processing in.
Defaults to the state
field of each processed email.consume
(boolean defaulting to true
) whether the reprocessing should consume the mail in its originating mail repository. Passing
this value to false
allows non destructive reprocessing as you keep a copy of the email in the mail repository and can be valuable
when debugging.limit
(integer value. Optional, default is empty). It enables to limit the count of elements reprocessed.
If unspecified the count of the processed elements is unbounded.maxRetries
Optional integer, defaults to no max retries limit. Only processed emails that had been retried less
than this value. Ignored by default.For instance:
curl -XPATCH 'http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F/mails?action=reprocess&processor=transport&queue=spool'
Note that the action
query parameter is compulsary and can only take value reprocess
.
More details about endpoints returning a task.
Response codes:
The scheduled task will have the following type reprocessing-all
and the following additionalInformation
:
{
"mailRepositoryPath":"var/mail/error/",
"targetQueue":"spool",
"targetProcessor":"transport",
"initialCount": 243,
"remainingCount": 17
}
To reprocess a specific mail from a mail repository:
curl -XPATCH http://ip:port/mailRepositories/{encodedPathOfTheRepository}/mails/mailKey?action=reprocess
Resource name encodedPathOfTheRepository
should be the resource id of an existing mail repository. Resource name mailKey
should be the key of a mail stored in that repository. Example:
For instance:
curl -XPATCH http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F/mails/name1?action=reprocess
Additional query parameters are supported:
queue
allows you to target the mail queue you want to enqueue the mails in. Defaults to spool
.processor
allows you to overwrite the state of the reprocessing mails, and thus select the processors they will start their processing in.
Defaults to the state
field of each processed email.consume
(boolean defaulting to true
) whether the reprocessing should consume the mail in its originating mail repository. Passing
this value to false
allows non destructive reprocessing as you keep a copy of the email in the mail repository and can be valuable
when debugging.While processor
being an optional parameter, not specifying it will result reprocessing the mails in their current state (see documentation about processors and state).
Consequently, only few cases will give a different result, definitively storing them out of the mail repository.
For instance:
curl -XPATCH 'http://ip:port/mailRepositories/var%2Fmail%2Ferror%2F/mails/name1?action=reprocess&processor=transport&queue=spool'
Note that the action
query parameter is compulsary and can only take value reprocess
.
More details about endpoints returning a task.
Response codes:
The scheduled task will have the following type reprocessing-one
and the following additionalInformation
:
{
"mailRepositoryPath":"var/mail/error/",
"targetQueue":"spool",
"targetProcessor":"transport",
"mailKey":"name1"
}
curl -XGET http://ip:port/mailQueues
The answer looks like:
["outgoing","spool"]
Response codes:
curl -XGET http://ip:port/mailQueues/{mailQueueName}
Resource name mailQueueName
is the name of a mail queue, this command will return the details of the given mail queue. For instance:
{"name":"outgoing","size":0}
Response codes:
curl -XGET http://ip:port/mailQueues/{mailQueueName}/mails
Additional URL query parameters:
limit
: Maximum number of mails returned in a single call. Only strictly positive integer values are accepted. Example:curl -XGET http://ip:port/mailQueues/{mailQueueName}/mails?limit=100
The answer looks like:
[{
"name": "Mail1516976156284-8b3093b9-eebf-4c40-9c26-1450f4fcdc3c-to-test.com",
"sender": "user@james.linagora.com",
"recipients": ["someone@test.com"],
"nextDelivery": "1969-12-31T23:59:59.999Z"
}]
Response codes:
curl -XDELETE http://ip:port/mailQueues/{mailQueueName}/mails?sender=senderMailAddress
This request should have exactly one query parameter from the following list:
The mails from the given mail queue matching the query parameter will be deleted.
More details about endpoints returning a task.
Response codes:
The scheduled task will have the following type delete-mails-from-mail-queue
and the following additionalInformation
:
{
"queue":"outgoing",
"initialCount":10,
"remainingCount": 5,
"sender": "sender@james.org",
"name": "Java Developer",
"recipient: "recipient@james.org"
}
curl -XDELETE http://ip:port/mailQueues/{mailQueueName}/mails
All mails from the given mail queue will be deleted.
More details about endpoints returning a task.
Response codes:
The scheduled task will have the following type clear-mail-queue
and the following additionalInformation
:
{
"queue":"outgoing",
"initialCount":10,
"remainingCount": 0
}
curl -XPATCH http://ip:port/mailQueues/{mailQueueName}?delayed=true \
-d '{"delayed": false}' \
-H "Content-Type: application/json"
This request should have the query parameter delayed set to true, in order to indicate only delayed mails are affected.
The payload should set the delayed
field to false inorder to remove the delay. This is the only supported combination,
and it performs a flush.
The mails delayed in the given mail queue will be flushed.
More details about endpoints returning a task.
Response codes:
curl -XPOST 'http://ip:port/mailQueues/{mailQueueName}?action=RepublishNotProcessedMails&olderThan=1d'
This method is specific to the distributed flavor of James, which relies on Cassandra and RabbitMQ for implementing a mail queue.
In case of a RabbitMQ crash resulting in a loss of messages, this task can be launched to repopulate the
mailQueueName
queue in RabbitMQ using the information stored in Cassandra.
The olderThan
parameter is mandatory. It filters the mails to be restored, by taking into account only
the mails older than the given value.
The expected value should be expressed in the following format: Nunit
.
N
should be strictly positive.
unit
could be either in the short form (h
, d
, w
, etc.), or in the long form (day
, week
, month
, etc.).
Examples:
5h
7d
1y
Response codes:
The response body contains the id of the republishing task.
{
"taskId": "a650a66a-5984-431e-bdad-f1baad885856"
}
curl -XPOST 'http://ip:port/mailQueues/{mailQueueName}?action=updateBrowseStart
Will return a task that updates the browse start of the aforementioned mailQueue, regardless of the configuration.
More details about endpoints returning a task.
This is an advanced, potentially expensive operation which requires a good understanding of the RabbitMQMailQueue design (https://github.com/apache/james-project/blob/master/src/adr/0031-distributed-mail-queue.md). Especially, care needs to be taken to call this at most once per slice (not doing so might be expensive).
curl -XPOST /mail-transfer-service
{MIME message}
Will send the following email to the recipients specified in the MIME message.
The {MIME message}
payload must match message/rfc822
format.
DLP (stands for Data Leak Prevention) is supported by James. A DLP matcher will, on incoming emails,
execute regular expressions on email sender, recipients or content, in order to report suspicious emails to
an administrator. WebAdmin can be used to manage these DLP rules on a per senderDomain
basis.
senderDomain
is domain of the sender of incoming emails, for example: apache.org
, james.org
,…
Each senderDomain
correspond to a distinct DLP configuration.
Retrieve a DLP configuration for corresponding senderDomain
, a configuration contains list of configuration items
curl -XGET http://ip:port/dlp/rules/{senderDomain}
Response codes:
senderDomain
or payload in requestThis is an example of returned body. The rules field is a list of rules as described below.
{"rules : [
{
"id": "1",
"expression": "james.org",
"explanation": "Find senders or recipients containing james[any char]org",
"targetsSender": true,
"targetsRecipients": true,
"targetsContent": false
},
{
"id": "2",
"expression": "Find senders containing apache[any char]org",
"explanation": "apache.org",
"targetsSender": true,
"targetsRecipients": false,
"targetsContent": false
}
]}
Store a DLP configuration for corresponding senderDomain
, if any item of DLP configuration in the request is stored before,
it will not be stored anymore
curl -XPUT http://ip:port/dlp/rules/{senderDomain}
The body can contain a list of DLP configuration items formed by those fields:
id
(String) is mandatory, unique identifier of the configuration itemexpression
(String) is mandatory, regular expression to match contents of targetsexplanation
(String) is optional, description of the configuration itemtargetsSender
(boolean) is optional and defaults to false. If true, expression
will be applied to Sender and to From headers of the mailtargetsContent
(boolean) is optional and defaults to false. If true, expression
will be applied to Subject headers and textual bodies (text/plain and text/html) of the mailtargetsRecipients
(boolean) is optional and defaults to false. If true, expression
will be applied to recipients of the mailThis is an example of returned body. The rules field is a list of rules as described below.
{"rules": [
{
"id": "1",
"expression": "james.org",
"explanation": "Find senders or recipients containing james[any char]org",
"targetsSender": true,
"targetsRecipients": true,
"targetsContent": false
},
{
"id": "2",
"expression": "Find senders containing apache[any char]org",
"explanation": "apache.org",
"targetsSender": true,
"targetsRecipients": false,
"targetsContent": false
}
]}
Response codes:
senderDomain
or payload in requestRemove a DLP configuration for corresponding senderDomain
curl -XDELETE http://ip:port/dlp/rules/{senderDomain}
Response codes:
senderDomain
or payload in requestRetrieve a DLP configuration rule for corresponding senderDomain
and a ruleId
curl -XGET http://ip:port/dlp/rules/{senderDomain}/rules/{ruleId}
Response codes:
senderDomain
or payload in requestThis is an example of returned body.
{
"id": "1",
"expression": "james.org",
"explanation": "Find senders or recipients containing james[any char]org",
"targetsSender": true,
"targetsRecipients": true,
"targetsContent": false
}
Some limitations on space Users Sieve script can occupy can be configured by default, and overridden by user.
This endpoints allows to retrieve the global Sieve quota, which will be users default:
curl -XGET http://ip:port/sieve/quota/default
Will return the bytes count allowed by user per default on this server.
102400
Response codes:
This endpoints allows to update the global Sieve quota, which will be users default:
curl -XPUT http://ip:port/sieve/quota/default
With the body being the bytes count allowed by user per default on this server.
102400
Response codes:
This endpoints allows to remove the global Sieve quota. There will no more be users default:
curl -XDELETE http://ip:port/sieve/quota/default
Response codes:
This endpoints allows to retrieve the Sieve quota of a user, which will be this users quota:
curl -XGET http://ip:port/sieve/quota/users/user@domain.com
Will return the bytes count allowed for this user.
102400
Response codes:
This endpoints allows to update the Sieve quota of a user, which will be users default:
curl -XPUT http://ip:port/sieve/quota/users/user@domain.com
With the body being the bytes count allowed for this user on this server.
102400
Response codes:
This endpoints allows to remove the Sieve quota of a user. There will no more quota for this user:
curl -XDELETE http://ip:port/sieve/quota/users/user@domain.com
Response codes:
When deduplication is enabled one needs to explicitly run a garbage collection in order to delete no longer referenced blobs.
To do so:
curl -XDELETE http://ip:port/blobs?scope=unreferenced
More details about endpoints returning a task.
Additional parameters include Bloom filter tuning parameters:
0.01
.1.000.000
.These settings directly impacts the memory footprint of the bloom filter. Simulators can help understand those parameters.
The created task has the following additional information:
{
"referenceSourceCount": 3456,
"blobCount": 5678,
"gcedBlobCount": 1234,
"bloomFilterExpectedBlobCount": 10000,
"bloomFilterAssociatedProbability": 0.01
}
Where:
curl -XDELETE http://ip:port/jmap/uploads?scope=expired
Will schedule a task for clearing expired upload entries.
More details about endpoints returning a task.
Query parameter scope
is required and have the value expired
.
Response codes:
The scheduled task will have the following type UploadRepositoryCleanupTask
and
the following additionalInformation
:
{
"scope": "expired",
"timestamp": "2007-12-03T10:15:30Z",
"type": "UploadRepositoryCleanupTask"
}
The EventBus allows to register ‘group listeners’ that are called in a (potentially) distributed fashion. These group listeners enable the implementation of some advanced mailbox manager feature like indexing, spam reporting, quota management and the like.
Upon exceptions, a bounded number of retries are performed (with exponential backoff delays). If after those retries the listener is still failing, then the event will be stored in the “Event Dead Letter”. This API allows diagnosing issues, as well as performing event replay (not implemented yet).
This endpoint allows discovering the list of mailbox listener groups.
curl -XGET http://ip:port/events/deadLetter/groups
Will return a list of group names that can be further used to interact with the dead letter API:
["org.apache.james.mailbox.events.EventBusTestFixture$GroupA", "org.apache.james.mailbox.events.GenericGroup-abc"]
Response codes:
This endpoint allows listing failed events for a given group:
curl -XGET http://ip:port/events/deadLetter/groups/org.apache.james.mailbox.events.EventBusTestFixture$GroupA
Will return a list of insertionIds:
["6e0dd59d-660e-4d9b-b22f-0354479f47b4", "58a8f59d-660e-4d9b-b22f-0354486322a2"]
Response codes:
curl -XGET http://ip:port/events/deadLetter/groups/org.apache.james.mailbox.events.EventBusTestFixture$GroupA/6e0dd59d-660e-4d9b-b22f-0354479f47b4
Will return the full JSON associated with this event.
Response codes:
insertionId
insertionId
curl -XDELETE http://ip:port/events/deadLetter/groups/org.apache.james.mailbox.events.EventBusTestFixture$GroupA/6e0dd59d-660e-4d9b-b22f-0354479f47b4
Will delete this event.
Response codes:
insertionId
curl -XDELETE http://ip:port/events/deadLetter/groups/org.apache.james.mailbox.events.EventBusTestFixture$GroupA
Will delete all events of this group.
Response codes:
curl -XPOST http://ip:port/events/deadLetter?action=reDeliver
Will create a task that will attempt to redeliver all events stored in “Event Dead Letter”. If successful, redelivered events will then be removed from “Dead Letter”.
More details about endpoints returning a task.
Response codes:
curl -XPOST http://ip:port/events/deadLetter/groups/org.apache.james.mailbox.events.EventBusTestFixture$GroupA
Will create a task that will attempt to redeliver all events of a particular group stored in “Event Dead Letter”. If successful, redelivered events will then be removed from “Dead Letter”.
More details about endpoints returning a task.
Response codes:
curl -XPOST http://ip:port/events/deadLetter/groups/org.apache.james.mailbox.events.EventBusTestFixture$GroupA/6e0dd59d-660e-4d9b-b22f-0354479f47b4?action=reDeliver
Will create a task that will attempt to redeliver a single event of a particular group stored in “Event Dead Letter”. If successful, redelivered event will then be removed from “Dead Letter”.
More details about endpoints returning a task.
Response codes:
Not implemented yet.
The ‘Deleted Message Vault plugin’ allows you to keep users deleted messages during a given retention time. This set of routes allow you to restore users deleted messages or export them in an archive.
To move deleted messages in the vault, you need to specifically configure the DeletedMessageVault PreDeletionHook.
Here are the following actions available on the ‘Deleted Messages Vault’
Note that the ‘Deleted Messages Vault’ feature is supported on top of all available Guice products.
Deleted messages of a specific user can be restored by calling the following endpoint:
curl -XPOST http://ip:port/deletedMessages/users/userToRestore@domain.ext?action=restore
{
"combinator": "and",
"criteria": [
{
"fieldName": "subject",
"operator": "containsIgnoreCase",
"value": "Apache James"
},
{
"fieldName": "deliveryDate",
"operator": "beforeOrEquals",
"value": "2014-10-30T14:12:00Z"
},
{
"fieldName": "deletionDate",
"operator": "afterOrEquals",
"value": "2015-10-20T09:08:00Z"
},
{
"fieldName": "recipients","
"operator": "contains","
"value": "recipient@james.org"
},
{
"fieldName": "hasAttachment",
"operator": "equals",
"value": "false"
},
{
"fieldName": "sender",
"operator": "equals",
"value": "sender@apache.org"
},
{
"fieldName": "originMailboxes",
"operator": "contains",
"value": "02874f7c-d10e-102f-acda-0015176f7922"
}
]
};
The requested Json body is made from a list of criterion objects which have the following structure:
{
"fieldName": "supportedFieldName",
"operator": "supportedOperator",
"value": "A plain string representing the matching value of the corresponding field"
}
Deleted Messages which are matched with the all criterion in the query body will be restored. Here are a list of supported fieldName for the restoring:
subject
field matching. Supports below string operators:
deliveryDate
field matching. Tested value should follow the right date time with zone offset format (ISO-8601) like
2008-09-15T15:53:00+05:00
or 2008-09-15T15:53:00Z
Supports below date time operators:
deliveryDate
before or equals the time of tested value.deliveryDate
after or equals the time of tested valuedeletionDate
field matching. Tested value & Supports operators: similar to deliveryDate
sender
field matching. Tested value should be a valid mail address. Supports mail address operator:
recipients
field matching. Tested value should be a valid mail address. Supports list mail address operator:
hasAttachment
field matching. Tested value could be false
or true
. Supports boolean operator:
originMailboxes
field matching. Tested value is a string serialized of mailbox id. Supports list mailbox id operators:
Messages in the Deleted Messages Vault of a specified user that are matched with Query Json Object in the body will be appended to his ‘Restored-Messages’ mailbox, which will be created if needed.
Note:
action
is required and should have the value restore
to represent the restoring feature. Otherwise, a bad request response will be returnedaction
is case sensitiveand
value, otherwise, requests will be rejected{
"fieldName": "subject",
"operator": "containsIgnoreCase",
"value": "Apache James"
}
matching all deleted messages
:{
"combinator": "and",
"criteria": []
}
limit
query property:{
"combinator": "and",
"limit": 99
"criteria": []
}
Warning: Current web-admin uses US
locale as the default. Therefore, there might be some conflicts when using String containsIgnoreCase
comparators to apply
on the String data of other special locales stored in the Vault. More details at JIRA
Response code:
More details about endpoints returning a task.
The scheduled task will have the following type deleted-messages-restore
and the following additionalInformation
:
{
"successfulRestoreCount": 47,
"errorRestoreCount": 0,
"user": "userToRestore@domain.ext"
}
while:
Retrieve deleted messages matched with requested query from an user then share the content to a targeted mail address (exportTo)
curl -XPOST 'http://ip:port/deletedMessages/users/userExportFrom@domain.ext?action=export&exportTo=userReceiving@domain.ext'
BODY: is the json query has the same structure with Restore Deleted Messages section
Note: Json query passing into the body follows the same rules & restrictions like in Restore Deleted Messages
Response code:
More details about endpoints returning a task.
The scheduled task will have the following type deleted-messages-export
and the following additionalInformation
:
{
"userExportFrom": "userToRestore@domain.ext",
"exportTo": "userReceiving@domain.ext",
"totalExportedMessages": 1432
}
while:
You can overwrite ‘retentionPeriod’ configuration in ‘deletedMessageVault’ configuration file or use the default value of 1 year.
Purge all deleted messages older than the configured ‘retentionPeriod’
curl -XDELETE http://ip:port/deletedMessages?scope=expired
More details about endpoints returning a task.
Response code:
You may want to call this endpoint on a regular basis.
Delete a Deleted Message with MessageId
curl -XDELETE http://ip:port/deletedMessages/users/user@domain.ext/messages/3294a976-ce63-491e-bd52-1b6f465ed7a2
More details about endpoints returning a task.
Response code:
The scheduled task will have the following type deleted-messages-delete
and the following additionalInformation
:
{
"userName": "user@domain.ext",
"messageId": "3294a976-ce63-491e-bd52-1b6f465ed7a2"
}
while:
Some webadmin features schedules tasks. The task management API allow to monitor and manage the execution of the following tasks.
Note that the taskId
used in the following APIs is returned by other WebAdmin APIs scheduling tasks.
curl -XGET http://ip:port/tasks/3294a976-ce63-491e-bd52-1b6f465ed7a2
An Execution Report will be returned:
{
"submitDate": "2017-12-27T15:15:24.805+0700",
"startedDate": "2017-12-27T15:15:24.809+0700",
"completedDate": "2017-12-27T15:15:24.815+0700",
"cancelledDate": null,
"failedDate": null,
"taskId": "3294a976-ce63-491e-bd52-1b6f465ed7a2",
"additionalInformation": {},
"status": "completed",
"type": "type-of-the-task"
}
Note that:
status
can have the value:
waiting
: The task is scheduled but its execution did not start yetinProgress
: The task is currently executedcancelled
: The task had been cancelledcompleted
: The task execution is finished, and this execution is a successfailed
: The task execution is finished, and this execution is a failureadditionalInformation
is a task specific object giving additional information and context about that task. The structure
of this additionalInformation
field is provided along the specific task submission endpoint.
Response codes:
One can await the end of a task, then receive it's final execution report.
That feature is especially usefull for testing purpose but still can serve real-life scenari.
curl -XGET http://ip:port/tasks/3294a976-ce63-491e-bd52-1b6f465ed7a2/await?timeout=duration
An Execution Report will be returned.
timeout
is optional.
By default it is set to 365 days (the maximum value).
The expected value is expressed in the following format: Nunit
.
N
should be strictly positive.
unit
could be either in the short form (s
, m
, h
, etc.), or in the long form (day
, week
, month
, etc.).
Examples:
30s
5m
7d
1y
Response codes:
You can cancel a task by calling:
curl -XDELETE http://ip:port/tasks/3294a976-ce63-491e-bd52-1b6f465ed7a2
Response codes:
A list of all tasks can be retrieved:
curl -XGET http://ip:port/tasks
Will return a list of Execution reports
One can filter the above results by status. For example:
curl -XGET http://ip:port/tasks?status=inProgress
Will return a list of Execution reports that are currently in progress. This list is sorted by reverse submitted date (recent tasks goes first).
Response codes:
Additionnal optional task parameters are supported:
status
one of waiting
, inProgress
, canceledRequested
, completed
, canceled
, failed
. Only
tasks with the given status are returned.type
: only tasks with the given type are returned.submittedBefore
: Date. Returns only tasks submitted before this date.submittedAfter
: Date. Returns only tasks submitted after this date.startedBefore
: Date. Returns only tasks started before this date.startedAfter
: Date. Returns only tasks started after this date.completedBefore
: Date. Returns only tasks completed before this date.completedAfter
: Date. Returns only tasks completed after this date.failedBefore
: Date. Returns only tasks failed before this date.failedAfter
: Date. Returns only tasks faield after this date.offset
: Integer, number of tasks to skip in the response. Useful for paging.limit
: Integer, maximum number of tasks to return in one callExample of date format: 2023-04-15T07:23:27.541254+07:00
and 2023-04-15T07%3A23%3A27.541254%2B07%3A00
once URL encoded.
Many endpoints do generate a task.
Example:
curl -XPOST /endpoint?action={action}
The response to these requests will be the scheduled taskId
:
{"taskId":"5641376-02ed-47bd-bcc7-76ff6262d92a"}
Positionned headers:
Location: /tasks/3294a976-ce63-491e-bd52-1b6f465ed7a2
Response codes:
The additional information returned depends on the scheduled task type and is documented in the endpoint documentation.
Some webadmin features to manage some extra operations on Cassandra tables, like solving inconsistencies on projection tables.
Such inconsistencies can be for example created by a fail of the DAO to add a mapping into 'mappings_sources, while it was successful regarding the
rrt` table.
You can do a series of action on mappings_sources
projection table :
curl -XPOST /cassandra/mappings?action={action}
Will return the taskId corresponding to the related task. Actions supported so far are :
mappings_sources
index and then repopulate it correctly. In the meantime,
listing sources of a mapping might create temporary inconsistencies during the process.For example :
curl -XPOST /cassandra/mappings?action=SolveInconsistencies
More details about endpoints returning a task.
Response codes :
Certificates for TCP based protocols (IMAP, SMTP, POP3, LMTP and ManageSieve) can be updated at runtime, without service interuption and without closing existing connections.
In order to do so:
curl -XPOST http://ip:port/servers?reload-certificate
Optional query parameters:
port
: positive integer (valid port number). Only reload certificates for the specific port.Return code: