Glenno-Notes: Difference between revisions

Line 603: Line 603:
# Remount /system to rw instead of ro:<code><pre>./platform-tools/adb remount</pre></code>
# Remount /system to rw instead of ro:<code><pre>./platform-tools/adb remount</pre></code>
# Pull the current hosts file with the adb tool, included in the SDK:<code><pre>./platform-tools/adb pull hosts /system/etc/hosts</pre></code>
# Pull the current hosts file with the adb tool, included in the SDK:<code><pre>./platform-tools/adb pull hosts /system/etc/hosts</pre></code>
# Modify and add to the hosts file as needed.
# Push the updated hosts file to the running AVD:<code><pre>./platform-tools/adb push hosts /system/etc/hosts</pre></code>


[[Category: Community Sandbox]]
[[Category: Community Sandbox]]

Revision as of 22:55, 13 December 2010

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

Monitoring file access

An issue came up where /opt/zimbra/log/clamd.pid 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/clamd.pid -S -k clamd-pid
Test:
# cat /opt/zimbra/log/clamd.pid
# 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="clamd.pid" 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="clamd.pid" 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
    or
    % 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/ldap-vmm.cf ~/conf/ldap-slm.cf
      Edit the new file ldap-slm.cf 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/ldap-slm.cf
  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. http://www.postfix.org/postconf.5.html#smtpd_sender_restrictions

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:

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

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

Shutdown:

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

Startup:

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 buildhost=build01.lab.zimbra.com
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 java.vm.info=mixed mode
2010-08-31 16:05:27,989 INFO  [main] [] misc - System property java.vm.name=Java 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 os.name=Linux
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 sun.arch.data.model=32
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@0.0.0.0:443
2010-08-31 16:05:45,020 INFO  [main] [] log - Started SslSelectChannelConnector@0.0.0.0:7071
2010-08-31 16:05:45,020 INFO  [main] [] log - Started SelectChannelConnector@0.0.0.0:7072

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
f4033675a216bbbe0712917e3281fe3c
# openssl rsa -noout -modulus -in commercial.key | openssl md5
76991327ac5bdae0840270dffeb4b214

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
59688017a0601a37a07d8fcd4ec9908c
# openssl rsa -noout -modulus -in /opt/zimbra/conf/slapd.key | openssl md5
59688017a0601a37a07d8fcd4ec9908c

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: http://kb.wisc.edu/middleware/page.php?id=4064

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 host.example.com


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

https://search.thawte.com/support/ssl-digital-certificates/index?page=content&id=SO13187

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


3. Determine which SSL product you bought from Thawte.

https://search.thawte.com/support/ssl-digital-certificates/index?page=content&id=SO1498&actp=LIST&viewlocale=en_US

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:

https://search.thawte.com/support/ssl-digital-certificates/index?page=content&id=SO14822


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:

https://search.thawte.com/support/ssl-digital-certificates/index?page=content&actp=CROSSLINK&id=AR1374

# cd /tmp && wget https://search.thawte.com/library/VERISIGN/ALL_OTHER/thawte%20ca/SSL_CA_Bundle.pem


5. Download the Root Certificate Authority:

https://www.thawte.com/roots/index.html

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 https://www.thawte.com/roots/thawte_Premium_Server_CA.pem


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 (admin_assistant@example.com). 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 admin_assistant@example.com, and then delete those appointments.


#!/bin/bash
# tested on ZCS 6.0.8

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

# change query below to what you want to match
# the example searches for a body matching "Organizer: admin_assistant@example.com"
query="\"\\\"Organizer: admin_assistant@example.com\\\"\""

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

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"
do
  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
  fi
done

Credit to: King0770-Notes-Removal_of_Bad_Contact_Address

Deciphering zmstat charts

MySQL: InnoDB Buffer Pool Hit Rate

In general, should stay above 995.

Bad

Innodb bad.png

Better

Innodb better.png

Ideal

Innodb perfect.png

Mailboxd: Minor Garbage Collection Time and Mailboxd: Major Garbage Collection Time

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

Listing of zmprov commands

Taken from version 6.0.7 of com.zimbra.cs.account.ProvUtil.java

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 com.zimbra.cs.zclient.ZMailboxUtil.java

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, 
        O_DATE, O_FLAGS, O_NO_VALIDATION),
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,
        O_OUTPUT_FILE, O_START_TIME, O_END_TIME, O_URL),
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,
        O_CONTENT_TYPE, O_IGNORE_ERROR, O_PRESERVE_ALARMS, O_URL),
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: http://www.blogsdna.com/10400/android-2-2-froyo-emulator-for-pc-and-mac-os-x.htm

  • 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.

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:
    ./platform-tools/adb remount
  3. Pull the current hosts file with the adb tool, included in the SDK:
    ./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
Jump to: navigation, search