Feel free to try this out. I used the Provisioning API code from
http://code.google.com/p/google-apps-provisioning-api-client/downloads/list
as a starting point, and this file depends on the connection class
developed for that library. The only problem I encountered using the
older Provisioning API code was the validation of the SSL certificate
used in the https connections. I had to comment out the ca_file and
verify_mode lines in connection.rb, around line 70, to get the https
connections to work:
if uri.scheme == 'https'
# conn.ca_file = __FILE__ # certs embedded at end of
this file
# conn.verify_mode = OpenSSL::SSL::VERIFY_PEER
conn.use_ssl = true
end
Dowload the source from http://pastie.caboo.se/176815
Or cut and paste:
#!/usr/bin/ruby
#
# Copyright 2008 Peter F. Zingg
# Based on Provisioning API ruby client, Copyright 2006 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you
may not
# use this file except in compliance with the License. You may obtain
a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
the
# License for the specific language governing permissions and
limitations under
# the License.
#
require 'rexml/document'
require 'date'
require 'appsforyourdomain/connection'
module AppsForYourDomain #:nodoc:
# Google Apps Email Migration API - Example Client in Ruby
#
# == What Is This Library?
#
# This API enables partners to migrate email to GMail
#
# This module expects REXML Ruby module to be already installed
#
# There are two different groups who can migrate mail:
#
# * A domain administrator can migrate mail to any mailbox, by
specifying
# the username of the mailbox to be migrated, and specifiying
# the administrator email and password in the API.new call.
# * An end user can migrate mail only to their own mailbox, and
only if an
# administrator has enabled end-user access to migration. The
email
# in the API.new call must correspond to
"[EMAIL PROTECTED]".
#
# On creation of the EmailMigrationAPI object, an authentication
token
# is obtained from the Google client login. Client programs may
then invoke
# the uploadSingleMessage or uploadBatchedMessages methods on the
# object to post messages to the Google Email Migration API.
#
# The uploadSingleMessage and uploadBatchedMessages methods have
# a single mail object or a list of mail objects as their first
# argument respectively. This can be any object that has a to_s
# method that will convert the object to a string representing an
# RFC822-compliant mail message. For example, a TMail object or
the
# contents of a mail message in a file can be used.
#
# Note: Client programs must ensure that single or batch XML files
# posted to GMail are less than 32MB in size. Messages are base64
encoded
# so that they will increase in size about 30%.
#
# == Example (using TMail)
#
# #!/usr/bin/ruby
# require 'tmail'
# require 'appsforyourdomain/migrationapi'
#
# domain = "mydomain.com"
# username = "root"
# email = "[EMAIL PROTECTED]"
# password = "secret"
# a = AppsForYourDomain::EmailMigrationAPI.new(domain, username,
email, password)
#
# mail = TMail.new
# mail.to = '[EMAIL PROTECTED]'
# mail.from = 'Minero Aoki <[EMAIL PROTECTED]>'
# mail.subject = 'test mail'
# mail.date = Time.now
# mail.mime_version = '1.0'
# mail.set_content_type 'text', 'plain', {'charset' => 'utf-8'}
# mail.body = 'This is test mail.'
# a.uploadSingleMessage(mail, ['IS_STARRED', 'IS_UNREAD'],
['Test'])
#
# == Properties for migrated emails
#
# 'IS_DRAFT'
# The message should be marked as a draft when inserted.
# 'IS_INBOX'
# The message should appear in the Inbox, regardless of its
labels.
# (By default, a migrated mail message will appear in the Inbox
only if
# it has no labels.)
# 'IS_SENT'
# The message should be marked as "Sent Mail" when inserted.
# 'IS_STARRED'
# The message should be starred when inserted.
# 'IS_TRASH'
# The message should be marked as "Trash" when inserted.
# 'IS_UNREAD'
# The message should be marked as unread when inserted. Without
this
# property, a migrated mail message is marked as read.
class EmailMigrationAPI
# XML Namespace for Atom feeds
NS_ATOM = 'http://www.w3.org/2005/Atom'
# XML namespace for Google Apps
NS_APPS = 'http://schemas.google.com/apps/2006'
# XML namespace for GData batch results
NS_BATCH = 'http://schemas.google.com/gdata/batch'
# Base URL for email migration requests
BASEURL = 'https://apps-apis.google.com/a/feeds/migration/2.0/'
# Creates an Administrative object
#
# Args:
# - domain: such as "google.com"
# - email: user such as "[EMAIL PROTECTED]"
# - password: Administrator password
# - backend: Email Migration API URL to connect to (normally not
needed)
#
def initialize(domain, username, email, password, backend =
BASEURL)
@domain = domain
@username = username
@conn = AppsForYourDomain::Connection.new(backend)
@conn.user_agent = "Ruby-EmailMigrationAPI/0.1"
creds = {
'Email' => email, 'Passwd' => password,
'accountType' => 'HOSTED', 'service' => 'apps' }
tokens = @conn.clientAuth(creds)
# The Auth value is the authentication token that you'll send to
the
# Email Migration API with your request, so keep a copy of that
value.
# You can ignore the SID and LSID values.
raise 'No authorization' unless tokens.key?('Auth')
@conn.authorization = "GoogleLogin auth=#{tokens['Auth']}"
@backend = backend
end
def self.newXmlDocument(root_element)
doc = REXML::Document.new
doc << REXML::XMLDecl.new("1.0", "UTF-8")
root = doc.add_element(root_element)
root.add_namespace('atom', NS_ATOM)
root.add_namespace('batch', NS_BATCH)
root.add_namespace('apps', NS_APPS)
doc
end
def self.decodeResponse(response) #:nodoc: internal
status = { 'request' => { :code => response.code.to_i, :message
=> response.message } }
doc = REXML::Document.new(response.body)
doc.root.elements.each('atom:entry') do |entry|
batch_id = entry.elements['batch:id']
batch_status = entry.elements['batch:status']
if !batch_id.nil? && !batch_status.nil?
atom_id = entry.elements['atom:id']
status[batch_id.text.to_i] = {
:id => atom_id.nil? ? nil : atom_id.text,
:code => batch_status.attributes['code'],
:message => batch_status.attributes['reason'] }
end
end
status
end
# Encodes, sends, receives decodes message to/from
# email migration service.
# Returns a hash where the batch id (integer 1..n) is the key
# and the value is a has with :code, :message and :id key-value
pairs
#
# On a successful post, each batched item will have a code and
# text message returned.
#
# 201 Created:
# The message was successfully migrated
#
# 400 Bad Request:
# If a message is rejected as malformed, you'll receive a
# 400 Bad Request batch status code
#
# 503 Service Unavailable:
# If your client exceeds the maximum allowed
# rate of message uploads per second, the entries that failed
contain
# the batch status code 503 Service Unavailable. If you receive
that
# status code, then record which entries failed (using their batch
IDs)
# and retry the upload. We recommend using an exponential backoff
# strategy for this process. For example, you might wait thirty
seconds
# and retry the upload; then if your request still returns 503s,
# wait 60 seconds before trying again, and so on.
def request(doc) #:nodoc: internal
# submit and decode
path = "[EMAIL PROTECTED]@domain}/[EMAIL PROTECTED]/mail/batch"
begin
resp = @conn.perform("POST", path, doc.to_s, 'application/atom
+xml')
return EmailMigrationAPI.decodeResponse(resp)
# On an overall malformed request, you'll get a 400 for the
post:
rescue Net::HTTPServerException => e
$stderr.print "#{e} POSTing to #{path}\n"
return { 'request' => { :code =>
e.response.code.to_i, :message => e.response.message } }
end
end
def addEntryContents(entry, rfc822msg, properties=[], labels=[],
batch_id=nil)
entry.add_element('atom:category',
'scheme' => 'http://schemas.google.com/g/2005#kind',
'term' => 'http://schemas.google.com/apps/2006#mailItem')
msg = entry.add_element('apps:rfc822Msg', 'encoding' =>
'base64')
msg.add_text([rfc822msg.to_s].pack('m')) # base64 encoding
properties.each do |prop|
entry.add_element('apps:mailItemProperty', 'value' => prop)
end
labels.each do |label|
entry.add_element('apps:label', 'labelName' => label)
end
if !batch_id.nil?
entry.add_element('batch:id').add_text(batch_id.to_s)
end
end
def uploadBatchedMessages(message_list, properties=[],
labels=[])
doc = EmailMigrationAPI.newXmlDocument('atom:feed')
batch_id = 1
message_list.each do |rfc822msg|
entry = doc.root.add_element('atom:entry')
addEntryContents(entry, rfc822msg, properties, labels,
batch_id)
batch_id += 1
end
request(doc)
end
def uploadSingleMessage(rfc822msg, properties=[], labels=[])
return uploadBatchedMessages([rfc822msg], properties, labels)
# non-batched alternative
# doc = EmailMigrationAPI.newXmlDocument('atom:entry')
# addEntryContents(doc.root, rfc822msg, properties, labels)
# request(doc)
end
end
end
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Google Apps APIs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/google-apps-apis?hl=en
-~----------~----~----~----~------~----~------~--~---