Difference between revisions of "ShanxT-Notes"

(Useful Zimbra One-Liners)
Line 18: Line 18:
'''Send 250 emails via CLI:'''
'''Send 250 emails via CLI:'''
for i in {1..250} ; do echo -e "Subject: email no. $i \nThe werewolf howls while the vampire hunts." | /opt/zimbra/postfix/sbin/sendmail surej.mathew@example.com ; done
Sends 250 emails, with the subject differing in each email
for i in {1..250} ; do echo -e "Subject: email no. $i \nThe werewolf howls while the vampire hunts." | /opt/zimbra/postfix/sbin/sendmail surej.mathew@example.com ; done
== Bulk provisioning using CSV in Zimbra 7 ==
== Bulk provisioning using CSV in Zimbra 7 ==

Revision as of 09:44, 12 April 2014

Zimbra Log Sorter

Script to sort Zimbra logs. Makes logs more legible, and can also filter logs using regexs. Use '--help' to see all options. Use '--examples' to see some examples.

Latest version of the script can be found here:


Useful Zimbra One-Liners

To find a spammer: The following will list the user that has authenticated the most, usually being the compromised ID via which spam is being sent. Change the password of the user immediately.

grep sasl_user /var/log/maillog | sed 's/.*sasl_username=//g' | sort | uniq -c | sort -nr | head

Get all members of all distribution lists: The following will get all the members of all the distribution lists on the server. The first line will be the distribution list ID, followed by the members, followed by a blank line, then the next distribution list ID, and so on.

for i in `zmprov -l gadl`; do echo "$i" ;zmprov gdl $i | grep zimbraMailForwardingAddress: | awk '{print $2}' ; echo ""; done | less

Send 250 emails via CLI: Sends 250 emails, with the subject differing in each email

for i in {1..250} ; do echo -e "Subject: email no. $i \nThe werewolf howls while the vampire hunts." | /opt/zimbra/postfix/sbin/sendmail surej.mathew@example.com ; done

Bulk provisioning using CSV in Zimbra 7

Zimbra 7 has removed the ability to add users using the GUI, but this can be done using the following script. The CSV has to be semi-colon separated, NOT comma separated. It has to be in the following format:

"Email ID";"Name";"Company";"Description";"Mobile Number";"Phone Number";"Address";"State";"Country"


"keyur.shah@example.com";"Keyur Shah";"Acme Inc";"This guy works in engineering";996323418;4216857841;"Valley road, random colony";"New Delhi";"India"

Save your csv as '/tmp/newusers.csv', and run the script. A file '/tmp/zmprovinput' will be created, which can then be analysed and added using the zmprov commmand, as shown:

zmprov < /tmp/zmprovinput

The password for all users will be 'very_secure_password_1831'. This can be changed in the script. Read script for more info.

Latest version of the script can be found here:


Set random passwords and force user to change password on login

The following script generates a random password, stores it to a file, and forces the user the change password on first login using the zimbraPasswordMustChange attribute.

The userlist has to be supplied before running the script, and should be stored in the file /tmp/allaccounts. The users should be in the format 'user@example.com'. To change for all users, simply run:

zmprov -l gaa > /tmp/allaccounts

After running the script, two files are created. /tmp/newpasswords.csv contains the list of usernames and passwords in CSV format, whereas /tmp/zmprovPwChange is the file input for zmprov, which after analysis can be run as follows:

zmprov < /tmp/zmprovPwChange

Latest version of the script can be found here:


Simple archival server for Zimbra OSE


This document shows how to create a simple archiving server. If you have a user 'keyur@example.com', all mails sent to and from this email ID will be forwarded to 'keyur@archive.example.com'.

We will need two servers for this. Both will be installed with Zimbra, one being the live mail server 'example.com', and the other the archiving server, 'archive.example.com'. The archiving server should have a much larger HDD drive than the mail server, preferably formatted using LVM, to allow for expansion later.

The installation on each server will be independent, ie, this isn't a multi-server setup. Each server will be a single-server, with the only difference being the domain names.

In this example, let's assume the live server's domain is 'example.com', with IP, and the archiving server is 'archive.example.com', with IP Install Zimbra on both as usual.


The servers will require a local DNS, as we use this to forward the mails. In this example, I will assume that we have set up a caching name server using bind on the live server. Typical entries would be something like this:

example.com.       	IN A  
mail.example.com.       IN A  
example.com.            IN MX           10 mail.example.com.

Along with this, we need to add an A and MX record for archive.example.com as well.

archive.example.com.    IN A  
archive.example.com.    IN MX           10 archive.example.com.

Now all mails addressed to 'archive.example.com' will be forwarded to the archive server.


In postfix, we can specify an email address to which all incoming and outgoing mails from a particular email ID will be forwarded to. This is done using 'sender_bcc_maps' and 'recipient_bcc_maps'. All these changes are done only on the main server.

We make the following entries at the end of /opt/zimbra/postfix/conf/main.cf

sender_bcc_maps = hash:/opt/zimbra/postfix/conf/archivelist
recipient_bcc_maps = hash:/opt/zimbra/postfix/conf/archivelist

The file '/opt/zimbra/postfix/conf/archivelist' will have users in the following format: keyur@example.com keyur@archive.example.com

All mails to and from keyur@example.com will be forwarded to keyur@archive.example.com.

Manual addition

