logo

Let’s Work Together

Partner with you to deliver responsive and cost-effective IT & Support solutions
Reponsive
Cost-Effective
Partner with you
Focus
Attitude to Serve
Professional
These are the reasons why AionSolution is your vendor when you are seeking someone to support your IT in your office.
info@aionsolution.com
+852 2636 6177

Zimbra Account mailbox database structure

Account mailbox database structure

Each zimbra account is associated with a mailbox group, which is based on the mailbox id number. (The mailboxId is specific to the store, the zimbraId on the other hand is system wide). You can determine the mailbox id for an account (this example account is named “b@test.test”) like this:

$ zmprov getMailboxInfo b@test.test
mailboxId: 5247
quotaUsed: 1951021

Mailbox users are members of mailbox groups on a rotation up to a maximum of 100 mailbox groups; you can determine the mailbox group by modulo division of the mailbox id by 100 (the remainder of dividing the mailbox id by 100, i.e only the last two digits). Note that if the result is zero, the mailbox group is 100, not 0.

$ expr 5247 % 100
47

Take a look at the mail_item table in the mailbox group database, particularly the date, size, sender, and subject columns.

$ mysql mboxgroup47
mysql> describe mail_item;
+--------------+---------------------+------+-----+---------+-------+
| Field        | Type                | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+-------+
| mailbox_id   | int(10) unsigned    | NO   | PRI |         |       |
| id           | int(10) unsigned    | NO   | PRI |         |       |
| type         | tinyint(4)          | NO   |     |         |       |
| parent_id    | int(10) unsigned    | YES  |     | NULL    |       |
| folder_id    | int(10) unsigned    | YES  |     | NULL    |       |
| index_id     | int(10) unsigned    | YES  |     | NULL    |       |
| imap_id      | int(10) unsigned    | YES  |     | NULL    |       |
| date         | int(10) unsigned    | NO   |     |         |       |
| size         | int(10) unsigned    | NO   |     |         |       |
| volume_id    | tinyint(3) unsigned | YES  | MUL | NULL    |       |
| blob_digest  | varchar(28)         | YES  |     | NULL    |       |
| unread       | int(10) unsigned    | YES  |     | NULL    |       |
| flags        | int(11)             | NO   |     | 0       |       |
| tags         | bigint(20)          | NO   |     | 0       |       |
| sender       | varchar(128)        | YES  |     | NULL    |       |
| subject      | text                | YES  |     | NULL    |       |
| name         | varchar(128)        | YES  |     | NULL    |       |
| metadata     | text                | YES  |     | NULL    |       |
| mod_metadata | int(10) unsigned    | NO   |     |         |       |
| change_date  | int(10) unsigned    | YES  |     | NULL    |       |
| mod_content  | int(10) unsigned    | NO   |     |         |       |
+--------------+---------------------+------+-----+---------+-------+

Let’s examine a single mail item.

mysql> select * from mail_item where id>26000 and mailbox_id=5247 limit 1 \G
*************************** 1. row ***************************
  mailbox_id: 5247
          id: 26001
        type: 5
   parent_id: NULL
   folder_id: 2
    index_id: 26001
     imap_id: 26001
        date: 1182380903
        size: 95842
   volume_id: 1
 blob_digest: rbrw+fj0tvyvTPt2haxssued7,A=
      unread: 1
       flags: 2
        tags: 0
      sender: sender@domain.com
     subject: Message subject
        name: NULL
    metadata: d1:f147:This message...1:p8:Re: SF: 1:s21:sender@domain.com1:vi10ee
mod_metadata: 30102
 change_date: 1182380905
 mod_content: 30102
1 row in set (0.00 sec)

With the volume_id, mailbox_id, id, and mod_content fields, you can determine the location of the message “blob” file. Volume 1 is the default message store:

mysql> select * from zimbra.volume;
+----+------+----------+-------------------+-----------+-----------------+--------------+--------------------+----------------+-----------------------+
| id | type | name     | path              | file_bits | file_group_bits | mailbox_bits | mailbox_group_bits | compress_blobs | compression_threshold |
+----+------+----------+-------------------+-----------+-----------------+--------------+--------------------+----------------+-----------------------+
|  1 |    1 | message1 | /opt/zimbra/store |        12 |               8 |           12 |                  8 |              0 |                  4096 |
|  2 |   10 | index1   | /opt/zimbra/index |        12 |               8 |           12 |                  8 |              0 |                  4096 |
+----+------+----------+-------------------+-----------+-----------------+--------------+--------------------+----------------+-----------------------+

On the filesystem, the user directories and the message directories within each user directory are split so that there are a maximum of 4096 (that is, 212) files in each directory. To determine the appropriate directory “hash” numbers, bitshift the mailbox_id and the mail item id to the right by 12 bits (i.e. divide by 212, rounding down). It is significant to note that if the id is less than 4096, the hash number will be 0.

$ perl -e 'print 5247 >> 12 ; print "\n"'
1
$ perl -e 'print 26001 >> 12 ; print "\n"'
6

The mod_content field is used to keep track of message blob file revisions. If a blob file is ever updated (for example, if a calendar appointment is modified), the filename and this field are updated. So, if the user with mailbox_id 5427 has a message on volume 1 with id 26001 and mod_content 30102, we’ll see it like this:

$ ls -l /opt/zimbra/store/1/5247/msg/6/26001-30102.msg
-rw-r-----  1 zimbra zimbra 95842 Jun 20 16:08 /opt/zimbra/store/1/5247/msg/6/26001-30102.msg

Assuming only the default message store is in use, the filename for an item may be derived with a query.

mysql> select id, 
    concat('/opt/zimbra/store/', (mailbox_id >> 12), '/', mailbox_id, '/msg/',
    (id >> 12), '/', id, '-', mod_metadata, '.msg') as file
    from mail_item where mailbox_id="723" limit 1;
+-----+-------------------------------------------+
| id  | file                                      |
+-----+-------------------------------------------+
| 261 | /opt/zimbra/store/0/723/msg/0/261-103.msg |
+-----+-------------------------------------------+