We have just migrated our calendars from MeetingMaker to Google Apps for Education.
This cloud service is of course very cool and all that, but I would still like to have an off-cloud backup.

There are several commercial applications that you can, but I wanted something simple that can be scheduled from CRON.
A useful script is the one from Matthew M. Boedicker.
This script uses WWW:Mechanize to login in to Google Calendar and download a ZIP copy of all the calendars.
If you make sure the user account is an administrative one, and is subscribed to all your users calendars, this will make a ZIP file containing all calendars.

Unfortunately that did not work straight away, because our 'regular' users use federated logins to the Google Calendar.
So the URLs in Matthew's script did work. Moreover, the federated stuff makes 'mechanizing' it alot more complex.

The good thing is you can have non-federated accounts as well, you'll need to use https://www.google.com/a/cpanel/domain.com to access the control panel.
From there, the admin can also make backups of calendars.

I adjusted the original script to use that specific administrative page. Also, I made the script read in a password file, instead of giving sensitive information on the command line, which makes it show up in the process list. This might be an issue, since backing up several large calendars takes a while.

#!/usr/bin/ruby
# $Id: gcal_backup.rb 110 2010-10-03 17:50:39Z visser $
# Backup all Google Calendars in a educational domain.
# Make sure the used account has admin rights, and that
# this user is subscribed to all calendars that need to
# be backupped.
# Based on idea from Matthew M. Boedicker <matthewm@boedicker.org>.
require 'rubygems'
require 'mechanize'

$VERBOSE = 1

outdir, cred_file = ARGV
unless [outdir, cred_file].include?(nil)

credentials  = open(cred_file, "r").gets.split
domain = credentials[0]
username = credentials[1]
password = credentials[2]

time = Time.new
agent = WWW::Mechanize.new

agent.get("https://www.google.com/a/#{domain}/ServiceLogin?service=CPanel&passive=1209600&continue=https://www.google.com/a/cpanel/#{domain}/Dashboard&followup=https://www.google.com/a/cpanel/#{domain}/Dashboard") do |p|
  p.form(:action => "https://www.google.com/a/#{domain}/LoginAction2?service=CPanel") do |f|
    f.Email = username
    f.Passwd = password
    agent.submit(f)
    agent.get("https://www.google.com/calendar/hosted/#{domain}/exporticalzip").save_as("#{outdir}/#{domain}_#{time.strftime('%Y-%m-%d %H%M')}.zip")
  end
end
else
        puts "Usage: #{$0} destination_dir credentials_file\nCredentials file should have 'domain username password' on first line"
end

  • No labels