How to synchronize your Google Calendar with Zimbra automatically

Submitted by Justin Freeman on 3 February, 2010 - 15:47
So you've just bought an Android phone, pretty cool huh? But now you want to synchronize the Zimbra Calendar with your Android phone and Google Calendar. How the heck do you do that? Well, it's not too hard actually... so here's my method.
Overview - how it works
- export your Zimbra calendar in iCal format on your Zimbra server
- use the Zimbra Apache server to publish the iCal files on the Internet
- create a new Calendar in Google Calendar and subscribe to a remote URL (bummer that Google cannot do URL authentication)
- Google will then automatically retrieve this public URL, consume the iCal file and update the calendar. This happens about every 12 to 24 hrs, depending on same random Google'ness.
Caveats
- .ics files are available on the Internet without any password protection, it's only security by obscurity. But the URL is pretty impossible to guess as it must be the exact .ics file name
- Google will update the calendar every 12 to 24 hrs
Setup and configuration
To set this up:
- The Zimbra Apache web server is only accessible on Port 7780 which is not open by default to the Internet. So open a random port on your Firewall (some random high port) and redirect that to Port 7780 (for TCP only). You can also lock this down to only permit access from Google servers, if you can figure that out ;)
- copy the bash script (zimbra-google-calendar-export.sh) below to your Zimbra server. This will generate the local iCal files.
- edit the /opt/zimbra/httpd/conf/httpd.conf and add a Options -Indexes entry to the Directory entries below. This will stop Apache from simply listing ALL files in the directory, which is not optimal as it simply exposes all the iCal files to the world, eek!
<Directory /> #Options FollowSymLinks Options -Indexes AllowOverride None Order deny,allow Deny from all </Directory><Directory "/opt/zimbra/httpd-2.2.14/htdocs"> # # Possible values for the Options directive are "None", "All", # or any combination of: # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews # # Note that "MultiViews" must be named *explicitly* --- "Options All" # doesn't give it to you. # # The Options directive is both complicated and important. Please see # http://httpd.apache.org/docs/2.2/mod/core.html#options # for more information. # # Options Indexes FollowSymLinks Options -Indexes # # AllowOverride controls what directives may be placed in .htaccess files. # It can be "All", "None", or any combination of the keywords: # Options FileInfo AuthConfig Limit # AllowOverride None # # Controls who can get stuff from this server. # Order allow,deny Allow from all </Directory> - after making these changes restart the Zimbra server (or just the Zimbra Apache server):
zmapachectl stop; zmapachectl start - add a crontab entry to regularly export all the Zimbra Calendars, once a day should be suffficient
0 7 * * * root /etc/custom-scripts/zimbra-google-calendar-export.sh > /dev/null 2>&1 - run the zimbra-google-calendar-export.sh as root and then check /opt/zimbra/httpd/htdocs you should see a listing of *.ics files
- each ics file uses the Zimbra account ID (which is pretty random) as the file name. Check the /var/log/zimbra-google-calendar-export.log file to work out which Zimbra account corresponds to which .ics file. These file names do not change.
- the URL for each .ics file will be something like, http://zimbra.xyz.com:123456/1111231a-v476-48g1-e1gc-h1ks921k198s.ics (don't forget your random high port number!)
- you can now log into Google Calendar:
- add a new Calendar
- subscribe to a remote URL (again, bummer that Google cannot do URL authentication)
- create a new Calendar and supply the magic URL (http://zimbra.xyz.com:123456/1111231a-v476-48g1-e1gc-h1ks921k198s.ics)
- Google will now fetch the .ics file and populate your new Calendar
- check your Android phone's Calendars and you should now see your imported Zimbra calendar. WOO HOO!
bash script: zimbra-google-calendar-export.sh
Copy the following bash script as zimbra-google-calendar-export.sh and put on your Zimbra server.
#!/bin/bash # Zimbra calendar export for Google Calendar import # (c) Copyright Agileware Pty Ltd. All rights reserved. http://agileware.net # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # http://www.gnu.org/licenses/gpl-2.0.txt LOGFILE="/var/log/zimbra-google-calendar-export.log"; APACHE_HTDOCS="/opt/zimbra/httpd/htdocs"; echo "zimbra google calendar export starting" >> $LOGFILE; #Remove the default 'It works!' page and replace with a blank page echo '' > $APACHE_HTDOCS/index.html #Do not use zmaccts as long domain names cause the email address to be truncated #So query LDAP for account names instead ZIMBRA_ACCOUNTS=`su - zimbra --command='/opt/zimbra/bin/zmprov -l gaa'`; for ZIMBRA_ACCOUNT in $ZIMBRA_ACCOUNTS; do # Get all attributes for this account, slow as zmprov has to initiate ZIMBRA_ACCOUNT_DETAILS="`su - zimbra --command='/opt/zimbra/bin/zmprov ga '$ZIMBRA_ACCOUNT''`"; IS_SYSTEM_ACCOUNT=`echo "$ZIMBRA_ACCOUNT_DETAILS" | grep 'zimbraIsSystemResource'`; # Skip the Wiki, Ham, Spam or other type of system accounts if [ -z "$IS_SYSTEM_ACCOUNT" ]; then ZIMBRA_ACCOUNT_ID=`echo "$ZIMBRA_ACCOUNT_DETAILS" | grep zimbraId | sed 's|zimbraId: ||g'`; echo "calendar export starting for $ZIMBRA_ACCOUNT ($ZIMBRA_ACCOUNT_ID)" >> $LOGFILE; su - zimbra --command='/opt/zimbra/bin/zmmailbox -z -m '$ZIMBRA_ACCOUNT' getRestURL "/calendar?fmt=ics"' > $APACHE_HTDOCS/$ZIMBRA_ACCOUNT_ID.ics; echo "calendar export completed for $ZIMBRA_ACCOUNT ($ZIMBRA_ACCOUNT_ID)" >> $LOGFILE; else echo "$ZIMBRA_ACCOUNT : Is system account. Skipping." >> $LOGFILE; fi done; echo "zimbra google calendar export completed" >> $LOGFILE;
Another easy option
Another easy option for individual use or when you don't have root access to the Zimbra server is to:
- using the Zimbra REST API you can perform a GET request to the Zimbra server and download a copy of calendar just by knowing the required user name and password.
- so you can do this in a Web Browser:
https://somedude:somedudepassword@mail.acme.com/service/home/somedude/calendar?fmt=ics - or use wget and a cron job to download the calendar to a remote web server, which Google Calendar can then subscribe too, like:
wget --no-check-certificate https://somedude:somedudepassword@mail.acme.com/service/home/somedude/calendar?fmt=ics
This is handy for Geeks who have access to bash and a web server, but not necessarily the Zimbra server.
More thoughts
- you might have noticed that the above script runs pretty damn slow. This is because with each call to zmmailbox and zmcontrol a new Java VM is instantiated. It would be great if it were possible to instantiate zmmailbox and zmcontrol once and pipe commands to it. This is currently beyond my bash kung fu.
- it would be better if the calendar was synchronised more regularly with Google. Like hourly instead of once a day. I'm been working on another version which does this using libopensync similar to a method outlined here, http://satyajitranjeev.wordpress.com/2009/08/02/synchronizing-nokia-e-series-with-fedora I have had some success but is still a work in progress.





Thanks for posting this
Thanks for posting this information. Upon trying the script I get no output files in the /opt/zimbra/httpd/htdocs/ directory. Also, I get the following message when the script runs:
./zimbra-google-calendar-export.sh: line 43: $APACHE_HTDOCS/$ZIMBRA_ACCOUNT_ID.ics: ambiguous redirectAny ideas?
G'day Eddie Not sure what the
G'day Eddie
Not sure what the problem is there, the code as posted here is verbatim the same as we use in production. Perhaps a copy and paste error? You have to be careful to ensure that the single quotes and double quotes are in the correct places on that line.
Other than that, not really sure. What OS are you running the code on?
Justin