Revision as of 20:38, 15 March 2011 by Glenno (talk | contribs) (Deciphering zmstat charts)

Attention.png - This article is NOT official Zimbra documentation. It is a user contribution and may include unsupported customizations, references, suggestions, or information.

Reindexing all mailboxes

To re-index all mailboxes for domain

% for i in `zmprov -l gaa`; do echo "rim $i start" >> /tmp/rim_start.txt; done
% zmprov -f /tmp/rim_start.txt

To check re-index status of all mailboxes on

% for i in `zmprov -l gaa`; do echo "rim $i status">>   /tmp/rim_status.txt; done
% zmprov -f /tmp/rim_status.txt

To cancel any in-progress indexing jobs for

 % for i in `zmprov -l gaa`; do echo "rim $i cancel">>   /tmp/rim_cancel.txt; done
 % zmprov -f /tmp/rim_cancel.txt

Add latency to localhost

To simulate a far away server, add RTT time to the localhost device. For example if we add 100 milliseconds (which then makes 200ms ping time to localhost):

$ tc qdisc add dev lo root handle 1:0 netem delay 100msec

Restore it back to normal again with:

$ tc qdisc del dev lo root


Monitoring file access

An issue came up where /opt/zimbra/log/ was being deleted in a RHCS environment, causing the cluster to fail over. It was unknown how or why clamd.log was deleted. To monitor access to the file, the linux audit daemon was used. This is installed and running in default RHEL5 installations.

# service auditd status
Monitor all syscall() functions:
# auditctl -w /opt/zimbra/log/ -S -k clamd-pid
# cat /opt/zimbra/log/
# ausearch -k clamd-pid

ausearch should return something like:
time->Tue Dec  7 11:56:24 2010
type=PATH msg=audit(1291751784.798:18499): item=0 name="" inode=2361424 dev=fd:00 mode=0100644 ouid=0 ogid=0 rdev=00:00
type=CWD msg=audit(1291751784.798:18499):  cwd="/opt/zimbra/log"
type=SYSCALL msg=audit(1291751784.798:18499): arch=c000003e syscall=2 success=yes exit=3 a0=7fff50968694 a1=0 a2=7fff509676a0 a3=2
   items=1 ppid=24532 pid=29341 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 ses=3053 comm="cat" exe="/bin/cat" key="clamd-pid"

Wait for the file to be deleted and run ausearch again:
# ausearch -k clamd-pid

time->Tue Dec  7 11:47:14 2010
type=PATH msg=audit(1291751234.987:18483): item=1 name="" inode=2361434 dev=fd:00 mode=0100644 ouid=0 ogid=0 rdev=00:00
type=PATH msg=audit(1291751234.987:18483): item=0  name="/root" inode=2359297 dev=fd:00 mode=040750 ouid=0 ogid=0 rdev=00:00
type=CWD msg=audit(1291751234.987:18483):  cwd="/opt/zimbra/log"
type=SYSCALL msg=audit(1291751234.987:18483): arch=c000003e syscall=87 success=yes exit=0 a0=7fff53607696 a1=1 a2=2 a3=1ffcab80
    items=2 ppid=24532 pid=29291 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 ses=3053 comm="rm" exe="/bin/rm" key="clamd-pid"

To stop monitoring the file:
# auditctl -D -k clamd-pid

Restrict authenticated users to send email from account or aliases

By default, when users authenticate to postfix via SASL, they can set the FROM: header to any address they choose, allowing spoofing. The instructions below outline how to configure postfix to restrict a sender's FROM address header to their Zimbra primary email or any aliases on the account.

  1. The first part is to add one of "reject_sender_login_mismatch" or "reject_authenticated_sender_login_mismatch" to postfix's smtpd_sender_restrictions.
    % postconf -e smtpd_sender_restrictions=permit_mynetworks,reject_sender_login_mismatch
    % postconf -e smtpd_sender_restrictions=permit_mynetworks,reject_sender_login_mismatch
  2. Having that work depends on setting the smtpd_sender_login_maps, which is empty by default (and leaving it empty after setting reject_*sender_login_mismatch will prevent anyone from being able to send mail).
    1. If your users do not have account aliases, i.e. if you expect valid users to only send from and perform smtp authentication using their primary account name (shown in the zimbraMailDeliveryAddress attribute on the account), then it will be OK to use the existing virtual mailbox maps. Use the single quotes as shown in the command below to prevent the command shell from parsing the variable name.
       % postconf -e smtpd_sender_login_maps='$virtual_mailbox_maps'
    2. If you expect valid users to potentially use account aliases, or if they might be allowed to send mail from additional addresses (shown in the zimbraAllowFromAddress account attribute), it will be necessary to create a new ldap lookup file. The easiest way is to start with a copy of the file referenced above.
      % cp ~/conf/ ~/conf/
      Edit the new file and change the query_filter and result_attribute lines to match these:
      query_filter = (&(|(zimbraMailDeliveryAddress=%s)(mail=%s)(zimbraAllowFromAddress=%s))(zimbraMailStatus=enabled))
      result_attribute = zimbraMailDeliveryAddress,mail,zimbraAllowFromAddress
      Then set postfix's smtpd_sender_login_maps to reference the new file for lookups.
      % postconf -e smtpd_sender_login_maps=proxy:ldap:/opt/zimbra/conf/
  3. If you configure smtpd_sender_login_maps to use a new file like this, it will also be necessary to update proxy_read_maps. Run this first to get the current setting; I'm not showing it here because it's a few lines long.
    % postconf proxy_read_maps
    Then modify it to contain everything that was there before plus a reference to smtpd_sender_login_maps. Again, make sure to use the single quotes to prevent the shell from trying to expand postfix's variables.
    % postconf -e proxy_read_maps='...previous-proxy_read_maps-content... $smtpd_sender_login_maps'
  4. Then you'll need postfix to reload its configuration.
    % postfix reload

At this point it should be ready. Note that some or all of these changes will be reverted by a ZCS upgrade. Bug 11258 is on file to manage this functionality in ZCS configuration which should reduce the configuration complexity and allow the configuration to be preserved during upgrades.

For additional reference, here's a link to the postfix documentation with more information about the postfix configuration parameters.

Fresh sync of LDAP replica

