Soap
Soap
http://server/service/home/[˜][{username}]/[{folder}]?[{query-params}]
fmt={ics, csv, etc}
charset={Windows-31J, GBK, etc, default is UTF-8}
id={item-id}
imap_id={item-imap-id}
part={mime-part}
query={search-query}
types={types} // when searching
auth={auth-types}
start={time}
end={time}
sync="1"
----------------------
/service/soap/
-------------------------------
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<context xmlns="urn:zimbra">
[<authToken>...</authToken>]
[<csrfToken>...</csrfToken>]
[<authTokenControl voidOnExpired="1"/>]
[<session [id="{returned-from-server-in-last-response}"
[seq="{highest_notification_received}"] [type="admin"]/>]
[<account by="name|id">{account-name-or-id}</account>]
[<change token="{change-id}" [type="mod|new"]/>]
[<targetServer>{proxy-target-server-id}</targetServer>]
[<userAgent name="{client-name}" [version="{client-version}"]/>]
[<via>{request-ip(user-agent)[,...]}</via>
[<format type="{response-format}" />]
</context>
</soap:Header>
<soap:Body>
<FooRequest ... [requestId="{client-generated-id}"]>
</FooRequest>
</soap:Body>
</soap:Envelope>
Notification Reliability
To ensure that the client receives all notifications, the client
must send the highest known notification ID (the highest <notify>
block that the client has received and processed) so that the server
can discard them once it knows they have been received. If the client
is capable of sending multiple overlapping requests, the client is
responsible for making sure that notifications are not applied more
than once even if they are received more than one time.
Race Conditions
To avoid race conditions, the client may specify the highest change ID
that it knows about in the <change> header element. The default behavior
(type="mod") will cause mail.MODIFY_CONFLICT to be thrown if we try to
modify an object that has been touched (flags, tags, folders, etc.) since
the specified change ID. Alternatively, type="new" will throw
mail.MODIFY_CONFLICT if we try to modify an object that has been created
or whose content has been modified since the specified change ID.
In general, the sync client will use type="mod" and the web client will
use type="new".
Proxy Mechanism
Sessions
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
[<soap:Header>
<context xmlns="urn:zimbra">
<session id="{session-id}" [type="admin"]/>
<change token="{change-id}"/>
[<refresh>
<version>{server-version-string}</version>
<mbx s="{bytes-used}" [acct="{remote-mailbox-owner-id}"]/>
<tags>
<-- all tags listed -->
</tags>
<folder id="1">
<folder .../>
<folder ...>
<folder .../>
</folder>
<folder .../>
</folder>
</refresh>]
[<notify seq="sequence-number">
<deleted id="665,1192,452,883"/>
<created>
<tag id="466" name="phlox" u="8" n="13"/>
<folder id="4353" name="a&p" u="2" l="1"/>
<folder id="4356" name="subfolder" u="2" l="4353"/>
<link id="1" name="new-mount-point" l="1" n="6" u="1" f="u"
owner="[email protected]" zid="151bd192-e19a-40be-b8c9-259b21ffac48" rid="2"
oname="user1folder">
<folder id="151bd192-e19a-40be-b8c9-259b21ffac48:260" name="remote-
subfolder" n="43" l="151bd192-e19a-40be-b8c9-259b21ffac48:2"/>
</link>
</created>
<modified>
<tag id="652" u="0" n="2"/>
<m id="553" f="ua"/>
</modified>
</notify>]+
</context>
<soap:/Header>]
<soap:Body>
<FooResponse ... [requestId="{client-generated-id}"]>
</FooResponse>
</soap:Body>
</soap:Envelope>
batch requests:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<context xmlns="urn:zimbra">
<authToken>...</authToken>
[<session [id="{returned-from-server-in-last-response}"]/>]
[<account by="name|id">{account-name-or-id}</account>]
[<change token="{change-id}" [type="mod|new"]/>]
</context>
</soap:Header>
<soap:Body>
<BatchRequest xmlns="urn:zimbra" onerror="continue*|stop">
<FooRequest requestId="1">
</FooRequest>
<BarRequest requestId="2">
</BarRequest>
</BatchRequest>
</soap:Body>
</soap:Envelope>
response:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
[<soap:Header>
<context xmlns="urn:zimbra">
<session id="{session-id}" [type="admin"]>
[<refresh>
<mbx s="{bytes-used}" [acct="{remote-mailbox-owner-id}"]/>
<tags>
<-- all tags listed -->
</tags>
<folder id="1">
<folder .../>
<folder ...>
<folder .../>
</folder>
<folder .../>
</folder>
</refresh>]
[<notify seq="sequence-number">
<deleted ids="665,466,452,883"/>
<created>
<tag id="966" name="phlox" u="8" n="12"/>
<folder id="4353" name="a&p" u="2" l="1"/>
</created>
<modified>
<tag id="654" u="0" n="3"/>
<m id="553" f="ua"/>
</modified>
</notify>]+
</context>
<soap:/Header>]
<soap:Body>
<BatchResponse xmlns="urn:zimbra">
<soap:Fault requestId="1">
</soap:Fault>
<BarResponse ... requestId="2">
</BarResponse>
</BatchResponse>
</soap:Body>
</soap:Envelope>
User Agent
The requests and responses can be specified in XML or JSON format. The
server determines the request format automatically but JSON requests
MUST follow these requirements:
Example:
{
"Header": {
"context": {
"_jsns": "urn:zimbra",
"authToken": {
"_content": "0_3e761bdc...303b"
}
}
},
"Body": {
"FooRequest": {
"_jsns": "urn:zimbra",
"name": "attribute content",
"_content": "element content"
}
}
}
<soap:Envelope ...>
<soap:Header>
<context xmlns="urn:zimbra">
...
<format type='js' />
</context>
</soap:Header>
...
</soap:Envelope>
{
"Header": {
"context": {
...
"format": { "type": "xml" },
"_jsns": "urn:zimbra"
}
},
...
}
In addition, the server removes trailing whitespace and characters below 0x20 from
item names.
-----------------------------
SOAP 1.2
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
</soap:Code>
<soap:Reason><soap:Text>...</soap:Text><soap:Reason>
<soap:Detail>
<Error xmlns="urn:zimbra">
<Code>...</Code>
[<a n="{name}" t="{type}">{value}</a>]* // error information (arguments,
e.g. ID that was bad, or whatever)
</Error>
</soap:Detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>
SOAP 1.1
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<soap:faultcode>soap:Server</soap:faultcode>
<soap:faultstring>Server Error</soap:faultstring>
<soap:detail>
<Error xmlns="urn:zimbra">
<Code>...</Code>
[<a n="{name}" t="{type}">{value}</a>]* // error information (arguments,
e.g. ID that was bad, or whatever)
</Error>
</soap:detail>
</soap:Fault>
</soap:Body>
</soapEnvelope>
-----------------------------
urn:zimbraAccount
<AuthResponse>
<authToken>...</authToken>
[<csrfToken>...</csrfToken>]
<lifetime>{lifetime-in-millseconds}</lifetime>
<session .../>
<refer>{mail-host}</refer>
[<prefs><pref name="{name}" modified="{modified-
time}">{value}</pref>...</prefs>]
[<attrs><attr name="{name}">{value}</attr>...</attrs>]
[<skin>{skin-name}</skin>]
[<trustedToken>...</trustedToken>]
[<trustLifetime>...</trustLifetime>]
[<deviceId>...</deviceId>]
[<twoFactorAuthRequired>...</twoFactorAuthRequired>]
[<trustedDevicesEnabled>...</trustedDevicesEnabled>]
</AuthResponse>
Note:
only attrs that are allowed to be returned by GetInfo will be returned by this
call
Additional Notes about Auth behavior when mailstore is accessed via reverse proxy
(i.e. nginx)
1. All mail stores are capable of validating the user and generating an Auth Token.
Nginx will direct the auth request to an arbitrary server based on round robin
balancing.
3. For single node configurations (with no nginx proxy) - the session ID can be
passed in either manner - as a cookie -or- in the Soap Header. For code portability
it is best to use the cookie method.
4. For a multi-node configuration passing the Auth Token in the SOAP Header of
subsequent SOAP requests will NOT allow nginx to direct those requests to the
correct mail store for the user account.
The Auth Token MUST instead be sent as a cookie "ZM_AUTH_TOKEN=...Auth Token
returned from AuthRequest..." as this is how nginx tells which mail store the
request needs to be sent to.
---------
<ChangePasswordRequest>
<account by="name">...</account>
<oldPassword>...</oldPassword>
<password>...</password>
[<virtualHost>{virtual-host}</virtualHost>]
</ChangePasswordRequest>
<ChangePasswordResponse>
<authToken>...</authToken>
<lifetime>...</lifetime>
<ChangePasswordResponse/>
---------------------------
Ends the current session, removing it from all caches. Called when
the browser app (or other session-using app) shuts down. Has no
effect if called in a <nosession> context.
Setting logoff to "1" will prevent the cookie from being re-used.
---------
<GetPrefsRequest>
<!-- get only the specified prefs -->
[<pref name="{name1}"/>
<pref name="{name2}"/>]
</GetPrefsRequest>
If no <pref> elements are provided, all known prefs are returned in the response.
If <pref> elements are provided, only those prefs are returned in the response.
<GetPrefsResponse>
<pref name="{name}">{value}</pref>
...
<pref name="{name}">{value}</pref>
</GetPrefsResponse>
----------------------------
<GetInfoRequest
[sections="mbox,prefs,attrs,zimlets,props,idents,sigs,dsrcs,children"]
[rights="{comma-separated-rights}"]>
</GetInfoRequest>
<-- by default, GetInfo returns all data; to limit the returned data, specify
only the sections you want in the "sections" attr -->
<GetInfoResponse>
<version>{version}</version>
<id>{account-id}</id>
<name>{account-name}</name>
<lifetime>...</lifetime>
[<adminDelegated>{admin-delegated}</adminDelegated>
<rest>{account-base-REST-url}</rest>
<used>{used}</used>
<prevSession>{previous-SOAP-session}</prevSession>
<accessed>{last-SOAP-access}</accessed>
<recent>{recent-messages}</recent>
]
<docSizeLimit>{document-size-limit}</docSizeLimit>
<attSizeLimit>{attachment-size-limit}</attSizeLimit>
<cos name="cos-name" id="cos-id"/>
<attrs>
<attr name="{name}">{value}</a>
...
<attr name="{name}">{value}</a>
</attrs>
<prefs>
<pref name="{name}">{value}</pref>
...
<pref name="{name}">{value}</pref>
</prefs>
<props>
<prop zimlet="{zimlet-name}" name="{name}">{value}</prop>
...
<prop zimlet="{zimlet-name}" name="{name}">{value}</prop>
</props>
<zimlets>
<zimlet>
<zimletContext baseUrl="..." priority="..." presence="{zimlet-presence}"/>
<zimlet>...</zimlet>
<zimletConfig>...</zimletConfig>
</zimlet>
...
</zimlets>
<mailURL>{mail-url}</mailURL>+
<publicURL>{account-base-public-url}</publicURL>
[<adminURL>{admin-base-public-url}</adminURL>]
[<communityURL>{community-url}</communityURL>]
[<boshURL>{bosh-url}</boshURL>]
<identities>
<identity name={identity-name} id="...">
<a name="{name}">{value}</a>
...
<a name="{name}">{value}</a>
</identity>*
</identities>
<signatures>
<signature name={signature-name} id="...">
<a name="{name}">{value}</a>
...
<a name="{name}">{value}</a>
</signature>*
</signatures>
<dataSources>
{data-source}
...
</dataSources>*
<childAccounts>
<childAccount name="{child-account-name}" visible="0|1" id="{child-account-
id}">
<attrs>
<attr name="{name}">{value}</a>*
</attrs>
</childAccount>*
</childAccounts>
[<rights>
{same as DiscoverRightsResponse}
</rights>]
</GetInfoResponse>
returned only if the command successfully executes on the target user's home mail
server:
{used} = mailbox quota used in bytes
{last-SOAP-access} = time (in millis) of last write op from this session, or
from *any* SOAP session if we don't have one
{previous-SOAP-session} = time (in millis) of last write op from any SOAP
session before this session was initiated,
or same as {last-SOAP-access} if we don't have one
{recent-messages} = number of messages received since the previous soap
session, or since the last SOAP write op if we don't have a session
http://server:7070/service/soap/
Multiple URLs can be returned if both http and https (SSL) are enabled. If
only one of the two is enabled,
the only one URL will be returned.
attrs under <childAccount>: including the following attrs of the child account:
- displayName
----------------------------
<GetAccountInfoRequest>
<account by="id|name">...</account>
</GetAccountInfoRequest>
Note: For historical reasons, there are some minor differences between the Admin
and Account versions of
GetAccountInfoResponse.
<GetAccountInfoResponse>
<name>{account-name}</name>
<attr name="{name}">{value}</a>+
<soapURL>{soap-url}</soapURL>+
<publicURL>{account-base-public-url}</publicURL>
[<adminURL>{admin-base-public-url}</adminURL>]
[<changePasswordURL>{change-password-url}</changePasswordURL>]
[<communityURL>{community-url}</communityURL>]
[<boshURL>{bosh-url}</boshURL>]
</GetAccountInfoResponse>
{soap-url} = URL to talk to for soap service for this account. i.e:
http://server:7070/service/soap/
Multiple URLs can be returned if both http and https (SSL) are enabled. If
only one of the two is enabled,
the only one URL will be returned.
<GetAvailableSkinsRequest/>
<GetAvailableSkinsResponse>
<skin name="{skin-name}"/>+
</GetAvailableSkinsResponse>
----------------------------
<GetAvailableCsvFormatsRequest/>
<GetAvailableCsvFormatsResponse>
<csv name="{format-name}"/>+
</GetAvailableCsvFormatsResponse>
----------------------------
[<searchFilter>
<conds [not="1|0"] [or="1|0"] >
[<cond> or <conds>]+
</conds> (exactly one instance of <conds>)
-- or --
{tokenize-key-op} = and|or
- Not present if the search key was not tokenized.
- Some clients backtrack on GAL results assuming the results of a more
specific key is the subset of a more generic key, and it checks cached
results instead of issuing another SOAP request to the server.
If search key was tokenized and expanded with AND or OR, this cannot
be assumed.
needExp: if the "exp" flag is needed in the response for group entries.
default is 0
needIsOwner: if the "isOwner" flag is needed in the response for group entries.
default is 0
{gal-entry-ref}: a unigue reference id for the GAL entry. This is the ref id to
be used for the value
of type="G" contact group members. See CreateContactRequest and
ModifyContactRequest.
paginationSupported:
1 - limit and offset in the request was honored
0 - the underlying search does not support pagination
limit and offset in the request was not honored
exp: if the user can (has right to) expand group members
returned only if needExp is 1 in the request and only on group entries
(type=group in attrs on a <cn>).
----------------------------
{tokenize-key-op} = and|or
- Not present if the search key was not tokenized.
- Some clients backtrack on GAL results assuming the results of a more
specific key is the subset of a more generic key, and it checks cached
results instead of issuing another SOAP request to the server.
If search key was tokenized and expanded with AND or OR, this cannot
be assumed.
needExp: if the "exp" flag is needed in the response for group entries.
default is 0
exp: if the user can (has right to) expand group members
returned only if needExp is 1 in the request and only on group entries
(type=group in attrs on a <cn>).
----------------------------
<AutoCompleteResponse canBeCached="0|1">
<match ranking="..." email="..." type="gal|contact|rankingTable" isGroup="1|0"
[exp="1|0"] [display="..."] [id="..."] [l="..."] [first="..."] [middle="..."]
[last="..."] [nick="..."] [full="..."] [company="..."] [fileas="..."] />*
</AutoCompleteResponse>
----------------------------
If the request has idOnly set to true, then the response will contain
id attribute without all the contact fields populated. The sync client
then should make batch request to the server to fetch the contact fields
with <GetContactsRequest/>.
Note: idOnly only works when GAL sync account is configured/enabled.
If idOnly is specified and GAL sync account is not enabled, idOnly will
be ignored.
galDefinitionLastModified is the time at which the GAL definition is last
modified.
This is returned if the sync does not happen using GAL sync account.
{throttled-flag} - true if the SyncGal request is throttled.
{fullSyncRecommended-flag} - true if GalSync Account is available and the client
is using LDAP based sync.
----------------------------
<SearchCalendarResourcesRequest>
[attrs="a1,a2,a3"] [sortBy="{sortBy}"] [sortAscending="{sortAscending}"]
[limit="..."] [offset="..."]>
[<name>...</name>]
<searchFilter>
<conds [not="1|0"] [or="1|0"] >
[<cond> or <conds>]+
</conds> (exactly one instance of <conds>)
-- or --
</SearchCalendarResourcesRequest>
<SearchCalendarResourcesResponse [paginationSupported="1|0"]>
<calresource name="{name}" id="{id}">
<a n="...">...</a>+
</calresource>*
</SearchCalendarResourcesResponse>
Notes:
SearchCalendarResourcesRequest:
attrs - comma-separated list of attrs to return ("displayName", "zimbraId",
"zimbraCalResType")
sortBy - name of attribute to sort on. default is the calendar resource name.
sortAscending - whether to sort in ascending order (0/1), 1 is default
name: if specified, pass through to the GAL search as the search key
must have exactly one <conds> child or exactly one <cond> child and no other
child element
SearchCalendarResourcesResponse:
paginationSupported:
1 - limit and offset in the request was honored
0 - the underlying search does not support pagination
limit and offset in the request was not honored
----------------------------
<ModifyPrefsRequest>
[<pref name="{name}">{value}</pref>...]+
</ModifyPrefsRequest>
<ModifyPrefsResponse/>
Notes:
For multi-value prefs, just add the same attribute with 'n' different values:
<ModifyPrefsRequest>
<pref name="foo">value1</pref>
<pref name="foo">value2</pref>
.
.
.
</ModifyPrefsRequest>
You can also add/subtract single values to/from a multi-value pref by prefixing
the preference name with a '+' or '-', respectively in the same way you do when
using zmprov. For example:
<ModifyPrefsRequest>
<pref name="+foo">value1</pref>
<pref name="-foo">value2</pref>
.
.
.
</ModifyPrefsRequest>
---------
<CreateIdentityRequest>
<identity name="{identity-name}">
<a name="{name}">{value}</a>
...
<a name="{name}">{value}</a>
</identity>
</CreateIdentityRequest>
<CreateIdentityResponse>
<identity name="{identity-name}" id="{identity-id}">
....
</identity>
</CreateIdentityResponse>
Allowed attributes (see objectclass zimbraIdentity in zimbra.schema)
zimbraPrefBccAddress
zimbraPrefForwardIncludeOriginalText
zimbraPrefForwardReplyFormat
zimbraPrefForwardReplyPrefixChar
zimbraPrefFromAddress
zimbraPrefFromDisplay
zimbraPrefMailSignature
zimbraPrefMailSignatureEnabled
zimbraPrefMailSignatureStyle
zimbraPrefReplyIncludeOriginalText
zimbraPrefReplyToAddress
zimbraPrefReplyToDisplay
zimbraPrefReplyToEnabled
zimbraPrefSaveToSent
zimbraPrefSentMailFolder
zimbraPrefUseDefaultIdentitySettings
zimbraPrefWhenInFolderIds
zimbraPrefWhenInFoldersEnabled
zimbraPrefWhenSentToAddresses
zimbraPrefWhenSentToEnabled
---------
<GetIdentitiesRequest/>
<GetIdentitiesResponse>
<identity name="{identity-name}" id="{identity-id}">
<a name="{name}">{value}</a>
...
<a name="{name}">{value}</a>
</identity>+
</GetIdentitiesResponse>
---------
<ModifyIdentityRequest>
<identity [name="{identity-name}" | id="{identity-id}"]>
<a name="{name}">{value}</a>
...
<a name="{name}">{value}</a>
</identity>
</ModifyIdentityRequest>
<ModifyIdentityResponse/>
---------
<DeleteIdentityRequest>
<identity [name="{identity-name}" | id="{identity-id}"]/>
</DeleteIdentityRequest>
<DeleteIdentityResponse/>
<CreateSignatureRequest>
<signature name="{signature-name}" [id="{id}"]/>
<content type="{text/plain | text/html}">{signature-value}</content>+
[<cid>{contact-id}</cid>]
</signature>
</CreateSignatureRequest>
<CreateSignatureResponse>
<signature id="{id}" name="{signature-name}"/>
</CreateSignatureResponse>
- CreateSignature will set account default signature to the signature being created
if there is currently no default signature for the account.
- There can be at most one text/plain signatue and one text/html signature.
---------
<GetSignaturesRequest/>
<GetSignaturesResponse>
<signature name="{signature-name}" id="{signature-id}"
<content type="{text/plain | text/html}">{signature-value}</content>+
[<cid>{contact-id}</cid>]
</signature>+
</GetSignaturesResponse>
---------
<ModifySignatureRequest>
<signature id="{signature-id}" [name="{signature-name}"]>
<content type="{text/plain | text/html}">{signature-value}</content>+
[<cid>{contact-id}</cid>]
</signature>
</ModifySignatureRequest>
<ModifySignatureResponse/>
- Changes attributes of the given signature. Only the attributes specified in the
request
are modified.
- Server identify the signature by id, if the name attribute is present and is
different
from the current name of the signature, the signature will be renamed.
---------
<DeleteSignatureRequest>
<signature [name="{signature-name}" | id="{signature-id}"]/>
</DeleteSignatureRequest>
<DeleteSignatureResponse/>
---------
urn:zimbraMail
------------------------------
mail.QUERY_PARSE_ERROR details
Arguments:
colNo - index into query string where the error occured
curTok - current token being parsed (not always set)
parserErr - localizable error code describing what happened. Current codes:
UNKNOWN_TEXT_AFTER_IS - user entered is:blah, blah unknown
MISSING_TEXT_AFTER_TOFROMCC - user entered from: without required text
LEXICAL_ERROR - Invalid character in search string or invalid operator
name (e.g. "iis:foo")
PARSER_ERROR - Missing operand after operator ("in:") or other general
parse error, look at curTok
INVALID_DATE - Couldn't parse argument to date: (before: after: etc)
query. Check curTok.
------------------------------
<!--
-->
Email addresses:
Note that "rf" addresses can only be *returned* on a message; when sending
a message, "rf" is ignored
MimeParts:
{mime-part-name} = MIME part, "" means top-level part, 1 first part, 1.1 first
part of a multipart inside of 1.
truncated="1" = the caller requested a maximum length (max="...") for inlined
<content>, and this part's content was truncated down to that length
{content-type} = MIME Content-Type. The mime type is the content of the element.
{name} = name attribute from the Content-Type param list
{cont-disp} = MIME Content-Disposition
{filename} = filename attribute from the Content-Disposition param list
{content-id} = MIME Content-ID (for display of embedded images)
{content-location} = MIME/Microsoft Content-Location (for display of embedded
images)
{cont-desc} = MIME Content-Description. Note cont-desc is not currently used in
the code.
{content} = the content of the part, if requested
{is-body} = set to 1, if this part is considered to be the "body" of the message
for display
purposes.
{message-id} = item id of the enclosing message, only present if <mp> is not
enclosed within a <m> element
Messages:
<mid>{Message-ID header}</mid>
[<inv>...</inv>]
[<mp>...</mp>]
[<content (url="{url}")>...</content>]
</m>
{content} = complete rfc822 message. only present during certain operations that
deal with the raw content
of a message. There is at most 1 content element.
{conv-id} = converstation id. only present if <m> is not enclosed within a <c>
element
{size} = size in bytes
{flags} = (u)nread, (f)lagged, has (a)ttachment, (r)eplied, (s)ent by me,
for(w)arded, calendar in(v)ite,
(d)raft, IMAP-\Deleted (x), (n)otification sent, urgent (!), low-
priority (?), priority (+)
{date} = secs since epoch, from date header in message
{original-id} = message id of message being replied to/forwarded (outbound
messages only)
{url} = content servlet relative url for retrieving message content
{subject} = subject of the message, only returned on an expanded message
{fragment} = first n-bytes of the message (probably between 40-100)
<e .../>* = zero or more addresses in the message, indentified by
type (t="f|t|c")
<inv ...>...</inv> = Parsed out iCal invite. See soap-calendar.txt
<mp ...>...</mp> = The root MIME part of the message. There is exactly 1 MIME
part under
a message element. The "body" will be tagged with body="1", and the
content
of the body will also be present
<content> = the raw content of the message. cannot have more than one of <mp>,
<content> url, and <content> body.
Conversations:
folders can have an optional ACL set on them for sharing. if they do (and the
authenticated
user has (a)dminister rights on the folder), an <acl> element will be returned
containing
1 or more <grant> elements.
Retention policy:
<retentionPolicy>?
<keep>
<policy type="user" lifetime="{duration}"/>?
<policy type="system" id="{id}" name="{name}" lifetime="{duration}"/>*
</keep>
<purge>
<policy type="user" lifetime="{duration}"/>?
<policy type="system" id="{id}" name="{name}" lifetime="{duration}"/>*
</purge>
</retentionPolicy>
Mountpoints:
Tags:
{tag-name} = name of tag; cannot begin with '\' (avoid collsions with IMAP)
{color} = numeric; range 0-127; defaults to 0 if not present; client can
display only 0-7
{unread} = number of unread messages with this tag
{item-count} = number of items with this flag
----------
*(<header n="{header-name}/>)
[<cursor id="prevId" [sortVal="prevSortValue"] [endSortVal="endSortValue"]
[includeOffset="true|false"]/>]
[ // OPTIONAL: client timezone identification (necessary to time-correct a
user-specified date/time query)
OR
<query>{query-string}</query>
</SearchRequest>
if fetch="1" (or fetch="first") is specified, the first hit will be expanded inline
(messages only at present)
if fetch="{item-id}", only the message with the given {item-id} is expanded inline
if fetch="all", all hits are expanded inline
+ if html="1" is also specified, inlined hits will return HTML parts if
available
+ if read="1" is also specified, inlined hits will be marked as read
+ if neuter="0" is also specified, images in inlined HTML parts will not be
"neutered"
+ if <header>s are requested, any matching headers are included in inlined
message hits
+ if max="{max-inlined-length}" is specified, inlined body content in limited
to the given length;
if the part is truncated, truncated="1" is specified on the <mp> in
question
warmup: When this option is specified, all other options are simply ignored, so
you can't include this option in
regular search requests. This option gives a hint to the index system to open
the index data and primes it for
search. The client should send this warm-up request as soon as the user puts the
cursor on the search bar. This will
not only prime the index but also opens a persistent HTTP connection (HTTP 1.1
Keep-Alive) to the server, hence
smaller latencies in subseqent search requests. Sending this warm-up request too
early (e.g. login time) will be in
vain in most cases because the index data is evicted from the cache due to
inactivity timeout by the time you
actually send a search request.
quick: For performance reasons, the index system accumulates messages with not-
indexed-yet state until a certain
threshold and indexes them as a batch. To return up-to-date search results, the
index system also indexes those
pending messages right before a search. To lower latencies, this option gives a
hint to the index system not to
trigger this catch-up index prior to the search by giving up the freshness of
the search results, i.e. recent
messages may not be included in the search results.
If needExp is "1", two additional flags will be included in <e> elements for
messages
returned inline:
- isGroup: "1" if the email address is a group
- exp: present only when isGroup="1"
"1" if the authed user can (has permission to) expand members in this
group
"0" if the authed user does not have permission to expand group members
<cursor> (optional):
- id, sortVal: These correspond to the last hit on the current page (assuming
you're going forward, if you're backing
up then they should be the first hit on the current page) or the selected item
before changing the sort order.
sortVal should be set to the value of the 'sf' (SortField) attribute. If you
are changing the sort field, don't
specify sortVal because 'sf' is sort field dependent. (In this case, the server
supplements sortVal using the
specified item ID. If the item no longer exist, the cursor gets cleared.) The
server uses those attributes to find
the spot in the new results that corresponds to your old position: even if some
entries have been removed or added
to the search results (e.g. if you are searching is:unread and you read some).
- endSortVal (optional): Used for ranges to tell the cursor where to stop (non-
inclusive) returning values
- includeOffset (optional): If true, the response will include the cursor
position (starting from 0) in the entire
hits. This can't be used with text queries. Don't abuse this option because
this operation is relatively expensive
in the server.
- Cursors are NOT legal if sortBy="none".
conversation result:
--------------------
Info block:
The <info> block is used to return general status
information about your search. The <wildcard> element tells
you about the status of wildcard expansions within your search
-- if expanded=1, then the wildcard was expanded and the
matches are included in the search. If expanded=0 then the
wildcard was not specific enough and therefore no wildcard
matches are included (exact-match *is* included in results).
message result:
---------------
<SearchResponse sortBy="sort-by" offset="..." more="{more-flag}">
[<info>...</info>]
<m id="{message-id}" tn="{tag-names}" f="{flags}" s="{size}" d="{date}"
cid="{conv-id}" l="{location}" [mbx="UID"] sf="SORT-FIELD-VALUE" [cm="1"]>
<e .../>* <!- from only -->
<su>{subject}</su>
<fr>{fragment}</fr>
*(<header n="{header-name}">header content</header>)
[<mp>...</mp>] // if fetch=1, the <mp>'s of the hit (first hit only)
<hp part="{mime-part-name}"/>+ // Hit Part -- indicator that the named part
matched the search string
</m>
</SearchResponse>
contact result:
---------------
<SearchResponse offset="..." more="{more-flag}">
[<info>...</info>]
<cn id="id" tn="tags" l="folder" sf="SORT-FIELD-VALUE" [email="Email_1 Addr"]
[email2="Email_2_addr"]
email3="Email_3_addr" [type="contact|group"] rev="REVISION" fileAsStr="..."
md="{metadata-change-date}"/>
appointment result:
-------------------
<appt|task id="appointment_mail_item_id"
tn="{tag-names}" f="{flags}" s="{size}" d="{date}" cid="{conv-id}" //
standard hit data
l="{location}" [mbx="UID"] sf="SORT-FIELD-VALUE" // standard hit data
[fba="F|B|T|U"]
[transp="O|T"]
status="TENT|CONF|CANC"
ptst="NE|TE|AC|DE|DG"
[allDay="1"] // if set, this is an "all day" appointment
[otherAtt="1"] // if set, this appointment has other attendees
[alarm="1"]
[recur="1"] // if set, this is a recurring appointment
[hasEx="1"] // if set, this is a recurring appointment with
exceptions
[name="NAME"] [loc="LOCATION"]
invId="default_invite_mail_item_id"
compNum="default_invite_component_number"
isOrg="default_am_i_organizer_flag"
[priority="num"]
[percentComplete="num"] // only if a <task>
[dur="duration"] // default duration; for appointments only
>
[<or d="friendly name" a="address">] // organizer, if available
[<fr>DEFAULT FRAGMENT</fr>]
[ <inst
[s="ms"] // start time in millis
[tzo="ms"] // offset from GMT in milliseconds for start time in the
// time zone of the instance; this is useful because the
// instance time zone may not be the same as the time zone
// of the requesting client; when rendering an all-day
// appointment, the client must shift the appointment by
// the difference between the instance time zone and its
// local time zone to determine the correct date to render
// the all-day block
[dueDate="ms"] // due date in millis; for tasks only
[tzoDue="ms"] // similar to tzo, but for dueDate; tzoDue can be
different from tzo if start date
// and due date lie on different sides of daylight
savings transition
[ex="1"]
[ridZ="YYYYMMDD[ThhmmssZ]"] // RECURRENCE-ID in "Z" (UTC) timezone, if
this is an exception
[ANY CHANGED PARAMETERS]
>
[<f>FRAGMENT IF DIFFERENT FROM DEFAULT</f>]
[<dur DURATION>] // duration this instance if not same as default
[<isOrg>] // isOrg flag if not same as default
[<otherAtt>] // otherAtt flag if not same as default
</inst>
]+
Next alarm trigger time and related info:
[ <alarmData
nextAlarm="time in millis to show the alarm"
alarmInstStart="start time of the meeting instance the alarm is reminding
about"
name="meeting subject"
loc="meeting location"
invId="invId" compNum="compNum" // these are used in GetMsg call
>
<alarm .../> // detail of the alarm (repeat policy, text to show, etc.)
// See <alarm> definition in soap-calendar.txt
</alarmData>
]
</appt|task>
message-part result:
--------------------
<SearchResponse offset="..." more="{more-flag}">
[<info>...</info>]
<mp part="{mime-part-name}" s="{size-in-bytes} mid="{message-id}"
ct="{content-type}" name="{name}" filename="{filename}" sf="SORT-FIELD-
VALUE"/>
</SearchResponse>
-----------
fetch:
0|none|false: no messages are expanded inline
1|first: the first matching message is expanded inline
!: the first message in the conversation is expanded inline
u|unread: all unread matching messages are expanded inline
u1|unread-first: all unread messages (or the first message if there are no
unread messages) are expanded inline
u!: if there are unread matching messages, they are expanded inline, otherwise
the first message is expanded
u1!: if there are unread matching messages, they are expanded inline, otherwise
the first message and the first matching message are expanded
hits: all matching messages are expanded inline
hits!: if there are matching messages, they are expanded inline, otherwise the
first message is expanded
all: all messages are expanded inline
{comma-separated item-ids}: only the messages with {item-id} in the list are
expanded inline
wantContent = "full" to get the complete message along with the quoted content
wantContent = "original" to get the message without quoted content
wantContent = "both" to get complete message as well as the message without quoted
content
By default wantContent = "full"
Note: Quoted text identification is a best effort. It is not supported by any RFCs
If needExp is "1", two additional flags will be included in <e> elements for
messages
returned inline:
- isGroup: "1" if the email address is a group
- exp: present only when isGroup="1"
"1" if the authed user can (has permission to) expand members in this
group
"0" if the authed user does not have permission to expand group members
------------
<BrowseResponse>
<bd freq="count">{browse-data}</bd>*
</BrowseResponse>
{browse-by} = domains|attachments|objects
where "objects" means objects in message body content recognized by
Zimlets via <contentObject>
configuration.
{regex-string} = return only those results which match the specified regular
expression
{max} = return only a maximum number of entries as requested. If more than {max}
results exist, the server will return the first {max}, sorted by
frequency
{browse-data} =
for attachments: content type (application/msword)
<bd h="{h-flags}">stanford.edu</bd>
which indicates whether or not the domain was from the "From", "To", or "Cc"
header.
Valid flags are always one of: "f", "t", "ft", "c", "fc", "tc", "ftc"
----------
<GetItemRequest>
[<item [id="{item-id}"] [path="{path}"] [l="{folder-id}"]/>]
</GetItemRequest>
<GetItemResponse>
<folder|m|c|cn|wiki|etc. ...>
</GetItemResponse>
----------
- if *no* folders are visible and visible=1, the response looks like
<GetFolderResponse/>
- if "view" is set then only the folders with matching view will be returned.
otherwise folders with any default views will be returned.
<GetFolderResponse>
<folder ...>
<folder .../>
<folder ...>
<folder .../>
</folder>
<folder .../>
[<link .../>]
[<search .../>]
</folder>
</GetFolderResponse>
GetFolderResponse always has exactly 1 folder element within it. Without a base
folder ID that folder element will represent the virtual root folder.
If "tr" is true, broken links are rendered with broken="1" on the resulting <link>
element.
----------
<GetConvRequest>
<c id="{conv-id}" [fetch="1|all|{item-id}" max="{max-inlined-length}" html="0|1"
needExp="0|1"]>
*(<header n="{header-name}/>)
</c>
</GetConvRequest>
if <header>s are requested, any matching headers are inlined into the response
(not available when raw="1")
needExp="1" to return group info (isGroup and exp flags) on <e> elements in the
response
(default is 0.)
<GetConvResponse>
<c id="{conv-id}" [tn="{tag-names}"] n="{num-msgs}" [total="{all-msgs}"]
[f="{flags}"]>
<su>{subject}</su>
<m id="{message-id}" [f="{flags}"] s="{size}" d="{date}" [tn="{tag-names}"]>
<e .../>
<fr>{fragment}</fr>
<su>{subject}</su>
</m>+
</c>
</GetConvResponse>
------------
<GetMsgRequest>
<m id="{msg-id}" [read="1"] [raw="1"] [max="{max-inlined-length}"] [html="1"]
[neuter="0"] [part="{part}"]
[ridZ="YYYYMMDD[ThhmmssZ]"] [needExp="1|0"] [wantContent="full|original|
both"]>
*(<header n="{header-name}/>)
</m>
</GetMsgRequest>
read="1" to mark the message as read, "0" to leave the read status unchanged.
(default is 0.)
raw="1" to return the raw message content rather than a parsed mime structure;
(default is "0". if message too big or not ASCII, a content servlet URL is
returned)
max="{max-inlined-length}" to limit the length of the text inlined into body
<content> when raw="0"
(default is "0", meaning no limit.)
html="1" to return defanged HTML content by default.
(default is 0.)
neuter="1" to "neuter" <IMG> tags returned in HTML content; this involves switching
the "src" attribute to "dfsrc" so that images don't display by default
(default is 1.)
supply a "part" and the retrieved data will be on the specified message/rfc822
subpart.
if the part does not exist or is not a message/rfc822 part, mail.NO_SUCH_PART
needExp="1" to return group info (isGroup and exp flags) on <e> elements in the
response
(default is 0.)
wantContent = "full" to get the complete message along with the quoted content
wantContent = "original" to get the message without quoted content
wantContent = "both" to get complete message as well as the message without quoted
content
By default wantContent = "full"
Note: Quoted text identification is a best effort. It is not supported by any RFCs
if <header>s are requested, any matching headers are inlined into the response
(not available when raw="1")
<GetMsgResponse>
<m id="{message-id}" [origid="..." rt="r|w"] [part="{part}"] f="{flags}"
tn="{tag-names}" s="{size}" [d="{received-date}"] sd="{date-header}" [rd="{resent-
date}"] l="{folder}" (cid="{conv}")
(cif="{X-Zimbra-Calendar-Intended-For header}")
>
<e ... [isGroup="1|0"] [exp="1|0"]/>*
<su>{subject}</su>
<fr>{fragment}</fr>
[<irt>{Message-ID header for message being replied to}</irt>]
<mid>{Message-ID header}</mid>
*(<header n="{header-name}">header content</header>)
[<mp>...</mp>]
[<shr><content>{share-announcement-in-xml}</content</shr>]
[<dlSubs><content>{dl-subscription-request-in-xml}</content</dlSubs>]
[<content (url="...")>...</content>]
[<origContent>...</origContent>]
</m>
</GetMsgResponse>
If needExp is "1" in the request, two additional flags will be included in <e>
elements for the message:
- isGroup: "1" if the email address is a group
- exp: present only when isGroup="1"
"1" if the authed user can (has permission to) expand members in this
group
"0" if the authed user does not have permission to expand group members
------------
<GetMsgMetadataRequest>
<m ids="{msg-id-list}"/>
</GetMsgMetadataRequest>
<GetMsgMetadataResponse>
(<m id="{message-id}" f="{flags}" tn="{tag-names}" s="{size}" d="{received-date}"
l="{folder}" [cid="{conv}"]
rev="{revision-number}" md="{date-metadata-changed}" ms="{change-
sequence}"/>)*
</GetMsgMetadataResponse>
------------
<CreateFolderRequest>
<folder name="..." [l="{parent-folder}"] [fie="1"] [view="{default-type}"]
[color="{color}"] [rgb="{rgb-color}"] [f="{flags}"] [url="{url}"] [sync="1"]>
<acl [internalGrantExpiry="{millis-since-epoch}"] [guestGrantExpiry="{millis-
since-epoch}"]>
<grant perm="{rights}" gt="{grantee-type}" zid="{zimbra-id}"
[expiry="{millis-since-epoch}"] [d="{grantee-name}"] [key="{access-key}"]/>*
</acl>?
</folder>
</CreateFolderRequest>
- if l is unset, name is the full path of the new folder; otherwise, name may not
contain the folder separator '/'
- if fie="1" is set, the server will fetch the folder if it already exists rather
than throwing mail.ALREADY_EXISTS
- if url is set and sync="1" (default), synchronize folder content on folder
creation
<CreateFolderResponse>
<folder id="..." name="..." l="{parent-folder}" [u="{unread count}"] [n="{msg
count}"]/>
</CreateFolderResponse>
---------
<ItemActionRequest>
<!-- action can be preceeded by a "!" to negate it" -->
<action id="{list}" op="delete|dumpsterdelete|recover|read|flag|priority|tag|
move|trash|rename|update|color|lock|unlock"
[tn="{tag-name/list}"] [l="{folder}"] [name="{item-name}"]
[color="{color}"] [rgb="{rgb-color}"]
[tcon="[-]{constraint}"] [f="{flags}"]/>
</ItemActionRequest>
<ItemActionResponse>
<action id="{list}" op="delete|read|flag|tag|move|trash|rename|update"/>
</ItemActionResponse>
For op="update", caller can specify any or all of: l="{folder}", name="{name}",
color="{color}",
tn="{tag-names}", f="{flags}". When modifying tags or flags, all specified
tags and flags
are set, and all others are unset.
For op="recover", caller must specify l="{folder}". The item is recovered from
dumpster as a copy
in the specified folder. The dumpster copy is then deleted.
For op="tag" or op="!tag", caller must specify tn="{tag-name}". This changes the
state of
the specified tag without altering other tags.
A trash operation on a remote item will cause it to be moved to the trash folder
of its
remote mailbox, not the local mailbox.
The <action> element in the response always contains the same id list that the
client
sent in the request. Id's that were ignored due to constraints are included in
the
id list.
---------
<MsgActionRequest>
<!-- action can be preceeded by a "!" to negate it" -->
<action id="{list}" op="delete|read|flag|tag|move|update|spam|trash" [tag="{id}"]
[l="{folder}"] [f="{flags}"] [tn="{tag-names}"] [color="{color}"]/>
</MsgActionRequest>
<MsgActionResponse>
<action id="{list}" op="delete|read|flag|tag|move|update|spam|trash"/>
</MsgActionResponse>
For op="update", caller can specify any or all of: l="{folder}", name="{name}",
color="{color}",
tn="{tag-names}", f="{flags}".
---------
<ConvActionRequest>
<!-- action can be preceeded by a "!" to negate it" -->
<action id="{list}" op="delete|read|flag|priority|tag|move|spam|trash|mute"
[tag="{id}"] [l="{folder}"] [tcon="{constraint}"] [tcon="[-]{constraint}"]
[acctRelPath="{relative-folder-path}"]/>
</ConvActionRequest>
<ConvActionResponse>
<action id="{list}" op="delete|read|flag|tag|move|spam|trash"/>
</ConvActionResponse>
For op="move", "acctRelPath" attr can also be used to specify the target folder,
in terms of the relative path
from the account / data source's root folder. The target account / data source
is identified based on where the
messages in this conversation already reside. If a conversation contains
messages belonging of multiple accounts /
data sources then it would not be affected by this operation.
---------
<FolderActionRequest>
<action id="{list}" op="read|delete|rename|move|trash|empty|color|[!]grant|
revokeorphangrants|url|import|sync|fb|[!]check|update|[!]syncon|retentionpolicy|
[!]disableactivesync|webofflinesyncdays" [l="{target-folder}"]
[name="{new-name}"] [color="{new-color}"] [rgb="{rgb-color}"]
[zid="{grantee-zimbra-id}"] [url="{target-url}"]
[excludeFreeBusy="{exclude-free-busy-boolean}"]
[numDays="{web-offline-sync-days}"]>
[<grant perm="..." gt="..." zid="..." [expiry="{millis-since-epoch}"] [d="..."]
[key="..."]/>]
[<retentionPolicy> ... </retentionPolicy>]
</action>
</FolderActionRequest>
<FolderActionResponse>
<action id="{list}" op="read|delete|empty|rename|move|trash|color|grant|url|
import|sync|fb|[!]check|update" [zid="{grantee-zimbra-id}"]/>
</FolderActionResponse>
Actions:
<action op="read" id="{list}"/>
- mark all items in the folder as read
{list} = on input, list of folders to act on, on output, list of folders that
were acted on;
list may only have 1 element for actions empty, sync, fb, check, !check,
url, import, grant, !grant, revokeorphangrants,
!flag, !tag, syncon, !syncon, retentionpolicy
output of "grant" action includes the zimbra id the rights were granted on
note that "delete", "empty", "rename", "move", "color", "update" can be used on
search folders as well as standard folders
---------
<TagActionRequest>
<action op="read|rename|color|delete|update|retentionpolicy" [id="{tag-ids}" |
tn="{tag-names}"] [name="..."] [color="..."]>
[<retentionPolicy> ... </retentionPolicy>]
</action>
</TagActionRequest>
<TagActionResponse>
<action op="read|rename|color|delete|update|retentionpolicy" id="..."
[tn="..."] /> <!-- iff op was successful -->
</TagActionResponse>
--------------
<GetTagRequest/>
<GetTagResponse>
<tag id="..." name="..." color="..." [u="{unread_count}"] [n="{item-count}"]/>+
</GetTagResponse>
<CreateTagRequest>
<tag name="..." (color="...")/>
</CreateTagRequest>
<CreateTagResponse>
<tag (same as GetTagResponse)/>
</CreateTagResponse>
---------
<GetSearchFolderRequest>
<!-- get all by default -->
</GetSearchFolderRequest>
<GetSearchFolderResponse>
<search id="..." name="..." query="..." [types="..."] [sortBy="..."]
l="{folder}"/>+
</GetSearchFolderResponse>
---------
<CreateSearchFolderRequest>
<search name="..." query="..." [types="..."] [sortBy="..."] l="{folder}"
[f="{flags}"] [color="{color}"] [rgb="{rgb-color}"]/>
</CreateSearchFolderRequest>
<CreateSearchFolderResponse>
<search id="..." name="..." query="..." [types="...] [sortBy="..."]
l="{folder}"/>
</CreateSearchFolderResponse>
---------
<ModifySearchFolderRequest>
<search id="..." query="..." [types="..."] [sortBy="..."]/>
</ModifySearchFolderRequest>
<ModifySearchFolderResponse>
<search id="..." name="..." query="..." [types="...] [sortBy="..."]
l="{folder}"/> <!-- iff it was modified -->
</ModifySearchFolderResponse>
---------
<CreateMountpointRequest>
<link l="{folder}" name="{mountpoint-name}" [view="..."] [color="{color}"]
[rgb="{rgb-color}"] [f="{flags}"] [fie="1"]
[zid="{owner's-zimbra-id}" | owner="{owner's-email-address}"] [rid="{id-
of-shared-item}" | path="{path-to-shared-item}"]
[reminder="0"]/>
</CreateMountpointRequest>
- caller must specify one of (zid | owner) and one of (rid | path)
- reminder=1 means client should display reminders for shared appointments/tasks
<CreateMountpointResponse>
<link id="{created-link-item-id}" l="{folder}" name="..." [view="..."]/>
</CreateMountpointResponse>
---------
<EnableSharedReminderRequest>
<link id="{mountpoint id}" reminder="0|1"/>
</EnableSharedReminderRequest
<EnableSharedReminderResponse/>
---------
If you want to compose the message based on existing draft use the following. The
parameter sfd="1" (sendFromDraft) instructs
the server to construct message based on the "did" (id of the draft). The draft
item will be removed if the SendMsg is successful.
Or if you want to compose the message based on existing draft, but want to make
some changes such
as subject/recipient follow the below steps.
1> Send <GetMsgRequest> with the draft id as message id, and get all the data for
the saved message.
2> Use <SendMsgRequest> with the data retrieved from <GetMsgResponse> and set the
"did" parameter to draft id.
This will ensure that the draft gets removed if the SendMsg is successful.
# If the message is saved to the sent folder then the id of the message is
returned.
# Otherwise, no id is returned -- just a <m></m> is returned.
<SendMsgResponse>
<m id="..." />
</SendMsgResponse>
dsId - Id of the data source in case SMTP settings of that data source must be used
for sending the message.
----------------------------
+ only allowed one top-level <mp> but can nest <mp>s within if multipart/*
+ on reply/forward, set origid on <m> element and set rt to "r" or "w",
respectively
+ can optionally set identity-id to specify the identity being used to compose the
message
+ if updating an existing draft, set "id" attr on <m> element
+ can refer to parts of existing draft in <attach> block
+ drafts default to the Drafts folder
+ setting folder/tags/flags/color occurs *after* the draft is created/updated, and
if it fails the content *WILL STILL BE SAVED*
+ can optionally set autoSendTime to specify the time at which the draft should be
automatically sent by the server
<SaveDraftRequest>
<m [id="{existing-draft-id}"] [origid="..." rt="r|w"] [idnt="{identity-id}"]
[l="{folder}"] [f="{flags}"] [tn="{tag-names}"] [color="{color}"]
[autoSendTime="{millis-since-epoch}"]>
<e t="{type}" a="{email-address}" p="{personal-name}"/>+
<su>{subject}</su>*
[<header name="{header-name}">{header-value}</header>]*
[<irt>{Message-ID header for message being replied to}</irt>]
<mp ct="{content-type}">
<content>...</content>
</mp>
<attach [aid="{attach-upload-id}"]>
[<m id="{message-id}" [optional="0|1"]/>]*
[<mp mid="{message-id}" part="{part-id}" [optional="0|1"]/>]*
[<cn id="{contact-id}" [optional="0|1"]/>]*
[<doc (id="{document-id}" | path="{document-path}") [optional="0|1"]/>]*
</attach>
</m>
</SaveDraftRequest>
<SaveDraftRequest>
<m aid="{uploaded-MIME-body-ID}" [id="{existing-draft-id}"]
[origid="..." rt="r|w"] [l="{folder}"] [f="{flags}"] [tn="{tag-names}"]
[color="{color}"] [autoSendTime="{millis-since-epoch}"]/>
</SaveDraftRequest>
The identity referenced by {identity-id} specifies the folder where the sent
message
is saved.
----------------------------
<SendDeliveryReportRequest mid="{message-id}"/>
<SendDeliveryReportResponse/>
----------------------------
<BounceMsgRequest>
<m id="{id-of-msg-to-resend}">
<e .../>*
</m>
</BounceMsgRequest>
<BounceMsgResponse/>
----------------------------
<AddMsgRequest [filterSent="0|1"]>
<m l="{folder}" [f="{flags}"] [tn="{tag-names}"] [d="{received-date}"]
[aid="{uploaded-MIME-body-ID}"] [noICal="0|1"]>
<content>
...
</content>
[
<inv uid="UID">...</inv> # MUST have UID
]
...
</m>
</AddMsgRequest>
Note that the <m> element should include the <content> element with the
entire message's content. (Omit <content> if you specify an "aid" attribute.)
No <mp> elements should be provided within <m>.
----------------------------
<RemoveAttachmentsRequest>
<m id="{message-id}" part="{list-of-part-ids-to-remove}">
</RemoveAttachmentsRequest>
# NOTE that this operation is effectively a create and a delete, and thus the
message's item ID will change
<RemoveAttachmentsResponse>
<m id="{message-id}" f="{flags}" tn="{tag-names}" s="{size}" d="{received-
date}" l="{folder}" [cid="{conv}"]
rev="{revision-number}" md="{date-metadata-changed}" ms="{change-
sequence}"/>
</RemoveAttachmentsResponse>
----------------------------
Contacts:
Date related attributes like "birthday" and "anniversary" SHOULD use "yyyy-MM-dd"
format or, if the year
isn't specified "--MM-dd" format
----------
<CreateContactRequest [verbose="0|1"]>
<cn [l="{folder-id}"] [tn="{tag-names}"]>
<a>...</a>+
<m type="{member-type}" value="{member-value}"/>*
</cn>
</CreateContactRequest>
<m> : valid only if the contact being created is a contact group (has attribute
type="group")
{member-type} = C|G|I
C: reference to another contact
G: reference to a GAL entry
I: inlined member (member name and email address is embeded in
the contact group)
or, if you have an existing vCard to add, you can specify a <vcard> element with
*one* of
-- inlined content
-- mid/part attributes specifying an existing message part
-- aid attribute specifying an uploaded text/calendar file
<CreateContactRequest [verbose="0|1"]>
<cn [l="{folder-id}"] [tn="{tag-names}"]>
<vcard [mid="{message-id}" part="{part-identifier}] [aid={uploaded-attachment-
id"}"]>
[BEGIN:VCARD
...
END:VCARD]
</vcard>
</cn>
</CreateContactRequest>
<CreateContactResponse>
(<cn> definition above)
</CreateContactResponse>
----------
if {replace-mode} is 1, all attrs and group members in the specified contact are
replaced with specified attrs
and group members, otherwise the attrs and group members are merged with the
existing contact.
{op} = + | -
+ : add the value
- : remove the value
(2) if op is present:
if {attr-value} is empty, throw INVALID_REQUEST
- otherwise, add/remove the specified value.
{member-op} = + | - | reset
+ : add the value - {member-type} and {member-value} are required
- : remove the value - {member-type} and {member-value} are required
reset : Delete all pre-existing members - new members can be specified
with later <m> elements using "+"
{member-type} and {member-value} are ignored
When {replace-mode} is 1, {member-op} must NOT be specified. If it is,
INVALID_REQUEST will be thrown
When {replace-mode} is 0, {member-op} is required.
When modifying tags, all specified tags are set and all others are unset. If
tn="{tag-names}" is NOT specified
then any existing tags will remain set.
<ModifyContactResponse>
<cn ...>
<a n="...">...</a>
<m type="{member-type}" value="{member-value}"/>*
</cn>
</ModifyContactResponse>
----------
<GetContactsResponse>
<cn [md="{metadata-change-date}"] [tooManyMembers="1"]>...</cn>*
</GetContactsResponse>
For example:
<GetContactsResponse xmlns="urn:zimbraMail">
<cn id="680" fileAsStr="group1" d="1308612784000" rev="900" l="7">
<a n="nickname">group one</a>
<a n="type">group</a>
<a n="fileAs">8:group1</a>
<m value="[email protected]" type="I"/>
<m value="282" type="C">
<cn id="282" fileAsStr="Smith, John" d="1308547353000" rev="27" l="7">
<a n="lastName">Smith</a>
<a n="email">[email protected]</a>
<a n="workURL">http://www.example.zimbra.com</a>
<a n="company">Zimbra</a>
<a n="workCountry">US</a>
<a n="workState">CA</a>
<a n="workPhone">(408) 123-4567</a>
<a n="firstName">Mark</a>
</cn>
</m>
<m value="uid=user1,ou=people,dc=phoebe,dc=mbp" type="G">
<cn id="2a692f57-1a5b-4542-9f8e-28dfdd0e3f43:260" fileAsStr="Demo User One"
d="1308626790000" rev="22" l="257">
<a n="createTimeStamp">20110620052132Z</a>
<a n="lastName">user1</a>
<a n="email">[email protected]</a>
<a n="zimbraId">b4bf7953-c10f-449e-b7fe-3df48eea36f8</a>
<a n="objectClass">inetOrgPerson</a>
<a n="objectClass">zimbraAccount</a>
<a n="objectClass">amavisAccount</a>
<a n="fullName">Demo User One</a>
<a n="dn">uid=user1,ou=people,dc=phoebe,dc=mbp</a>
<a n="workPhone">+1 650 555 1111</a>
<a n="modifyTimeStamp">20110620052229Z</a>
<a n="fileAs">8:Demo User One</a>
</cn>
</m>
</cn>
</GetContactsResponse>
----------
<ContactActionRequest>
<!-- some actions can be preceeded by a "!" to negate them -->
<action id="{list}" op="move|delete|flag|trash|tag|update" tag="{id}" l="..."/>
</ContactActionRequest>
<ContactActionResponse>
<action id="{list}" op="move|delete|flag|trash|tag|update"/>
</ContactActionResponse>
for op="update", caller can specify any or all of: l="{folder}", tn="{tag-names}",
f="{flags}", color="{color}", <a> attribute list:
----------
<ImportContactsResponse>
<cn ids="{list-of-created-ids} n="{num-imported}"/>
</ImportContactsResponse>
{content-type} = only currently supported content type is "csv"
{folder-id} = optional folder id to import contacts into
TODO: should have an option on import that matches email addresses to existing
contacts, and updates/ignores them.
----------
<ExportContactsResponse>
<content>...</content>
</ExportContactsResponse>
----------
EXAMPLE:
<SearchRequest>
<query>is:unread</query>
</SearchRequest>
EXAMPLE:
<GetConvRequest>
<c id="12345">
<m id=""9845"/>
</c>
</GetConvRequest>
<GetConvResponse>
<c id="12345" tn="foo,tag2" n="2">
<su>Speaking of animals</su>
<m id="123445" f="1" s="1234" d="10002323">
<e p="Dan Karp" a="[email protected]"/>
<fr>This is the fragment</fr>
</m>
<m id="9845" a="1" s="128981" d="10002323">
<e t="f" p="Roland Schemers" a="[email protected]"/>
<e t="t" p="Dan Karp" a="[email protected]"/>
<fr>This is another frag</fr>
<mp part="" ct="multipart/mixed">
<mp part="1" ct="text/plain" body=1">
<content>This is another frag that is part of a bigger
message. blah blah blah</content>
</mp>
<mp part="2" ct="message/rfc822">
<mp part="2.1" ct="multipart/mixed">
<mp part="2.1.1" ct="text/plain" name="README.txt" cd="attachment"
filename="README.txt"/>
<mp part="2.1.2" ct="image/jpeg" name="shot1.jpg" cd="inline"
filename="shot1.jpg"/>
</mp>
</mp>
</mp>
</m>
</c>
</GetConvResponse>
EXAMPLE:
<GetMsgRequest>
<m id="9845"/>
</GetMsgRequest>
<GetMsgResponse>
<m id="9845" a="1" s="128981" d="10002323">
<e t="f" id="1" p="Roland Schemers" a="[email protected]"/>
<e t="t" id="2" p="Dan Karp" a="[email protected]"/>
<su>Speaking of animals</su>
<fr>This is another frag</fr>
<mp part="" ct="multipart/mixed"/>
<mp part="1" ct="text/plain" body="1"/>
<content>This is another frag that is part of a bigger
message. blah blah blah</content>
</mp>
<mp part="2" ct="message/rfc822"/>
<mp part="2.1" ct="multipart/mixed"/>
<mp part="2.1.1" ct="text/plain"/>
<mp part="2.1.2" ct="text/plain" name="README.txt" cd="attachment"
filename="README.txt"/>
<mp part="2.1.3" ct="image/jpeg" name="shot1.jpg" cd="inline"
filename="shot1.jpg"/>
</mp>
</mp>
</mp>
</m>
</GetMsgResponse>
EXAMPLE:
<mail:BrowseRequest xmlns:mail="urn:zimbraMail">
<query>from:roland</query>
<browseBy>attachments</browseBy>
</mail:BrowseRequest>
<mail:BrowseResponse xmlns:mail="urn:zimbraMail">
<bd>application/pdf</bd>
<bd>application/msword</bd>
<bd>application/vnd.ms-powerpoint</bd>
<bd>image/jpeg</bd>
<bd>application/octet-stream</bd>
<bd>text/plain</bd>
<bd>image/gif</bd>
<bd>message/rfc822</bd>
</mail:BrowseResponse>
-----------------------
<NoOpResponse [waitDisallowed="1"]/>
A request that does nothing and always returns nothing. Used to keep a session
alive, and return
any pending notifications.
If "wait" is set, and if the current session allows them, this request
will block until there are new notifications for the client. Note
that the soap envelope must reference an existing session that has
notifications enabled, and the notification sequencing number should
be specified.
-----------------------
<SetCustomMetadataRequest id="{item-id}">
<meta section="{metadata-section-key}">
(<a n="{key}"> {value} </a>)*
</meta>
</SetCustomMetadataRequest>
<SetCustomMetadataResponse id="{item-id}"/>
<GetCustomMetadataRequest id="{item-id}">
<meta section="{metadata-section-key}"/>
</GetCustomMetadataRequest>
<GetCustomMetadataResponse id="{item-id}">
[<meta section="{metadata-section-key}">
(<a n="{key}"> {value} </a>)*
</meta>]
</GetCustomMetadataResponse>
---------------------------
<SetMailboxMetadataRequest>
<meta section="{metadata-section-key}">
(<a n="{key}">{value}</a>)*
</meta>
</SetMailboxMetadataRequest>
<SetMailboxMetadataResponse/>
<ModifyMailboxMetadataRequest>
<meta section="{metadata-section-key}">
(<a n="{key}">{value}</a>)+
</meta>
</ModifyMailboxMetadataRequest>
<ModifyMailboxMetadataResponse/>
<GetMailboxMetadataRequest>
<meta section="{metadata-section-key}"/>
</GetMailboxMetadataRequest>
<GetMailboxMetadataResponse>
<meta section="{metadata-section-key}">
(<a n="{key}">{value}</a>)*
</meta>
</GetMailboxMetadataResponse>
---------------------------
<GetRulesRequest>
<SaveRulesRequest>
---------------------------
<GetFilterRulesRequest/>
<GetFilterRulesResponse>
<filterRules>
<filterRule name="{rule-name}" [active="{0|1}"]>*
<filterTests condition="{allof | anyof"}>
{test}
[test]
...
</filterTests>
[<nestedRule>
<filterTests>...</filterTests>
[<nestedRule>...</nestedRule>]
[<filterActions>...</filterActions>]
</nestedRule>]
[<filterActions>
{action}
[action]
...
</filterActions>]
</filterRule>
</filterRules>
</GetFilterRulesResponse>
<ModifyFilterRulesRequest>
<filterRules> ... </filterRules>
</ModifyFilterRulesRequest>
<ModifyFilterRulesResponse/>
<addressBookTest header="{header-name}"/>
<addressTest [part="{all|localpart|domain}"] stringComparison="{type}"
[caseSensitive="{0|1}"]
header="{comma-separated-header-names}" value="{value}"/>
<attachmentTest/>
<bulkTest/>
<contactRankingTest header="{header-name}"/>
<conversationTest [where="{started|participated}"]/>
<currentDayOfWeekTest value="comma-separated-day-of-week-indices"/>
<currentTimeTest dateComparison="{before|after}" d="time-in-HHmm-format}"/>
<bodyTest [caseSensitive="{0|1}"] value="{value}"/>
<dateTest dateComparison="{before|after}" d="{date}"/>
<facebookTest/>
<flaggedTest flagName="{flagged|read|priority}"/>
<headerExistsTest header="{header-name}"/>
<headerTest header="{comma-separated-header-names}" stringComparison="{type}"
[caseSensitive="{0|1}"] value="{value}"/>
<importanceTest imp="{high|normal|low}"/>
<inviteTest>
<method>{method}</method>+
</inviteTest>
<linkedinTest/>
<listTest/>
<meTest header="{header-name}"/>
<mimeHeaderTest header="{header-name}" stringComparison="{type}"
[caseSensitive="{0|1}"] value="{value}"/>
<sizeTest numberComparison="{over|under}" s="{size}"/>
<socialcastTest/>
<twitterTest/>
<communityRequestsTest/>
<communityContentTest/>
<communityConnectionsTest/>
Actions:
<actionKeep />
<actionDiscard />
<actionFileInto folderPath="{folder-path}" />
<actionTag tagName="{tag-name}" />
<actionFlag flagName="{flagged|read|priority}" />
<actionRedirect a="{email-address}" />
<actionStop />
<actionReply>
<content>{body-template}</content>
</actionReply>
<actionNotify a="email-address" [su="subject-template"] [maxBodySize="{num-
bytes}"] [origHeaders="{comma-separated-header-names}|*"]>
<content>{body-template}</content> ?
</actionNotify>
Each action has an optional "index" attribute which specifies a guaranteed order
for the action elements.
stringComparison values: is, contains, matches
numberComparison values: over, under
dateComparison values: before, after
size values are in bytes (no suffix), kilobytes (50K), megabytes (50M) or gigabytes
(2G)
<dateTest>: date values are are truncated to the day. Hours, minutes, and seconds
are ignored.
index is an integer, used to maintain the order of filter tests and actions.
method values: anyrequest, anyreply, publish, request, reply, add, cancel, refresh,
counter, declinecounter. anyrequest matches publish, request, add, cancel,
declinecounter. anyreply matches reply, refresh, counter. If no methods are
specified, the test returns true for all invites.
<mimeHeaderTest>: behaves just like <headerTest>, but matches headers on
all MIME parts, instead of just the top-level headers.
<currentDayOfWeekTest>: day-of-week-indices - 0=Sunday, 6=Saturday
body-template/subject-template: Can contain variables such as ${SUBJECT}, ${TO}, $
{CC}, etc
(basically ${any-header-name}; case not important), plus ${BODY} (text body of
the message).
origHeaders: Specifies list of headers to be copied from the original message to
the notification message.
Value "*" implies that all headers need to be copied.
<addressTest>: this test is preferred instead of <headerTest> for headers that
contain email addresses. The default
value of the part attribute is "all" which implies comparison against the full
email address.
<communityRequestsTest>, <communityContentTest>, and <communityConnectionsTest> all
check the "X-Zimbra-Community-Notification-Type"
header against predefined groups of values. The groups are:
communityRequestsTest:
bb196c30-fad3-4ad8-a644-2a0187fc5617 - Friendships Requests
3772ef23-6aa0-4a22-9e88-a4313c37ebe6 - Group Membership Request
1b0500d2-c789-421e-a25b-3ab823af53be - Forums Requiring Moderation
communityContentTest:
6a3659db-dec2-477f-981c-ada53603ccbb - Likes
94dc0d37-3a65-43de-915d-d7d62774b576 - Ratings
4876d7ce-b48c-4a08-8cd9-872342c5bdf8 - Blog Post Comment
82e1d0b4-854e-43c9-85d7-dea7d4dec949 - Wiki Page Update
8e627c29-8602-4110-877d-0232e4ea2fd5 - Media Comment
be997a7a-5026-435f-8ea5-4fe3d90a6ba9 - New Media in Owned Gallery
eea4ccbb-6e07-4a6d-9bb6-8b02f060f79c - Forum Thread Awaiting Moderation
Notification
352a702d-2a77-4307-9e9e-c564426e8cc8 - Forum Thread Subscription Notification
0e952633-fa46-448d-b1aa-bb6c60a388fb - Forum Reply Awaiting Moderation Notification
e3df1b21-ac81-4eb3-8ab6-69dc049f5684 - Forum Replies
f8c93cd5-d40e-461d-b13a-b02e92bfcbbf - Forum Thread Verified Answers
communityConnectionsTest:
194d3363-f5a8-43b4-a1bd-92a95f6dd76b - Friendships
1cee0f92-3650-4110-9f0b-69b0e175914d - Mentions
bb196c30-fad3-4ad8-a644-2a0187fc5617 - Group Membership
328e5139-d759-405c-98da-91cd25bcc80c - Group Mentions
Nested Rules:
In addition to the normal set of tests and actions, a filter rule may contain one
or more layers of nested rules. If nested rules are
specified the filter action(s) must be specified on the innermost level. All
conditions are evaluated and if true the innermost action(s) are executed.
Note that as of ZCS 8.5 nested filter rules are supported in the SOAP API but not
in the end user filter preferences UI.
---------------------------
<ApplyFilterRulesRequest>
<filterRules>
<filterRule name="{name}"/>+
</filterRules>
[<m ids="{msg-id-list}"/>]
[<query>{query-string}</query>]
</ApplyFilterRulesRequest>
<ApplyFilterRulesResponse>
<m ids="{msg-id-list}"/>
</ApplyFilterRulesResponse>
Note that redirect actions are ignored when applying filter rules
to existing messages.
--------------------------
<GetOutgoingFilterRulesRequest/>
<GetOutgoingFilterRulesResponse>
...
</GetOutgoingFilterRulesResponse>
<ModifyOutgoingFilterRulesRequest>
...
</ModifyOutgoingFilterRulesRequest>
<ModifyOutgoingFilterRulesResponse/>
<ApplyOutgoingFilterRulesRequest>
...
</ApplyOutgoingFilterRulesRequest>
<ApplyOutgoingFilterRulesResponse>
...
</ApplyOutgoingFilterRulesResponse>
--------------------------
Synchronization:
<GetSpellDictionariesRequest>
<GetSpellDictionariesResponse>
<dictionary>en_US</dictionary>
...
</GetSpellDictionariesResponse>
---------------------------
<CheckSpellingResponse available="0|1">
<misspelled word="chickun"
suggestions="chicken,chocking,chucking,Chicky,checking"/>
</CheckSpellingResponse>
{name} : the optional name of the aspell dictionary that will be used to
check spelling. If not specified, the the dictionary will be either
zimbraPrefSpellDictionary or the account's locale, in that order.
---------------------------
<GetAllLocalesRequest/>
<GetAllLocalesResponse>
<locale id="en_US" name="English (United States)" localName="English (United
States)"/>
...
</GetAllLocalesResponse>
Returns all locales defined in the system. This is the same list returned by
java.util.Locale.getAvailableLocales(), sorted by display name (name attribute).
---------------------------
<GetAvailableLocalesRequest/>
<GetAvailableLocalesResponse>
<locale id="{locale-id}" name="{locale-name-in-preferred-locale}"/>
...
</GetAvailableLocalesResponse>
Returns intersection of all translated locales installed on the server and the list
specified in zimbraAvailableLocale.
The locale list in the response is sorted by display name (name attribute).
---------------------------
<TestDataSourceRequest>
<pop3 host="pop.myisp.com" port="110" connectionType="cleartext|ssl"
username="mylogin" password="mypassword" leaveOnServer="true|false"
[smtpEnabled="0|1" smtpHost="smtp.myisp.com" smtpPort="465"
smtpConnectionType="cleartext|ssl"
smtpAuthRequired="0|1" smtpUsername="mylogin" smtpPassword="mypassword"]/>
or
or
<TestDataSourceRequest>
<pop3 id="{id}" [host="pop.myisp.com"] [port="110"] [connectionType="cleartext|
ssl"]
[username="mylogin"] [password="mypassword"]/>
or
<TestDataSourceResponse>
<pop3 success="0|1" [error="Error message"]/>
or
<imap success="0|1" [error="Error message"]/>
</TestDataSourceResponse>
Tests the connection to the specified data source. Does not modify
the data source or import data. If the id is specified, uses an existing
data source. Any values specified in the request are used in the test
instead of the saved values.
---------------------------
===================
emailAddress="[email protected]"
useAddressForForwardReply="false"
defaultSignature="95915d7a-1809-4a73-a50f-c465214fae62"
fromDisplay="changed-from-display"
replyToAddress="[email protected]"
replyToDisplay="changed-replyto-display"/>
==================
<CreateDataSourceRequest/>
<pop3 name="My POP3 Account" isEnabled="0|1" host="pop.myisp.com" port="110"
connectionType="cleartext|ssl" username="mylogin" password="mypassword"
l="{folder-id}"
[smtpEnabled="0|1" smtpHost="smtp.myisp.com" smtpPort="465"
smtpConnectionType="cleartext|ssl"
smtpAuthRequired="0|1" smtpUsername="mylogin" smtpPassword="mypassword"]
leaveOnServer="0|1" [pollingInterval="10m"]
[emailAddress="{email-address}"]
[useAddressForForwardReply="0|1"]
[defaultSignature="{default-signature-id}"]
[forwardReplySignature="{forward-reply-signature-id}"]
[fromDisplay="{from-display}"]
[replyToAddress="{replyto-address}"]
[replyToDisplay="{replyto-display}"]/>
or
<CreateDataSourceResponse>
<pop3 id="{id}"/>
</CreateDataSourceResponse>
Creates a data source that imports mail items into the specified folder via
the POP3 or IMAP protocol. Only one data source is allowed per request.
If SMTP is being enabled for the mail data source (IMAP/POP3) and SMTP settings are
being specified, the
emailAddress attr must also be specified.
---------------------------
<GetDataSourcesRequest/>
<GetDataSourcesResponse>
*[<pop3 id="{id}" name="My POP3 Account" isEnabled="0|1" host="pop3.myisp.com"
port="110"
username="mylogin" l="{folder-id}" leaveOnServer="0|1" [pollingInterval="10m"]
[smtpEnabled="0|1" smtpHost="smtp.myisp.com" smtpPort="465"
smtpConnectionType="cleartext|ssl"
smtpAuthRequired="0|1" smtpUsername="mylogin" smtpPassword="mypassword"]
[emailAddress="{email-address}"]
[useAddressForForwardReply="0|1"]
[defaultSignature="{default-signature-id}"]
[forwardReplySignature="{forward-reply-signature-id}"]
[fromDisplay="{from-display}"]
[replyToAddress="{replyto-address}"]
[replyToDisplay="{replyto-display}"]
[failingSince="{timestamp}">]
[<lastError>{error message}</lastError>]
</pop3>]
*[<imap name="My IMAP Account" isEnabled="0|1" host="imap.myisp.com" port="143"
connectionType="cleartext|ssl" username="mylogin" l="{folder-id}"
[pollingInterval="10m"]
[smtpEnabled="0|1" smtpHost="smtp.myisp.com" smtpPort="465"
smtpConnectionType="cleartext|ssl"
smtpAuthRequired="0|1" smtpUsername="mylogin" smtpPassword="mypassword"]
[emailAddress="{email-address}"]
[useAddressForForwardReply="0|1"]
[defaultSignature="{default-signature-id}"]
[forwardReplySignature="{forward-reply-signature-id}"]
[fromDisplay="{from-display}"]
[replyToAddress="{replyto-address}"]
[replyToDisplay="{replyto-display}"]>
[failingSince="{timestamp}">]
[<lastError>{error message}</lastError>]
</imap>]
...
</GetDataSourcesResponse>
Returns all data sources defined for the given mailbox. For each data source,
every attribute value is returned except password.
lastError: the error message from the most recent sync for this data source.
This element is not returned if the last sync was successful.
failingSince: if the most recent sync(s) failed, this attribute specifies
the timestamp of the first failure. This attribute is not returned
if the last sync was successful.
--------------------------
Note: OAuthToken is temporary and it expires after a certain time interval
Client can refresh the OAuthToken in two ways
1. Refresh and update OAuthToken periodically
2. Refresh and update OAuthToken if the client gets the response as - error="
Invalid credentials (Failure)"
---------------------------
---------------------------
<ModifyDataSourceRequest>
*[<pop3 id="{id}" [name="My POP3 Account"] [isEnabled="0|1"]
[host="pop3.myisp.com"]
[port="110"] [connectionType="cleartext|ssl"] [username="mylogin"]
[smtpEnabled="0|1" smtpHost="smtp.myisp.com" smtpPort="465"
smtpConnectionType="cleartext|ssl"
smtpAuthRequired="0|1" smtpUsername="mylogin" smtpPassword="mypassword"]
[password="mypassword"] [l="{folder-id}"] [leaveOnServer="0|1"]
[pollingInterval="10m"]
[emailAddress="{email-address}"]
[useAddressForForwardReply="0|1"]
[defaultSignature="{default-signature-id}"]
[forwardReplySignature="{forward-reply-signature-id}"]
[fromDisplay="{from-display}"]
[replyToAddress="{replyto-address}"]
[replyToDisplay="{replyto-display}"]/>
*[<imap name="My IMAP Account" isEnabled="0|1" host="imap.myisp.com" port="143"
connectionType="cleartext|ssl"
username="mylogin" [password="mypassword"] l="{folder-id}"
[oauthToken="myOAuthToken" clientId="clientId" clientSecret="clientSecret"
refreshToken="refreshToken" refreshTokenUrl="refreshTokenUrl"]
[smtpEnabled="0|1" smtpHost="smtp.myisp.com" smtpPort="465"
smtpConnectionType="cleartext|ssl"
smtpAuthRequired="0|1" smtpUsername="mylogin" smtpPassword="mypassword"]
[pollingInterval="10m"]
[emailAddress="{email-address}"]
[useAddressForForwardReply="0|1"]
[defaultSignature="{default-signature-id}"]
[forwardReplySignature="{forward-reply-signature-id}"]
[fromDisplay="{from-display}"]
[replyToAddress="{replyto-address}"]
[replyToDisplay="{replyto-display}"]
[test="0|1"]/>
</ModifyDataSourceRequest>
<ModifyDataSourceResponse/>
Changes attributes of the given data source. Only the attributes specified in the
request
are modified. If the username, host or leaveOnServer settings are modified, the
server
wipes out saved state for this data source. As a result, any previously downloaded
messages that are still stored on the remote server will be downloaded again.
---------------------------
<DeleteDataSourceRequest>
*[<dsrc [id="{data-source-id}" | name="{data-source-name}"]/>]
*[<pop3 [id="{data-source-id}" | name="{data-source-name}"]/>]
*[<imap [id="{data-source-id}" | name="{data-source-name}"]/>]
...
</DeleteDataSourceRequest>
<DeleteDataSourceResponse/>
Deletes the given data sources. The name or id of each data source must
be specified.
---------------------------
<ImportDataRequest>
*[<dsrc id="{id}"/>]
*[<pop3 id="{id}"/>]
*[<imap id="{id}"/>]
...
</ImportDataRequest>
<ImportDataResponse/>
Triggers the specified data sources to kick off their import processes. Data
import runs
asynchronously, so the response immediately returns. Status of an import can be
queried
via the <GetImportStatusRequest> message. If the server receives an
<ImportDataRequest> while an import is already running for a given data source,
the second request is ignored.
---------------------------
<GetImportStatusRequest/>
<GetImportStatusResponse>
*[<pop3 id="{id}" isRunning="0|1" [success="0|1"] [error="Error message"]/>]
*[<imap id="{id}" isRunning="0|1" [success="0|1"] [error="Error message"]/>]
...
</GetImportStatusResponse>
Returns current status for all data sources. Status values for a data source are
reinitialized when either (a) another import process is started or (b) when the
server is restarted. If import has not run yet, the success and error attributes
are not specified.
isRunning: Whether data is currently being imported from this data source.
success: Whether the last import completed successfully.
error: If the last import failed, the error message that was returned.
---------------------------
WaitSet: scalable mechanism for listening for changes to one or more accounts
<CreateWaitSetRequest>
<CreateWaitSetResponse>
<WaitSetRequest>
<WaitSetResponse>
<DestroyWaitSet>
<DestroyWaitSetResponse>
---------------------------
<GetPermissionRequest>
<!-- get only the permissions for the specified rights -->
[<ace right="{right1}"/>
<ace right="{right2}"/>]
</GetPermissionRequest>
If no <ace> elements are provided, all ACEs are returned in the response.
If <ace> elements are provided, only those ACEs with specified rights are returned
in the response.
<GetPermissionResponse>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" zid="{zimbra-id}"
[d="{grantee-name}"] [pw="{password}"] [key="{accesskey}"]/>*
</GetPermissionResponse>
{deny} = 1 | 0(default)
if a right is specifically denied
---------------------------
<GrantPermissionRequest>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" [zid="{zimbra-id}"]
[d="{grantee-name}"] [pw="{password}"] [key="{accesskey}"]/>+
</GrantPermissionRequest>
If gt is:
usr - either zid or d is required.
grp - either zid or d is required.
all - zid, d, pw are ignored
gst - zid is ignored, d is required, pw is optional
key - zid is ignored, d is required
pub - zid, d, pw are ignored
If gt == key:
- if key is given, server will use that as the access key for this grant
- if key is not given, server will generate an access key
<GrantPermissionResponse>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" zid="{zimbra-id}"
[d="{grantee-name}"] [pw="{password}"] [key="{accesskey}"]/>*
</GrantPermissionResponse>
---------------------------
<RevokePermissionRequest>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" [zid="{zimbra-id}"]
[d="{grantee-name}"]/>*
</RevokePermissionRequest>
<RevokePermissionResponse>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" zid="{zimbra-id}"
[d="{grantee-name}"] [pw="{password}"] [key="{accesskey}"]/>*
</RevokePermissionResponse>
---------------------------
<CheckPermissionRequest>
<target type="{target-type}" by="id|name">...</target>
<right>...</right>+
</CheckPermissionRequest>
e.g.
With user1's auth token, the following checks if user1 can invite user2 and
view user2's free/busy.
<CheckPermissionRequest>
<target type="account" by="name">[email protected]</target>
<right>invite</right>
<right>viewFreeBusy</right>
</CheckPermissionRequest>
<CheckPermissionResponse allow="{1|0}">
<right allow="{1|0}">invite</right>
<right allow="{1|0}">viewFreeBusy</right>
</CheckPermissionResponse>
allow = 1 | 0
1: the authed user has the right on the target
0: the authed user does not have the right on the target
In CheckPermissionResponse, it is the AND result of each individual result
In each <right> element, it is the result for that right.
---------------------------
<GetRightsRequest>
<!-- get only grants for the specified rights -->
[<ace right="{right1}"/>
<ace right="{right2}"/>]
</GetRightsRequest>
If no <ace> elements are provided, all ACEs are returned in the response.
If <ace> elements are provided, only those ACEs with specified rights are returned
in the response.
<GetRightsResponse>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" zid="{zimbra-id}"
[d="{grantee-name}"] [pw="{password}"] [key="{accesskey}"]/>*
</GetRightsResponse>
{deny} = 1 | 0(default)
if a right is specifically denied
---------------------------
<GrantRightsRequest>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" [zid="{zimbra-id}"]
[d="{grantee-name}"] [pw="{password}"] [key="{accesskey}"]
[chkgt="{checkGranteeType}"]/>+
</GrantRightsRequest>
If gt is:
usr - either zid or d is required.
grp - either zid or d is required.
all - zid, d, pw are ignored
gst - zid is ignored, d is required, pw is optional
key - zid is ignored, d is required
pub - zid, d, pw are ignored
If gt == key:
- if key is given, server will use that as the access key for this grant
- if key is not given, server will generate an access key
<GrantRightsResponse>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" zid="{zimbra-id}"
[d="{grantee-name}"] [pw="{password}"] [key="{accesskey}"]/>*
</GrantRightsResponse>
---------------------------
<RevokeRightsRequest>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" [zid="{zimbra-id}"]
[d="{grantee-name}"]/>*
</RevokeRightsRequest>
<RevokeRightsResponse>
<ace right="{right}" [deny="{deny}"] gt="{grantee-type}" zid="{zimbra-id}"
[d="{grantee-name}"] [pw="{password}"] [key="{accesskey}"]/>*
</RevokeRightsResponse>
---------------------------
<DiscoverRightsRequest>
<right>...</right>+
</DiscoverRightsRequest>
Return all targets of the specified rights applicable to the requested account.
Notes:
1. This call only discovers grants granted on the designated target type of the
specified rights.
It does not return grants granted on target types the rights can inherit from.
3. For all other rights, name attribute is always returned on <target> elements,
no
<e a="{email-address}"/> will be returned. name attribute contains the
entry's
primary name.
<DiscoverRightsResponse>
<targets right="...">
[<target type="{target-type}" id="..." [name="..."] [d=".."]>
[<email addr="{email-address}"/>+]
</target>+]
</targets>+
</DiscoverRightsResponse>
e.g.
<DiscoverRightsRequest>
<right>sendAs</right>
<right>sendAsDistList</right>
<right>viewFreeBusy</right>
</DiscoverRightsRequest>
<DiscoverRightsResponse>
<targets right="sendAs">
<target type="account" id="...">
<e a="[email protected]"/>
<e a="[email protected]"/>
</target>
<target type="account" id="...">
<e a="[email protected]"/>
</target>
</targets>
<targets right="sendAsDistList">
<target type="dl" id="...">
<e a="[email protected]"/>
<e a="[email protected]"/>
</target>
<target type="dl" id="...">
<e a="[email protected]"/>
<e a="[email protected]"/>
</target>
</targets>
<targets right="viewFreeBusy">
<target type="account" id="..." name="[email protected]">
</targets>
</DiscoverRightsResponse>
---------------------------
<CheckRightsRequest>
<target type="{target-type}" by="id|name" key="{key}">
<right>...</right>+
</target>+
</CheckRightsRequest>
<CheckRightsResponse>
<target type="{target-type}" by="id|name" key="{key}" allow="{1|0}">
<right allow="{1|0}">...</right>+
</target>+
</CheckRightsResponse>
allow = 1 | 0
1: the authed user has the right on the target
0: the authed user does not have the right on the target
For the allow="1|0" on each <target>, it is the AND value of all requetsed
rights
for the target.
---------------------------
<GetVersionInfoRequest/>
<GetVersionInfoResponse>
<info version="{version-string}" release="{release-string}" buildDate="{YYYYMMDD-
hhmm}" buildHost="{host-name}"/>
</GetVersionInfoResponse>
---------------------------
<GetWhiteBlackListRequest/>
<GetWhiteBlackListResponse>
<whiteList>
<addr>...</addr>+
</whiteList>
<blackList>
<addr>...</addr>+
</blackList>
</GetWhiteBlackListResponse>
----------------------------
<ModifyWhiteBlackListRequest>
[<whiteList>
<addr [op="{op}"]>...</addr>+
</whiteList>]
[<blackList>
<addr [op="{op}"]>...</addr>+
</blackList>]
</ModifyWhiteBlackListRequest>
Note:
If no <addr> is present in a list, it means to remove all addresses
in the list.
{op} = + | -
+ : add, ignored if the value already exists
- : remove, ignored if the value does not exist
if not present, replace the entire list with provided values.
e.g.
1. replace the entire white list with "foo", "bar".
<whiteList>
<addr>foo</addr>
<addr>bar</addr>
</whiteList>
<ModifyWhiteBlackListResponse/>
----------------------------
<GetShareInfoRequest [includeSelf="1|0"]>
[<grantee type="{grantee_type}" [id="{grantee-id}"] [name="{grantee-name}"]/>]
[<owner by="{owner-by}">...</owner>]
</GetShareInfoRequest>
{owner-by} = name | id
Note: In order to defend against harvest attacks this SOAP call
will
return "no shares" instead of error when an invalid user name/id
is used.
Notes:
- if <owner> is *not* specified server will search the LDAP for published shares
(zimbraSharedItem
account attribute) accessible to the authed user.
- if <owner> *is* specified, server will iterate through the owner's mailbox to
discover all
shares applicable to the authed user, instead of looking at any of the published
share info.
All applicable shares will be returned, including any shares that are:
- shared with the account directly
- shared with any group(and parent groups) the account belongs. (*is*
supported)
- shared with the cos assigned to the account. (*is*
supported)
- shared with the domain this account is in. (*is*
supported)
- shared with all authed users (i.e. all Zimbra users) (*is*
supported)
- shared with the public (*is*
supported)
e.g.
1. What folders are shared with any of the groups I belong to?
3. Show me all folders shared directly with me and with any entry I can inherit
shares from:
<GetShareInfoRequest>
</GetShareInfoRequest>
<GetShareInfoResponse>
[<share ownerId="{owner-id}" ownerEmail={owner-email} [ownerName="{owner-
display-name}"]
folderId="{folder-id}" folderPath="{fully-qualified-path}"
view="{default-type}" [mid="{mountpoint-id}"] rights="{rights}"
granteeType="{grantee-type}" granteeId="{grantee-id}"
granteeName="{grantee-name}" [granteeDisplayName="{grantee-display-name}">]]+
</GetShareInfoResponse>
----------------------------
<SendShareNotificationRequest [action="edit|revoke|expire"]>
<item id="{item-id}"/>
[<e a="{email-addr}"/>]+
[<notes>{notes}</notes>]
</SendShareNotificationRequest>
The client can list the recipient email addresses for the share, along
with the itemId of the item being shared.
<SendShareNotificationResponse/>
----------------------------
<GetEffectiveFolderPermsRequest>
<folder l="{folder-id}"/>]
</GetEffectiveFolderPermsRequest>
<GetEffectiveFolderPermsResponse>
<folder perm="{permissions}"/>
</GetEffectiveFolderPermsResponse>
----------------------------
<RankingActionRequest>
<action op="reset|delete" [email="{email-address}"] />
</RankingActionRequest>
<RankingActionResponse/>
----------------------------
<ModifyZimletPrefsRequest>
<zimlet name="{name}" presence="{enabled|disabled}"/>+
</ModifyZimletPrefsRequest>
<ModifyZimletPrefsResponse>
<zimlet name="{name}" presence="{enabled|disabled}"/>+
</ModifyZimletPrefsResponse>
----------------------------
<GenerateUUIDRequest/>
<GenerateUUIDResponse>{generated UUID}</GenerateUUIDResponse>
Ajax client can use this request to ask the server for help in generating a proper,
globally unique UUID.
-----------------------------
Notes:
limit - the number of members to return (0 is default and means all)
offset - the starting offset (0, 25, etc)
-----------------------------
<PurgeRevisionRequest>
<revision id="{item-id}" ver="{revision}" [includeOlderRevisions="true|false"]/>
</PurgeRevisionRequest>
<PurgeRevisionResponse/>
When includeOlderRevisions is set to true, the server will purge all the
old revisions inclusive of the revision specified in the request.
-----------------------------
<SendVerificationCodeRequest a="{device-email-address}"/>
<SendVerificationCodeResponse/>
<VerifyCodeResponse success="0|1">
Notes: Request for validating the verification code sent to a device. After
successful validation the server
sets device email address as the value of zimbraCalendarReminderDeviceEmail account
attribute.
<InvalidateReminderDeviceRequest a="{device-email-address}"/>
<InvalidateReminderDeviceResponse/>
-----------------------------
<AddCommentRequest>
<comment parentId="{item-id-of-parent}" text="{comment-text}"/>
</AddCommentRequest>
<AddCommentResponse>
<comment id="{item-id}"/>
</AddCommentResponse>
-----------------------------
<GetCommentsRequest>
<comment parentId="{item-id-of-parent}"/>
</GetCommentsRequest>
<GetCommentsResponse>
[<user id="{account-id}" name="{display-name}" email="{email-address}"/>]*
[<comment id="{item-id}" parentId="{item-id-of-parent}" email="{creator-email-
address}" d="{timestamp}" text="{comment-text}"/>]+
<GetCommentsResponse>
----------------------------
<GetShareNotificationsRequest/>
<GetShareNotificationsResponse>
[<share id="{notification-item-id}" d="{date}" status="new|seen">
<grantor id="{zimbra-id}" email="{email-address}" name="{display-name}"/>
<link id="{shared-item-id}" name="{item-name}" view="{item-type}"
perm="{permissions-granted}"/>
</share>]*
[<revoke id="{notification-item-id}" d="{date}" [expire="1"]>
<grantor id="{zimbra-id}" email="{email-address}" name="{display-name}"/>
<link id="{revoked-item-id}" name="{item-name}" view="{item-type}"/>
</revoke>]*
</GetShareNotificationsResponse>
There will be at most one <share/> or <revoke/> block for each shared item
regardless of how many times the share notification was re-sent by the
owner. <revoke/> indicates the previous share is no longer available
to the user and should be hidden or removed from the UI. If "expire=1" is set
on <revoke/> it indicates that the share expired and was automatically revoked
by the system.
-----------------------------
<GetSystemRetentionPolicyRequest/>
<GetSystemRetentionPolicyResponse>
<retentionPolicy>
<keep>
<policy id="{id}" name="{name}" type="system" lifetime="{duration}"/>*
</keep>
<purge>
<policy id="{id}" name="{name}" type="system" lifetime="{duration}"/>*
</purge>
</retentionPolicy>
</GetSystemRetentionPolicyResponse>
-----------------------------
<CreateDistributionListRequest [dynamic="1|0"]>
<name>...</name>
<a n="...">...</a>+
</CreateDistributionListRequest>
<CreateDistributionListResponse>
<dl name="{name}" id="{id}" ref="{dl-ldap-dn}">
<a n="...">...</a>+
</dl>
</CreateDistributionListResponse>
Notes:
authed account must have the privilege to create dist lists in the domain
-----------------------------
<GetDistributionListResponse >
<dl name="{name}" id="{id}" dynamic="1|0" [isOwner="1"] [isMember="1"]>
<a n="...">...</a>+
[<owners>
<owner type="{grantee-type}" id="{owner-id}" name="{owner-name}"/>+
</owners>]
[<rights>
[<right right="{right}">
<grantee type={grantee-type} [id="{grantee-id}"] [name="grantee-name"]/>
</right>+]
</rights>]
</dl>
</GetDistributionListResponse>
Notes:
If the authed account is one of the list owners, all (requested) attributes of
the DL
are returned in the response. Otherwise only attributes visible and useful to
non-owners are returned.
Specified <rights> are returned only if the authed account is one of the list
owners.
Only grants on this group entry is returned, inherited grants on domain or
globalgrant
are not returned.
-----------------------------
<DistributionListActionRequest>
<dl by="id|name">...</dl>
<action op="{op}">
[<a n="...">...</a>+]
[<newName>{new-DL-name}</newName>]
[<owner type={grantee-type} by="name|id}">{name-or-id}</owner>+]
[<right right="{right}">
<grantee type={grantee-type} by="name|id}">{name-or-id}</grantee>+
</right>+]
[<dlm>{member}</dlm>+]
[<subsReq op="subscribe/unsubscribe" [bccOwners="1|0"]>{member-
email}</subsReq>]
</action>
<DistributionListActionRequest>
Notes:
authed account must be one of the list owners
grantee-type:
usr - a Zimbra internal user
grp - a Zimbra internal group
egr - an external AD group
all - all Zimbra users (by and {name-or-id} are ignored)
pub - public (by and {name-or-id} are ignored)
email - an email address. Server will lookup in directory and determine the
actual grantee
Note:
For owners/rights, only grants on the group itself will be
modified, grants on domain and globalgrant (from which the right can be
inherited)
will not be touched. Only admins can modify grants on domains and
globalgrant,
owners of groups can only modify grants on the group entry.
<DistributionListActionResponse/>
-----------------------------
<SubscribeDistributionListRequest op="subscribe/unsubscribe">
<dl by="id|name">...</dl>
</SubscribeDistributionListRequest>
<SubscribeDistributionListResponse status={status}/>
-----------------------------
<GetAccountDistributionListsResponse>
<dl name="{name}" id="{id}" ref="{dl-ldap-dn}" [d="{display-name}"] [via="{via-
dl-name}] [isOwner="1|0"] [isMember="1|0"]>
[<a n="...">...</a>+]
</dl>+
</GetAccountDistributionListsResponse>
{member-of} = all: needs all groups the user is a direct or indirect member of.
none: do not need groups the user is a member of.
directOnly (default): needs groups the account is a direct member of.
{attrs} = comma-separated attributes to return. Note: non-owner user can see only
certain
attributes of a group. If a specified attribute is not visible to the
user,
it will not be returned.
-----------------------------
GetOAuthConsumerRequest:
This is OAuth related API used for fetching details of OAuth consumers/apps for an
account.
Response for this API include access token(this acts as a key), application name,
device information, approved on date.
```
<GetOAuthConsumersRequest xmlns="urn:zimbraAccount"/>
<GetOAuthConsumersResponse xmlns="urn:zimbraAccount">
<OauthConsumer approvedOn="{approved-on}" appName="{name-of-consumer}"
accessToken="{access-token}" device="{device-name}"/>
<OauthConsumer .../>
....
</GetOAuthConsumersResponse>
```
-----------------------------
RevokeOAuthConsumerRequest:
This is OAuth related API used for revoking access for an OAuth consumer.
<RevokeOAuthConsumerRequest
accessToken="9230ae1e4828b108e7696f66e2dc3c80"
xmlns="urn:zimbraAccount"/>
```
<RevokeOAuthConsumerResponse xmlns="urn:zimbraAccount"/>```