Create a user on the main server, and then the corresponding user on the archive server. Then add the users in the format as show above to the file '/opt/zimbra/postfix/conf/archivelist', and then run the postmap command as the zimbra user:

$ postmap /opt/zimbra/postfix/conf/archivelist
$ postfix reload


I wrote the following script to add users automatically on the archive server, and also to the 'archivelist' file. Run this on the main server, and all users will be automatically added. You can place it in the crontab for every half an hour, so that when a new user is created on the main server, he/she will be automatically added to the archive server. SSH using keys (password-less ssh) between the main and archive server is necessary for the script to function.

The latest version of the script can be found here:


NOTE: All mails, sent and received, will be stored in the inbox of the archive user.

Restore mails from store folder, without ldap

Zimbra Mailbox Structure

In Zimbra, each user is assigned a unique 'mailbox ID', which links him/her to their folder in /opt/zimbra/store/0.

Therefore a user with say mailbox ID '716', would have folder /opt/zimbra/store/0/716. The emails are stored in '.msg' format.

For more information on the structure, go here.

The problem

Now this information is stored in LDAP, so if LDAP is corrupted or unrecoverable, we cannot associate the mailbox ID with the user ID.

But the store folder is intact.

The solution

We will have to trace which folder belongs to which user. Since each folder belongs to a single user, it is sufficient to determine with a few emails who the inbox belongs to.

So we follow these steps to recover it: In our case the backup store folder is /opt/zimbra/store.old/0

Go to the backup store folder:

# cd /opt/zimbra/store.old/0

Save the script as 'findusers.sh', and the run the script.


for line in `ls`; do
echo $line >> /tmp/messagelist
cat $PWD/$line/msg/0/* | grep To: | sed 's/To: //' | sort | uniq -c | sort -nr | head -5 >> /tmp/messagelist
echo "" >> /tmp/messagelist
# /opt/zimbra/store.old/0/findusers.sh

This will return a list of top ten users (in /tmp/messagelist) whose name is present in the 'To:' field of the messages stored. Using the output of this, we can make a good estimate of the user's folder, but this needs to be confirmed manually as well, by reading the email.

The output returned will be as follows:

     37 "mis" <mis@example.com>,
     13 "jason johnson" <jason.johnson@example.com>,
     12 'Secretary'=20
     12 <DIV><B>To:</B> <A title=3Dsecretary@example.com=20
     7 <DIV><B>To:</B> <A title=3Dlucknow@example.com=20

     23 "Fahad Faheem" <fahad.faheem@example.com>
     12   <DIV style=3D"FONT: 10pt arial"><B>To:</B> <A =
     11 "Pawan Kumar" <pawan.kumar@example.com>
     11 Kolkata=20
     11 <DIV><B>To:</B> <A title=3Drokolkata@example.com=20

From this we can guess that the folder '547', ie /opt/zimbra/store.old/0/547, belongs to 'fahad.faheem@example.com'.

But we need to confirm this by going to the folder /opt/zimbra/store.old/0/547, and reading a few sample emails to confirm that the directory belongs to 'fahad.faheem@example.com'. Look for emails where there is only one recipient. This is a major clue. Also look for mails where there is one sender and and recipient of an outside domain. Since 'Sent' mails are also stored here, this would indicate that the email is sent by the user, to a remote recipient.

The mails can then be recovered by using zmmailbox as the Zimbra user.

Both the commands below give admin rights on zmmailbox prompt, so use any one.

zmmailbox -zadmin


zmmailbox adminAuthenticate -u https://server.domain.com:7071 admin@domain.com password

After that we create the 'Recovery' folder, and add messages to that folder from our old store folder.

mbox> selectMailbox fahad.faheem@example.com
mbox agmadmin@example.com> createfolder /Recovery
mbox agmadmin@example.com> addMessage /Recovery /opt/zimbra/store.old/0/547/msg/0

/opt/zimbra/store.old/0/547/msg/0 is the path to the folder containing the mails. Some IDs may have a large amount of mails, resulting in msg/1, msg/2, etc. These will have to be run one-by-one.

Deleting a particular mail from all accounts

The following script deletes a particular mail from all accounts.

In the script, the subject of the mail is "Re: Test2" and the sender is "jason.johnson@example.com". The file 'userlist' contains all the user's IDs, generated from 'zmprov -l gaa'.

Ajcody Notes and King0770 Notes were used. The script is a modification of King0770's script.

for i in `cat userlist`; do
 echo ""
 echo "Searching $addr"
 for msg in `zmmailbox -z -m "$addr" s -l 225 -t message 'subject:"Re: Test2" and From:jason.johnson@example.com' | awk '{ if (NR!=1) {print}}' | egrep -v 'Id|-----|^$' | awk '{ print $2 }'`
  echo "Removing "$msg""
  zmmailbox -z -m $i dm $msg
  echo "Deleted from $i"
  echo ""

Verified Against: Zimbra Collaboration Suite 6,7 Date Created: 08/04/2012
Article ID: https://wiki.zimbra.com/index.php?title=ShanxT-Notes Date Modified: 2014-04-12

Try Zimbra

Try Zimbra Collaboration with a 60-day free trial.
Get it now »

Want to get involved?

You can contribute in the Community, Wiki, Code, or development of Zimlets.
Find out more. »

Looking for a Video?

Visit our YouTube channel to get the latest webinars, technology news, product overviews, and so much more.
Go to the YouTube channel »

Jump to: navigation, search