% zmcontrol stop
% ps wwaux|grep slap   # verify ldap is stopped
% mkdir /tmp/ldap_bak
% cp -arp /opt/zimbra/data/ldap/hdb/db/ /tmp/ldap_bak/
% rm -rf /opt/zimbra/data/ldap/hdb/db/*
% cp /tmp/ldap_bak/db/DB_CONFIG /opt/zimbra/data/ldap/hdb/db/
% zmcontrol start

Check if LDAP replica is in sync with master

%/opt/zimbra/bin/ldapsearch -LLL -H <MasterHost name>  -x  -s base contextCSN && /opt/zimbra/bin/ldapsearch -LLL -H <Slave host name> -x  -s base contextCSN

Consolidating one HSM volume to another

Supposing you have multiple HSM volumes, and want to migrate the data from an inactive volume to another (allowing you to remove the inactive volume). There isn't a standard Zimbra procedure for this scenario. However, it is possible to move the blobs from one volume to another. You need to be sure Zimbra services are completely stopped during the process, or you risk data loss. It would be wise to firewall off client access (http/s, imap, smtp, etc.) until you've verified the migration worked.

Assuming the volume you want to retire is /opt/zimbra/store3 and the volume you want to move data to is /opt/zimbra/store2:

1. Get info from zmvolume:

Store 2:
path: /opt/zimbra/store2
Volume id: 2

Store 3:
path: /opt/zimbra/store3
Volume id: 3
(ensure current status isn't true)

2. Full backup in case restore is necessary:

% zmbackup -f -a all -sync

3. Stop Zimbra, backup MySQL, backup file listing of blobs, move blobs:

% zmcontrol stop
% mkdir /opt/zimbra/db/data.bak
% cp -a /opt/zimbra/db/data/* /opt/zimbra/db/data.bak/
% find /opt/zimbra/store3/ -name '*.msg' -ls| sed 's/.\+\/opt\//@/' > /tmp/store3-blobs.txt
% cp -a /opt/zimbra/store3/* /opt/zimbra/store2/

4. Update blob pointers in MySQL:

% mysql.server start

Test the following script, and run again by removing the echo in front of "mysql" if the output looks good:

for i in /opt/zimbra/db/data/mboxgroup*;
 x=`echo $i | sed 's/.\+\///'`;
 echo "Updating $i...";
 echo mysql $x -e "UPDATE mail_item SET volume_id=$store2id WHERE volume_id=$store3id;"

5. Verify migration:

Start Zimbra and check that mailboxes can retrieve the moved messages (should not get NO_SUCH_BLOB errors when clicking on messages that were migrated).

If all looks good, remove store3 via zmvolume and then archive the directory (if you're confident everything is fine, delete). Same goes for /opt/zimbra/db/data.bak.

If things aren't working, stopping all services and restoring the old MySQL tables from /opt/zimbra/db/data.bak should work. You can use /tmp/store3-blobs.txt to know which blobs to clean out of /opt/zimbra/store2.

Output in mailbox.log when mailboxd stops and starts


2010-08-31 16:00:06,751 INFO  [Shutdown] [] log - Shutdown hook executing
2010-08-31 16:00:07,274 INFO  [Shutdown] [] StatsImageServlet - Servlet StatsImageServlet shutting down
2010-08-31 16:00:07,275 INFO  [Shutdown] [] FileUploadServlet - Servlet FileUploadServlet shutting down
2010-08-31 16:00:07,277 INFO  [Shutdown] [] PublicICalServlet - Servlet PublicICalServlet shutting down
2010-08-31 16:00:07,277 INFO  [Shutdown] [] account - Servlet PreAuthServlet shutting down
2010-08-31 16:00:07,277 INFO  [Shutdown] [] mailbox - Servlet UserServlet shutting down
2010-08-31 16:00:07,277 INFO  [Shutdown] [] ContentServlet - Servlet ContentServlet shutting down
2010-08-31 16:00:07,277 INFO  [Shutdown] [] soap - Servlet AdminServlet shutting down
2010-08-31 16:00:07,278 INFO  [Shutdown] [] TcpServer/7025 - LmtpServer initiating shutdown
2010-08-31 16:00:07,419 INFO  [Shutdown] [] TcpServer/110 - Pop3Server initiating shutdown
2010-08-31 16:00:07,420 INFO  [Pop3Server] [] TcpServer/110 - finished accept loop
2010-08-31 16:00:07,521 INFO  [Shutdown] [] TcpServer/110 - Pop3Server shutting down idle thread pool
2010-08-31 16:00:07,521 INFO  [Shutdown] [] TcpServer/995 - Pop3SSLServer initiating shutdown
2010-08-31 16:00:07,522 INFO  [Pop3SSLServer] [] TcpServer/995 - finished accept loop
2010-08-31 16:00:07,720 INFO  [Shutdown] [] TcpServer/995 - Pop3SSLServer shutting down idle thread pool
2010-08-31 16:00:07,721 INFO  [Shutdown] [] TcpServer/143 - ImapServer initiating shutdown
2010-08-31 16:00:07,721 INFO  [ImapServer] [] TcpServer/143 - finished accept loop
2010-08-31 16:00:07,816 INFO  [Shutdown] [] TcpServer/143 - ImapServer shutting down idle thread pool
2010-08-31 16:00:07,816 INFO  [Shutdown] [] TcpServer/993 - ImapSSLServer initiating shutdown
2010-08-31 16:00:07,816 INFO  [ImapSSLServer] [] TcpServer/993 - finished accept loop
2010-08-31 16:00:07,877 INFO  [Shutdown] [] TcpServer/993 - ImapSSLServer shutting down idle thread pool

2010-08-31 16:00:09,172 WARN  [Shutdown] [] ZimbraHttpConnectionManager - shutting down http client idle connection reaper thread
2010-08-31 16:00:09,173 INFO  [Shutdown] [] soap - Servlet SoapServlet shutting down
2010-08-31 16:00:09,342 INFO  [Shutdown] [] log - Shutdown hook complete


2010-08-31 16:05:26,172 INFO  [main] [] soap - Servlet SoapServlet starting up
2010-08-31 16:05:26,501 INFO  [main] [] soap - Adding service AccountService to SoapServlet
2010-08-31 16:05:26,861 INFO  [main] [] soap - Adding service MailService to SoapServlet
2010-08-31 16:05:27,940 INFO  [main] [] soap - Adding service IMService to SoapServlet
2010-08-31 16:05:27,986 INFO  [main] [] misc - version=6.0.8_GA_2637 release=20100811142254 builddate=20100811-1424
2010-08-31 16:05:27,989 INFO  [main] [] misc - LANG environment is set to: C
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property java.home=/opt/zimbra/jdk1.6.0_21/jre
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property java.runtime.version=1.6.0_21-b06
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property java.version=1.6.0_21
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property mode
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property HotSpot(TM) Server VM
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property java.vm.version=17.0-b16
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property os.arch=i386
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property os.version=2.6.9-22.EL
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property sun.cpu.endian=little
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property sun.cpu.isalist=
2010-08-31 16:05:27,990 INFO  [main] [] misc - System property sun.os.patch.level=unknown
2010-08-31 16:05:28,117 INFO  [main] [] system - Setting mysql connector property: maxActive=100
2010-08-31 16:05:28,139 INFO  [main] [] system - Setting mysql connector property: maxActive=100
2010-08-31 16:05:31,018 INFO  [main] [] sqltrace - Setting slow SQL threshold to 2000ms
2010-08-31 16:05:40,890 INFO  [LmtpServer] [] TcpServer/7025 - starting accept loop
2010-08-31 16:05:40,905 INFO  [Pop3Server] [] TcpServer/110 - starting accept loop
2010-08-31 16:05:41,062 INFO  [Pop3SSLServer] [] TcpServer/995 - starting accept loop
2010-08-31 16:05:41,106 INFO  [ImapServer] [] TcpServer/143 - starting accept loop
2010-08-31 16:05:41,218 INFO  [ImapSSLServer] [] TcpServer/993 - starting accept loop
2010-08-31 16:05:45,017 INFO  [main] [] log - Started SslSelectChannelConnector@
2010-08-31 16:05:45,020 INFO  [main] [] log - Started SslSelectChannelConnector@
2010-08-31 16:05:45,020 INFO  [main] [] log - Started SelectChannelConnector@

SSL Cert Installation: Unmatching certificate and private key error

If you're seeing this error:

root@zimbra:/tmp# /opt/zimbra/bin/zmcertmgr verifycrt comm /opt/zimbra/ssl/zimbra/commercial/commercial.key commercial.crt commercial_ca.crt
** Verifying commercial.crt against /opt/zimbra/ssl/zimbra/commercial/commercial.key
XXXXX ERROR: Unmatching certificate (commercial.crt) and private key (/opt/zimbra/ssl/zimbra/commercial/commercial.key) pair. 

It may be that the commercial.crt doesn't match the signature from commercial.key. The following two hashes should match, but don't:

# openssl x509 -noout -modulus -in commercial.crt | openssl md5
# openssl rsa -noout -modulus -in commercial.key | openssl md5

Here is an example of two matching certificate and key files deployed for LDAP:

# openssl x509 -noout -modulus -in /opt/zimbra/conf/slapd.crt | openssl md5
# openssl rsa -noout -modulus -in /opt/zimbra/conf/slapd.key | openssl md5

If you have the CSR you can check to which key it belongs:

openssl req -noout -modulus -in server.csr | openssl md5

For a full explanation of the above commands:

Installing a Thawte SSL Certificate in ZCS 5.x and 6.x

Use the following instructions to install a commercial Thawte SSL certificate. All the commands below should be performed as the root user (not zimbra).

1. Begin by generating a Certificate Signing Request (CSR).

# /opt/zimbra/bin/zmcertmgr createcsr comm -new –subject "/C=US/ST=CO/L=Broomfield/O=VMware/OU=Zimbra Collaboration Suite" –subjectAltNames

2. Next, submit the CSR to the Thawte and get a commercial certificate in X.509/PEM format.

Save the new certificate to a temporary file (e.g. /tmp/comm.crt).

3. Determine which SSL product you bought from Thawte.

Depending on which it is, click the corresponding ApacheSSL from the link above. For the directions below, we'll assume it's plain SSL Web Server:

4. Download the Intermediate Certificate Authority in Apache format (X.509/PEM):

The Intermediate CA you download depends on which Thawte SSL product was bought. Below, we're assuming SSL Web Server:

# cd /tmp && wget

5. Download the Root Certificate Authority:

Again, the Root CA you download depends on the Thawte SSL product purchased. The Root CA below is for SSL Web Server:

# cd /tmp && wget

6. Combine Root and Intermediate CAs:

cat /tmp/thawte_Premium_Server_CA.pem /tmp/SSL_CA_Bundle.pem > /tmp/commercial_ca.crt

The order of files matters: first the Root CA followed by the Intermediate CA.

Look at commercial_ca.crt and make sure there are line breaks (there should be no more than 64 characters per line). If the file is not formatted correctly, Zimbra won't be able to import it.

7. Verify:

# /opt/zimbra/bin/zmcertmgr verifycrt comm /opt/zimbra/ssl/zimbra/commercial/commercial.key /tmp/comm.crt /tmp/commercial_ca.crt

8. Deploy:

# /opt/zimbra/bin/zmcertmgr deploycrt comm /tmp/comm.crt /tmp/commercial_ca.crt

Bulk delete items from all users matching query via zmmailbox

Suppose you have the following scenario:

We have an administrative assistant who left the company ( She had created reoccurring appointments on several people's calendars which now cannot be removed. Restoring the administrative assistant's account is not an option since she was removed a while back and our oldest backup doesn't contain her account. Any suggestions on how to remove the appointments?

As an administrator, you can script zmmailbox to search all accounts for appointments with an organizer of, and then delete those appointments.

# tested on ZCS 6.0.8

if [ `whoami` != "zimbra" ]; then
  echo "You must be the zimbra user to run this script."
  exit 0

# change query below to what you want to match
# the example searches for a body matching "Organizer:"

# change to search the type(s) of items you want to match
# types are: message,conversation,contact,appointment,document,task,wiki

for acct in `zmprov -l gaa`
# if you want to search specific accounts, use the for loop below
# for acct in "99@test2.test" "100@test2.test" "101@test2.test" "102@test2.test" "103@test2.test"
  echo "Searching account $acct..."
  ITEMS=`zmmailbox -z -m $acct search -t $type "$query" | awk '{ if (NR>4 && NF) {print $2}}' | tr '\n' ,`
  if [ -n "$ITEMS" ]; then
    echo " Deleting item(s) " $ITEMS
    # Remove echo after verifying the search results
    echo zmmailbox -z -m $acct di $ITEMS

Credit to: King0770-Notes-Removal_of_Bad_Contact_Address

Interpreting zmstat charts

MySQL: InnoDB Buffer Pool Hit Rate

In general, should stay above 995.


Innodb bad.png


Innodb better.png


Innodb perfect.png


If the GC time starts getting over a few percent, especially repeatedly, then it's something that users will notice.

Mailboxd: Garbage Collection Count Bad min gc count.png

Listing of zmprov commands

Taken from version 6.0.7 of

ADD_ACCOUNT_ALIAS("addAccountAlias", "aaa", "{name@domain|id} {alias@domain}", Category.ACCOUNT, 2, 2),
ADD_ACCOUNT_LOGGER("addAccountLogger", "aal", "[-s/--server hostname] {name@domain|id} {logging-category} {debug|info|warn|error}", Category.LOG, 3, 5),
ADD_DISTRIBUTION_LIST_ALIAS("addDistributionListAlias", "adla", "{list@domain|id} {alias@domain}", Category.LIST, 2, 2),
ADD_DISTRIBUTION_LIST_MEMBER("addDistributionListMember", "adlm", "{list@domain|id} {member@domain}+", Category.LIST, 2, Integer.MAX_VALUE),
AUTO_COMPLETE_GAL("autoCompleteGal", "acg", "{domain} {name}", Category.SEARCH, 2, 2),
CHECK_PASSWORD_STRENGTH("checkPasswordStrength", "cps", "{name@domain|id} {password}", Category.ACCOUNT, 2, 2),
CHECK_RIGHT("checkRight", "ckr", "{target-type} [{target-id|target-name}] {grantee-id|grantee-name (note:can only check internal user)} {right}", Category.RIGHT, 3, 4, null, new RightCommandHelp()),
COPY_COS("copyCos", "cpc", "{src-cos-name|id} {dest-cos-name}", Category.COS, 2, 2),
COUNT_ACCOUNT("countAccount", "cta", "{domain|id}", Category.DOMAIN, 1, 1),
CREATE_ACCOUNT("createAccount", "ca", "{name@domain} {password} [attr1 value1 [attr2 value2...]]", Category.ACCOUNT, 2, Integer.MAX_VALUE),        
CREATE_ALIAS_DOMAIN("createAliasDomain", "cad", "{alias-domain-name} {local-domain-name|id} [attr1 value1 [attr2 value2...]]", Category.DOMAIN, 2, Integer.MAX_VALUE),
CREATE_BULK_ACCOUNTS("createBulkAccounts", "cabulk"),  //("  CreateBulkAccounts(cabulk) {domain} {namemask} {number of accounts to create} ");
CREATE_CALENDAR_RESOURCE("createCalendarResource",  "ccr", "{name@domain} {password} [attr1 value1 [attr2 value2...]]", Category.CALENDAR, 2, Integer.MAX_VALUE),
CREATE_COS("createCos", "cc", "{name} [attr1 value1 [attr2 value2...]]", Category.COS, 1, Integer.MAX_VALUE),
CREATE_DATA_SOURCE("createDataSource", "cds", "{name@domain} {ds-type} {ds-name} zimbraDataSourceEnabled {TRUE|FALSE} zimbraDataSourceFolderId {folder-id} 
        [attr1 value1 [attr2 value2...]]", Category.ACCOUNT, 3, Integer.MAX_VALUE),                
CREATE_DISTRIBUTION_LIST("createDistributionList", "cdl", "{list@domain}", Category.LIST, 1, Integer.MAX_VALUE),
CREATE_DISTRIBUTION_LISTS_BULK("createDistributionListsBulk", "cdlbulk"),
CREATE_DOMAIN("createDomain", "cd", "{domain} [attr1 value1 [attr2 value2...]]", Category.DOMAIN, 1, Integer.MAX_VALUE),
CREATE_SERVER("createServer", "cs", "{name} [attr1 value1 [attr2 value2...]]", Category.SERVER, 1, Integer.MAX_VALUE),
CREATE_IDENTITY("createIdentity", "cid", "{name@domain} {identity-name} [attr1 value1 [attr2 value2...]]", Category.ACCOUNT, 2, Integer.MAX_VALUE),        
CREATE_SIGNATURE("createSignature", "csig", "{name@domain} {signature-name} [attr1 value1 [attr2 value2...]]", Category.ACCOUNT, 2, Integer.MAX_VALUE),
CREATE_XMPP_COMPONENT("createXMPPComponent", "cxc", "{short-name} {domain}  {server} {classname} {category} {type} [attr value1 [attr2 value2...]]", Category.CONFIG, 6, Integer.MAX_VALUE),
DELETE_ACCOUNT("deleteAccount", "da", "{name@domain|id}", Category.ACCOUNT, 1, 1),
DELETE_CALENDAR_RESOURCE("deleteCalendarResource",  "dcr", "{name@domain|id}", Category.CALENDAR, 1, 1),
DELETE_COS("deleteCos", "dc", "{name|id}", Category.COS, 1, 1),
DELETE_DATA_SOURCE("deleteDataSource", "dds", "{name@domain|id} {ds-name|ds-id}", Category.ACCOUNT, 2, 2),                        
DELETE_DISTRIBUTION_LIST("deleteDistributionList", "ddl", "{list@domain|id}", Category.LIST, 1, 1),
DELETE_DOMAIN("deleteDomain", "dd", "{domain|id}", Category.DOMAIN, 1, 1),
DELETE_IDENTITY("deleteIdentity", "did", "{name@domain|id} {identity-name}", Category.ACCOUNT, 2, 2),
DELETE_SIGNATURE("deleteSignature", "dsig", "{name@domain|id} {signature-name}", Category.ACCOUNT, 2, 2),
DELETE_SERVER("deleteServer", "ds", "{name|id}", Category.SERVER, 1, 1),
DELETE_XMPP_COMPONENT("deleteXMPPComponent", "dxc", "{xmpp-component-name}", Category.CONFIG, 1, 1),
DESCRIBE("describe", "desc", "[[-v] [-ni] [{entry-type}]] | [-a {attribute-name}]", Category.MISC, 0, Integer.MAX_VALUE, null, null, true),
EXIT("exit", "quit", "", Category.MISC, 0, 0),
FLUSH_CACHE("flushCache", "fc", "[-a] {skin|locale|license|account|config|cos|domain|group|server|zimlet|<extension-cache-type>} [name1|id1 [name2|id2...]]", Category.MISC, 1, Integer.MAX_VALUE),
GENERATE_DOMAIN_PRE_AUTH("generateDomainPreAuth", "gdpa", "{domain|id} {name|id|foreignPrincipal} {by} {timestamp|0} {expires|0}", Category.MISC, 5, 6),
GENERATE_DOMAIN_PRE_AUTH_KEY("generateDomainPreAuthKey", "gdpak", "[-f] {domain|id}", Category.MISC, 1, 2),
GET_ACCOUNT("getAccount", "ga", "[-e] {name@domain|id} [attr1 [attr2...]]", Category.ACCOUNT, 1, Integer.MAX_VALUE),
GET_DATA_SOURCES("getDataSources", "gds", "{name@domain|id} [arg1 [arg2...]]", Category.ACCOUNT, 1, Integer.MAX_VALUE),                
GET_IDENTITIES("getIdentities", "gid", "{name@domain|id} [arg1 [arg...]]", Category.ACCOUNT, 1, Integer.MAX_VALUE),
GET_SIGNATURES("getSignatures", "gsig", "{name@domain|id} [arg1 [arg...]]", Category.ACCOUNT, 1, Integer.MAX_VALUE),
GET_ACCOUNT_MEMBERSHIP("getAccountMembership", "gam", "{name@domain|id}", Category.ACCOUNT, 1, 2),
GET_ALL_ACCOUNTS("getAllAccounts","gaa", "[-v] [-e] [-s server] [{domain}]", Category.ACCOUNT, 0, 5),
GET_ACCOUNT_LOGGERS("getAccountLoggers", "gal", "[-s/--server hostname] {name@domain|id}", Category.LOG, 1, 3),
GET_ALL_ACCOUNT_LOGGERS("getAllAccountLoggers", "gaal", "[-s/--server hostname]", Category.LOG, 0, 2),
GET_ALL_ADMIN_ACCOUNTS("getAllAdminAccounts", "gaaa", "[-v] [-e] [attr1 [attr2...]]", Category.ACCOUNT, 0, Integer.MAX_VALUE),
GET_ALL_CALENDAR_RESOURCES("getAllCalendarResources", "gacr", "[-v] [-e] [-s server] [{domain}]", Category.CALENDAR, 0, 5),
GET_ALL_CONFIG("getAllConfig", "gacf", "[attr1 [attr2...]]", Category.CONFIG, 0, Integer.MAX_VALUE),
GET_ALL_COS("getAllCos", "gac", "[-v]", Category.COS, 0, 1),
GET_ALL_DISTRIBUTION_LISTS("getAllDistributionLists", "gadl", "[-v] [{domain}]", Category.LIST, 0, 2),
GET_ALL_DOMAINS("getAllDomains", "gad", "[-v] [-e] [attr1 [attr2...]]", Category.DOMAIN, 0, Integer.MAX_VALUE),
GET_ALL_EFFECTIVE_RIGHTS("getAllEffectiveRights", "gaer", "{grantee-type} {grantee-id|grantee-name} [expandSetAttrs] [expandGetAttrs]", Category.RIGHT, 2, 4),
GET_ALL_FREEBUSY_PROVIDERS("getAllFbp", "gafbp", "[-v]", Category.FREEBUSY, 0, 1),
GET_ALL_RIGHTS("getAllRights", "gar", "[-v] [{target-type}]", Category.RIGHT, 0, 2),
GET_ALL_SERVERS("getAllServers", "gas", "[-v] [-e] [service]", Category.SERVER, 0, 3),
GET_ALL_XMPP_COMPONENTS("getAllXMPPComponents", "gaxcs", "", Category.CONFIG, 0, 0),
GET_AUTH_TOKEN_INFO("getAuthTokenInfo", "gati", "{auth-token}", Category.MISC, 1, 1),
GET_CALENDAR_RESOURCE("getCalendarResource",     "gcr", "{name@domain|id} [attr1 [attr2...]]", Category.CALENDAR, 1, Integer.MAX_VALUE), 
GET_CONFIG("getConfig", "gcf", "{name}", Category.CONFIG, 1, 1),
GET_COS("getCos", "gc", "{name|id} [attr1 [attr2...]]", Category.COS, 1, Integer.MAX_VALUE),
GET_DISTRIBUTION_LIST("getDistributionList", "gdl", "{list@domain|id} [attr1 [attr2...]]", Category.LIST, 1, Integer.MAX_VALUE),
GET_DISTRIBUTION_LIST_MEMBERSHIP("getDistributionListMembership", "gdlm", "{name@domain|id}", Category.LIST, 1, 1),
GET_DOMAIN("getDomain", "gd", "[-e] {domain|id} [attr1 [attr2...]]", Category.DOMAIN, 1, Integer.MAX_VALUE),
GET_DOMAIN_INFO("getDomainInfo", "gdi", "name|id|virtualHostname {value} [attr1 [attr2...]]", Category.DOMAIN, 2, Integer.MAX_VALUE), 
GET_EFFECTIVE_RIGHTS("getEffectiveRights", "ger", "{target-type} [{target-id|target-name}] {grantee-id|grantee-name} [expandSetAttrs] [expandGetAttrs]", Category.RIGHT, 1, 5, 
        null, new RightCommandHelp()),

// for testing the provisioning interface only, comment out after testing, the soap is only used by admin console
GET_CREATE_OBJECT_ATTRS("getCreateObjectAttrs", "gcoa", "{target-type} {domain-id|domain-name} {cos-id|cos-name} {grantee-id|grantee-name}", Category.RIGHT, 3, 4),

GET_FREEBUSY_QUEUE_INFO("getFreebusyQueueInfo", "gfbqi", "[{provider-name}]", Category.FREEBUSY, 0, 1),
GET_GRANTS("getGrants", "gg", "[-t {target-type} [{target-id|target-name}]] [-g {grantee-type} {grantee-id|grantee-name} [{0|1 (whether to include grants granted to groups the grantee belongs)}]]", 
        Category.RIGHT, 2, 7, null, new RightCommandHelp()),
GET_MAILBOX_INFO("getMailboxInfo", "gmi", "{account}", Category.MAILBOX, 1, 1),
GET_PUBLISHED_DISTRIBUTION_LIST_SHARE_INFO("getPublishedDistributionListShareInfo", "gpdlsi", "{dl-name|dl-id} [{owner-name|owner-id}]", Category.SHARE, 1, 2),
GET_QUOTA_USAGE("getQuotaUsage", "gqu", "{server}", Category.MAILBOX, 1, 1),        
GET_RIGHT("getRight", "gr", "{right}", Category.RIGHT, 1, 1),
GET_RIGHTS_DOC("getRightsDoc", "grd", "[java packages]", Category.RIGHT, 0, Integer.MAX_VALUE),
GET_SERVER("getServer", "gs", "[-e] {name|id} [attr1 [attr2...]]", Category.SERVER, 1, Integer.MAX_VALUE),
GET_SHARE_INFO("getShareInfo", "gsi", "{owner-name|owner-id}", Category.SHARE, 1, 1),
GET_XMPP_COMPONENT("getXMPPComponent", "gxc", "{name|id} [attr1 [attr2...]]", Category.CONFIG, 1, Integer.MAX_VALUE),
GRANT_RIGHT("grantRight", "grr", "{target-type} [{target-id|target-name}] {grantee-type} [{grantee-id|grantee-name} [secret]] {[-]right}", Category.RIGHT, 3, 6, null, new RightCommandHelp()),
HELP("help", "?", "commands", Category.MISC, 0, 1),
IMPORT_NOTEBOOK("importNotebook", "impn", "{name@domain} {directory} {folder}", Category.NOTEBOOK),
INIT_NOTEBOOK("initNotebook", "in", "[{name@domain}]", Category.NOTEBOOK),
INIT_DOMAIN_NOTEBOOK("initDomainNotebook", "idn", "{domain} [{name@domain}]", Category.NOTEBOOK),
LDAP(".ldap", ".l"), 
MODIFY_ACCOUNT("modifyAccount", "ma", "{name@domain|id} [attr1 value1 [attr2 value2...]]", Category.ACCOUNT, 3, Integer.MAX_VALUE),
MODIFY_CALENDAR_RESOURCE("modifyCalendarResource",  "mcr", "{name@domain|id} [attr1 value1 [attr2 value2...]]", Category.CALENDAR, 3, Integer.MAX_VALUE),
MODIFY_CONFIG("modifyConfig", "mcf", "attr1 value1 [attr2 value2...]", Category.CONFIG, 2, Integer.MAX_VALUE),
MODIFY_COS("modifyCos", "mc", "{name|id} [attr1 value1 [attr2 value2...]]", Category.COS, 3, Integer.MAX_VALUE),
MODIFY_DATA_SOURCE("modifyDataSource", "mds", "{name@domain|id} {ds-name|ds-id} [attr1 value1 [attr2 value2...]]", Category.ACCOUNT, 4, Integer.MAX_VALUE),                
MODIFY_DISTRIBUTION_LIST("modifyDistributionList", "mdl", "{list@domain|id} attr1 value1 [attr2 value2...]", Category.LIST, 3, Integer.MAX_VALUE),
MODIFY_DOMAIN("modifyDomain", "md", "{domain|id} [attr1 value1 [attr2 value2...]]", Category.DOMAIN, 3, Integer.MAX_VALUE),
MODIFY_IDENTITY("modifyIdentity", "mid", "{name@domain|id} {identity-name} [attr1 value1 [attr2 value2...]]", Category.ACCOUNT, 4, Integer.MAX_VALUE),
MODIFY_SIGNATURE("modifySignature", "msig", "{name@domain|id} {signature-name|signature-id} [attr1 value1 [attr2 value2...]]", Category.ACCOUNT, 4, Integer.MAX_VALUE),
MODIFY_SERVER("modifyServer", "ms", "{name|id} [attr1 value1 [attr2 value2...]]", Category.SERVER, 3, Integer.MAX_VALUE),
MODIFY_XMPP_COMPONENT("modifyXMPPComponent", "mxc", "{name@domain} [attr1 value1 [attr value2...]]", Category.CONFIG, 3, Integer.MAX_VALUE),
PUBLISH_DISTRIBUTION_LIST_SHARE_INFO("publishDistributionListShareInfo", "pdlsi", "{+|-} {dl-name@domain|id} {owner-name|owner-id} [{folder-path|folder-id}]", Category.SHARE, 3, 4),
PUSH_FREEBUSY("pushFreebusy", "pfb", "[account-id ...]", Category.FREEBUSY, 1, Integer.MAX_VALUE),
PUSH_FREEBUSY_DOMAIN("pushFreebusyDomain", "pfbd", "{domain}", Category.FREEBUSY, 1, 1),
PURGE_ACCOUNT_CALENDAR_CACHE("purgeAccountCalendarCache", "pacc", "{name@domain|id} [...]", Category.CALENDAR, 1, Integer.MAX_VALUE),
RECALCULATE_MAILBOX_COUNTS("recalculateMailboxCounts", "rmc", "{name@domain|id}", Category.MAILBOX, 1, 1),
REMOVE_ACCOUNT_ALIAS("removeAccountAlias", "raa", "{name@domain|id} {alias@domain}", Category.ACCOUNT, 2, 2),
REMOVE_ACCOUNT_LOGGER("removeAccountLogger", "ral", "[-s/--server hostname] [{name@domain|id}] [{logging-category}]", Category.LOG, 0, 4),
REMOVE_DISTRIBUTION_LIST_ALIAS("removeDistributionListAlias", "rdla", "{list@domain|id} {alias@domain}", Category.LIST, 2, 2),
REMOVE_DISTRIBUTION_LIST_MEMBER("removeDistributionListMember", "rdlm", "{list@domain|id} {member@domain}", Category.LIST, 2, Integer.MAX_VALUE),
RENAME_ACCOUNT("renameAccount", "ra", "{name@domain|id} {newName@domain}", Category.ACCOUNT, 2, 2),
RENAME_CALENDAR_RESOURCE("renameCalendarResource",  "rcr", "{name@domain|id} {newName@domain}", Category.CALENDAR, 2, 2),
RENAME_COS("renameCos", "rc", "{name|id} {newName}", Category.COS, 2, 2),
RENAME_DISTRIBUTION_LIST("renameDistributionList", "rdl", "{list@domain|id} {newName@domain}", Category.LIST, 2, 2),
RENAME_DOMAIN("renameDomain", "rd", "{domain|id} {newDomain}", Category.DOMAIN, 2, 2, Via.ldap),
REINDEX_MAILBOX("reIndexMailbox", "rim", "{name@domain|id} {start|status|cancel} [{types|ids} {type or id} [,type or id...]]", Category.MAILBOX, 2, Integer.MAX_VALUE, null, new ReindexCommandHelp()),
REVOKE_RIGHT("revokeRight", "rvr", "{target-type} [{target-id|target-name}] {grantee-type} [{grantee-id|grantee-name}] {[-]right}", Category.RIGHT, 3, 5, null, new RightCommandHelp()),
SEARCH_ACCOUNTS("searchAccounts", "sa", "[-v] {ldap-query} [limit {limit}] [offset {offset}] [sortBy {attr}] [sortAscending 0|1*] [domain {domain}]", Category.SEARCH, 1, Integer.MAX_VALUE),
SEARCH_CALENDAR_RESOURCES("searchCalendarResources", "scr", "[-v] domain attr op value [attr op value...]", Category.SEARCH),
SEARCH_GAL("searchGal", "sg", "{domain} {name} [limit {limit}] [offset {offset}] [sortBy {attr}]", Category.SEARCH, 2, Integer.MAX_VALUE),
SELECT_MAILBOX("selectMailbox", "sm", "{account-name} [{zmmailbox commands}]", Category.MAILBOX, 1, Integer.MAX_VALUE),        
SET_ACCOUNT_COS("setAccountCos", "sac", "{name@domain|id} {cos-name|cos-id}", Category.ACCOUNT, 2, 2),
SET_PASSWORD("setPassword", "sp", "{name@domain|id} {password}", Category.ACCOUNT, 2, 2),
GET_ALL_MTA_AUTH_URLS("getAllMtaAuthURLs", "gamau", "", Category.SERVER, 0, 0),
GET_ALL_REVERSE_PROXY_URLS("getAllReverseProxyURLs", "garpu", "", Category.SERVER, 0, 0),
GET_ALL_REVERSE_PROXY_BACKENDS("getAllReverseProxyBackends", "garpb", "", Category.SERVER, 0, 0),
GET_ALL_MEMCACHED_SERVERS("getAllMemcachedServers", "gamcs", "", Category.SERVER, 0, 0),
RELOAD_MEMCACHED_CLIENT_CONFIG("reloadMemcachedClientConfig", "rmcc", "all | mailbox-server [...]", Category.MISC, 1, Integer.MAX_VALUE, Via.soap),
GET_MEMCACHED_CLIENT_CONFIG("getMemcachedClientConfig", "gmcc", "all | mailbox-server [...]", Category.MISC, 1, Integer.MAX_VALUE, Via.soap),
SOAP(".soap", ".s"),
SYNC_GAL("syncGal", "syg", "{domain} [{token}]", Category.MISC, 1, 2),
UPDATE_TEMPLATES("updateTemplates", "ut", "[-h host] {template-directory}", Category.NOTEBOOK, 1, 3);

Listing of zmmailbox commands

Taken from version 6.0.7 of

ADD_FILTER_RULE("addFilterRule", "afrl", "{name}  [*active|inactive] [any|*all] {conditions}+ {actions}+", "add filter rule", Category.FILTER,  2, Integer.MAX_VALUE, O_AFTER, O_BEFORE, 
        O_FIRST, O_LAST),
ADD_MESSAGE("addMessage", "am", "{dest-folder-path} {filename-or-dir} [{filename-or-dir} ...]", "add a message to a folder", Category.MESSAGE, 2, Integer.MAX_VALUE, O_TAGS, 
ADMIN_AUTHENTICATE("adminAuthenticate", "aa", "{admin-name} {admin-password}", "authenticate as an admin. can only be used by an admin", Category.ADMIN, 2, 2, O_URL),
AUTHENTICATE("authenticate", "a", "{name} {password}", "authenticate as account and open mailbox", Category.MISC, 2, 2, O_URL),
AUTO_COMPLETE("autoComplete", "ac", "{query}", "contact auto autocomplete", Category.CONTACT,  1, 1, O_VERBOSE),
AUTO_COMPLETE_GAL("autoCompleteGal", "acg", "{query}", "gal auto autocomplete", Category.CONTACT,  1, 1, O_VERBOSE),
// CHECK_PERMISSION("checkPermission", "cp", "[right1 [right2...]]", "check if the user has the specified right on target.", Category.PERMISSION, 0, Integer.MAX_VALUE, O_VERBOSE),
CREATE_CONTACT("createContact", "cct", "[attr1 value1 [attr2 value2...]]", "create contact", Category.CONTACT, 2, Integer.MAX_VALUE, O_FOLDER, O_IGNORE, O_TAGS),
CREATE_FOLDER("createFolder", "cf", "{folder-name}", "create folder", Category.FOLDER, 1, 1, O_VIEW, O_COLOR, O_FLAGS, O_URL),
CREATE_IDENTITY("createIdentity", "cid", "{identity-name} [attr1 value1 [attr2 value2...]]", "create identity", Category.ACCOUNT, 1, Integer.MAX_VALUE),
CREATE_MOUNTPOINT("createMountpoint", "cm", "{folder-name} {owner-id-or-name} {remote-item-id-or-path}", "create mountpoint", Category.FOLDER, 3, 3, O_VIEW, O_COLOR, O_FLAGS),
CREATE_SEARCH_FOLDER("createSearchFolder", "csf", "{folder-name} {query}", "create search folder", Category.FOLDER, 2, 2, O_SORT, O_TYPES, O_COLOR),
CREATE_SIGNATURE("createSignature", "csig", "{signature-name} [signature-value}", "create signature", Category.ACCOUNT, 2, 2),
CREATE_TAG("createTag", "ct", "{tag-name}", "create tag", Category.TAG, 1, 1, O_COLOR),
DELETE_CONTACT("deleteContact", "dct", "{contact-ids}", "hard delete contact(s)", Category.CONTACT, 1, 1),
DELETE_CONVERSATION("deleteConversation", "dc", "{conv-ids}", "hard delete conversastion(s)", Category.CONVERSATION, 1, 1),
DELETE_ITEM("deleteItem", "di", "{item-ids}", "hard delete item(s)", Category.ITEM, 1, 1),
DELETE_IDENTITY("deleteIdentity", "did", "{identity-name}", "delete an identity", Category.ACCOUNT, 1, 1),
DELETE_FILTER_RULE("deleteFilterRule", "dfrl", "{name}", "add filter rule", Category.FILTER,  1, 1),
DELETE_FOLDER("deleteFolder", "df", "{folder-path}", "hard delete a folder (and subfolders)", Category.FOLDER, 1, 1),
DELETE_MESSAGE("deleteMessage", "dm", "{msg-ids}", "hard delete message(s)", Category.MESSAGE, 1, 1),
DELETE_SIGNATURE("deleteSignature", "dsig", "{signature-name|signature-id}", "delete signature", Category.ACCOUNT, 1, 1),
DELETE_TAG("deleteTag", "dt", "{tag-name}", "delete a tag", Category.TAG, 1, 1),
EMPTY_FOLDER("emptyFolder", "ef", "{folder-path}", "empty all the items in a folder (including subfolders)", Category.FOLDER, 1, 1),
EXIT("exit", "quit", "", "exit program", Category.MISC, 0, 0),
FLAG_CONTACT("flagContact", "fct", "{contact-ids} [0|1*]", "flag/unflag contact(s)", Category.CONTACT, 1, 2),
FLAG_CONVERSATION("flagConversation", "fc", "{conv-ids} [0|1*]", "flag/unflag conversation(s)", Category.CONVERSATION, 1, 2),
FLAG_ITEM("flagItem", "fi", "{item-ids} [0|1*]", "flag/unflag item(s)", Category.ITEM, 1, 2),
FLAG_MESSAGE("flagMessage", "fm", "{msg-ids} [0|1*]", "flag/unflag message(s)", Category.MESSAGE, 1, 2),
GET_ALL_CONTACTS("getAllContacts", "gact", "[attr1 [attr2...]]", "get all contacts", Category.CONTACT, 0, Integer.MAX_VALUE, O_VERBOSE, O_FOLDER),
GET_ALL_FOLDERS("getAllFolders", "gaf", "", "get all folders", Category.FOLDER, 0, 0, O_VERBOSE),
GET_ALL_TAGS("getAllTags", "gat", "", "get all tags", Category.TAG, 0, 0, O_VERBOSE),
GET_APPOINTMENT_SUMMARIES("getAppointmentSummaries", "gaps", "{start-date-spec} {end-date-spec} {folder-path}", "get appointment summaries", Category.APPOINTMENT, 2, 3, O_VERBOSE),
GET_CONTACTS("getContacts", "gct", "{contact-ids} [attr1 [attr2...]]", "get contact(s)", Category.CONTACT, 1, Integer.MAX_VALUE, O_VERBOSE),
GET_CONVERSATION("getConversation", "gc", "{conv-id}", "get a converation", Category.CONVERSATION, 1, 1, O_VERBOSE),
GET_IDENTITIES("getIdentities", "gid", "", "get all identites", Category.ACCOUNT, 0, 0, O_VERBOSE),
GET_FILTER_RULES("getFilterRules", "gfrl", "", "get filter rules", Category.FILTER,  0, 0),
GET_FOLDER("getFolder", "gf", "{folder-path}", "get folder", Category.FOLDER, 1, 1, O_VERBOSE),
GET_FOLDER_REQUEST("getFolderRequest", "gfr", "{folder-id}", "get folder request (always issues a GetFolderRequest)", Category.FOLDER, 1, 1, O_VERBOSE),
GET_FOLDER_GRANT("getFolderGrant", "gfg", "{folder-path}", "get folder grants", Category.FOLDER, 1, 1, O_VERBOSE),
GET_MESSAGE("getMessage", "gm", "{msg-id}", "get a message", Category.MESSAGE, 1, 1, O_VERBOSE),
GET_MAILBOX_SIZE("getMailboxSize", "gms", "", "get mailbox size", Category.MISC, 0, 0, O_VERBOSE),
GET_PERMISSION("getPermission", "gp", "[right1 [right2...]]", "get rights currently granted", Category.PERMISSION, 0, Integer.MAX_VALUE, O_VERBOSE),
GET_REST_URL("getRestURL", "gru", "{relative-path}", "do a GET on a REST URL relative to the mailbox", Category.MISC, 1, 1,
GET_SIGNATURES("getSignatures", "gsig", "", "get all signatures", Category.ACCOUNT, 0, 0, O_VERBOSE),
GRANT_PERMISSION("grantPermission", "grp", "{account {name}|group {name}|domain {name}||all|public|guest {email} [{password}]|key {email} [{accesskey}] {[-]right}}", "allow or deny 
       a right to a grantee or a group of grantee. to deny a right, put a '-' in front of the right", Category.PERMISSION, 2, 4),
HELP("help", "?", "commands", "return help on a group of commands, or all commands. Use -v for detailed help.", Category.MISC, 0, 1, O_VERBOSE),
IMPORT_URL_INTO_FOLDER("importURLIntoFolder", "iuif", "{folder-path} {url}", "add the contents to the remote feed at {target-url} to the folder", Category.FOLDER, 2, 2),
LIST_PERMISSION("listPermission", "lp", "", "list and describe all rights that can be granted", Category.PERMISSION, 0, 0, O_VERBOSE),
MARK_CONVERSATION_READ("markConversationRead", "mcr", "{conv-ids} [0|1*]", "mark conversation(s) as read/unread", Category.CONVERSATION, 1, 2),
MARK_CONVERSATION_SPAM("markConversationSpam", "mcs", "{conv} [0|1*] [{dest-folder-path}]", "mark conversation as spam/not-spam, and optionally move", Category.CONVERSATION, 1, 3),
MARK_ITEM_READ("markItemRead", "mir", "{item-ids} [0|1*]", "mark item(s) as read/unread", Category.ITEM, 1, 2),
MARK_FOLDER_READ("markFolderRead", "mfr", "{folder-path}", "mark all items in a folder as read", Category.FOLDER, 1, 1),
MARK_MESSAGE_READ("markMessageRead", "mmr", "{msg-ids} [0|1*]", "mark message(s) as read/unread", Category.MESSAGE, 1, 2),
MARK_MESSAGE_SPAM("markMessageSpam", "mms", "{msg} [0|1*] [{dest-folder-path}]", "mark a message as spam/not-spam, and optionally move", Category.MESSAGE, 1, 3),
MARK_TAG_READ("markTagRead", "mtr", "{tag-name}", "mark all items with this tag as read", Category.TAG, 1, 1),
MODIFY_CONTACT("modifyContactAttrs", "mcta", "{contact-id} [attr1 value1 [attr2 value2...]]", "modify a contact", Category.CONTACT, 3, Integer.MAX_VALUE, O_REPLACE, O_IGNORE),
MODIFY_FILTER_RULE("modifyFilterRule", "mfrl", "{name} [*active|inactive] [any|*all] {conditions}+ {actions}+", "add filter rule", Category.FILTER,  2, Integer.MAX_VALUE),
MODIFY_FOLDER_CHECKED("modifyFolderChecked", "mfch", "{folder-path} [0|1*]", "modify whether a folder is checked in the UI", Category.FOLDER, 1, 2),
MODIFY_FOLDER_COLOR("modifyFolderColor", "mfc", "{folder-path} {new-color}", "modify a folder's color", Category.FOLDER, 2, 2),
MODIFY_FOLDER_EXCLUDE_FREE_BUSY("modifyFolderExcludeFreeBusy", "mfefb", "{folder-path} [0|1*]", "change whether folder is excluded from free-busy", Category.FOLDER, 1, 2),
MODIFY_FOLDER_FLAGS("modifyFolderFlags", "mff", "{folder-path} {folder-flags}", "replaces the flags on the folder (subscribed, checked, etc.)", Category.FOLDER, 2, 2),
MODIFY_FOLDER_GRANT("modifyFolderGrant", "mfg", "{folder-path} {account {name}|group {name}|domain {name}|all|public|guest {email} [{password}]|key {email} [{accesskey}] {permissions|none}}", 
       "add/remove a grant to a folder", Category.FOLDER, 3, 5),
MODIFY_FOLDER_URL("modifyFolderURL", "mfu", "{folder-path} {url}", "modify a folder's URL", Category.FOLDER, 2, 2),
MODIFY_IDENTITY("modifyIdentity", "mid", "{identity-name} [attr1 value1 [attr2 value2...]]", "modify an identity", Category.ACCOUNT, 1, Integer.MAX_VALUE),
MODIFY_ITEM_FLAGS("modifyItemFlags", "mif", "{item-ids} {item-flags}", "replaces the flags on the items (answered, unread, flagged, etc.)", Category.ITEM, 2, 2),
MODIFY_SIGNATURE("modifySignature", "msig", "{signature-name|signature-id} {value}", "modify signature value", Category.ACCOUNT, 2, 2),
MODIFY_TAG_COLOR("modifyTagColor", "mtc", "{tag-name} {tag-color}", "modify a tag's color", Category.TAG, 2, 2),
MOVE_CONTACT("moveContact", "mct", "{contact-ids} {dest-folder-path}", "move contact(s) to a new folder", Category.CONTACT, 2, 2),
MOVE_CONVERSATION("moveConversation", "mc", "{conv-ids} {dest-folder-path}", "move conversation(s) to a new folder", Category.CONVERSATION, 2, 2),
MOVE_ITEM("moveItem", "mi", "{item-ids} {dest-folder-path}", "move item(s) to a new folder", Category.ITEM, 2, 2),
MOVE_MESSAGE("moveMessage", "mm", "{msg-ids} {dest-folder-path}", "move message(s) to a new folder", Category.MESSAGE, 2, 2),
NOOP("noOp", "no", "", "do a NoOp SOAP call to the server", Category.MISC, 0, 1),
POST_REST_URL("postRestURL", "pru", "{relative-path} {file-name}", "do a POST on a REST URL relative to the mailbox", Category.MISC, 2, 2,
RENAME_FOLDER("renameFolder", "rf", "{folder-path} {new-folder-path}", "rename folder", Category.FOLDER, 2, 2),
RENAME_SIGNATURE("renameSignature", "rsig", "{signature-name|signature-id} {new-name}", "rename signature", Category.ACCOUNT, 2, 2),
RENAME_TAG("renameTag", "rt", "{tag-name} {new-tag-name}", "rename tag", Category.TAG, 2, 2),
REVOKE_PERMISSION("revokePermission", "rvp", "{account {name}|group {name}|domain {name}||all|public|guest {email} [{password}]|key {email} [{accesskey}] {[-]right}}", "revoke a right previously 
       granted to a grantee or a group of grantees. to revoke a denied right, put a '-' in front of the right", Category.PERMISSION, 2, 4),
SEARCH("search", "s", "{query}", "perform search", Category.SEARCH, 0, 1, O_LIMIT, O_SORT, O_TYPES, O_VERBOSE, O_CURRENT, O_NEXT, O_PREVIOUS),
SEARCH_CONVERSATION("searchConv", "sc", "{conv-id} {query}", "perform search on conversation", Category.SEARCH, 0, 2, O_LIMIT, O_SORT, O_TYPES, O_VERBOSE, O_CURRENT, O_NEXT, O_PREVIOUS),
SELECT_MAILBOX("selectMailbox", "sm", "{account-name}", "select a different mailbox. can only be used by an admin", Category.ADMIN, 1, 1),
SYNC_FOLDER("syncFolder", "sf", "{folder-path}", "synchronize folder's contents to the remote feed specified by folder's {url}", Category.FOLDER, 1, 1),
TAG_CONTACT("tagContact", "tct", "{contact-ids} {tag-name} [0|1*]", "tag/untag contact(s)", Category.CONTACT, 2, 3),
TAG_CONVERSATION("tagConversation", "tc", "{conv-ids} {tag-name} [0|1*]", "tag/untag conversation(s)", Category.CONVERSATION, 2, 3),
TAG_ITEM("tagItem", "ti", "{item-ids} {tag-name} [0|1*]", "tag/untag item(s)", Category.ITEM, 2, 3),
TAG_MESSAGE("tagMessage", "tm", "{msg-ids} {tag-name} [0|1*]", "tag/untag message(s)", Category.MESSAGE, 2, 3);

Using Android emulator to test issues

Initial installation of emulator:

  • Installed packages
    • Android SDK Tools, revision 8
    • Android SDK Platform-tools, revision 1
    • Documentation for Android SDK, API 9, revision 1
    • SDK Platform Android 2.3, API 9, revision 1
    • SDK Platform Android 2.2, API 8, revision 2
    • SDK Platform Android 2.1-update1, API 7, revision 2
    • Samples for SDK API 9, revision 1
    • Samples for SDK API 8, revision 1
    • Samples for SDK API 7, revision 1

Create an Android Virtual Device according to the desired target (2.1, 2.2, 2.3). Click "Start..." to launch emulator.

Starting emulator with proxy

From the tools directory:

emulator.exe -avd DroidX_2.1 -scale 0.59 -http-proxy

Modifying files on AVD

For one case, I needed to test a commercial SSL certificate with Android's built-in email and web browser app. I installed the certificate on a test server, but had to trick Android to use the test server's IP for the hostname in the certificate. This can be done by modifying /system/etc/hosts on the AVD:

  1. Start the emulator with a larger partition size, so /system has free space. If the AVD is named Android_2_2, launch from the command-line via:
    ./tools/emulator -partition-size 128 -avd Android_2_2 -shell
    The "-shell" option also gives you a root shell from the terminal you launched the emulator.
  2. Remount /system to rw instead of ro with the adb tool, included in the SDK:
    ./platform-tools/adb remount
  3. Pull the current hosts file:
    ./platform-tools/adb pull hosts /system/etc/hosts
  4. Modify and add to the hosts file as needed.
  5. Push the updated hosts file to the running AVD:
    ./platform-tools/adb push hosts /system/etc/hosts

SOAP Stuff

Jump to: navigation, search