English | Site Directory

Google Apps APIs

Google Apps Email Migration API Developer's Guide: .NET

The Google Apps Email Migration API allows administrators and users of Google Apps to migrate mail from legacy email systems into their domain's hosted Gmail accounts. Your client application can upload email messages into these accounts using standard Google data API feeds.

Note: This API is only available to Google Apps Premier, Education, and Partner Edition domains, and cannot be used for migration into Google Apps Standard Edition email or Gmail accounts.

Contents

  1. Audience
  2. Getting Started
  3. Authenticating to the Email Migration service
    1. ClientLogin username/password authentication
  4. Migrating email messages
    1. Sample RFC 822 email message
  5. Usage notes and troubleshooting

Audience

This document is intended for programmers who want to write client applications to allow domain administrators or end users to migrate email into Google Apps mailboxes. It provides a series of examples of basic data API interactions using the .NET client library, with explanations. After reading this document, you may wish to learn more about the underlying protocol (that is, the actual XML messages sent and the HTTP requests used to transmit them) by reading the protocol section of this developer's guide.

This document assumes that you understand the general ideas behind the Google data APIs.

For Apps Email Migration API reference information, see the reference guide.

Getting Started

You may want to create a Google Apps account for testing purposes. Email Migration uses Google Apps Accounts, so if you already have a test Google Apps account, you're all set. You can create new test accounts with the Google Apps control panel.

To use the .NET client library, you'll need version 1.1 or later of the .NET runtime, and you should also be current on all patches. After downloading the client library, you'll find the DLLs you need to get started in the lib/Release subdirectory of the distribution.

A full working copy of this sample is available in the GData project in the project hosting section of code.google.com. The sample is located at /trunk/clients/cs/samples/appsforyourdomain/migration/gapps_migration_sample.cs in the SVN repository accessible from the Source tab.

After compiling the sample, run it as follows:

gapps_migration_sample <domain> <userEmail> <password> [destinationEmail]

where domain is your Google Apps domain name, and userEmail and password are your administrator login credentials. Optionally, you may specify another email address on the domain, destinationEmail, into which the sample application will migrate mail messages. For example, if you're the owner of example.com, and you want to try migrating mail into test@example.com, invoke the sample as follows:

gapps_migration_sample example.com admin@example.com your_password test@example.com

The sample performs a number of operations to demonstrate the process of migrating mail into a hosted Gmail account. For more details, see the RunSample method of the code.

To compile the examples in this document into your own code, you'll need to use the following using statements:

using Google.GData.Apps.Migration;
using Google.GData.Client;
using Google.GData.Extensions.Apps;

The MailItemService class represents a connection to the feed that allows you to migrate mail messages into a hosted Gmail account. This feed is described in more detail below.

For more information, see Getting Started with the .NET Client Library.

Authenticating to the Email Migration service

To migrate email messages, you must first authenticate using the ClientLogin authentication system. To use this system, you submit the email address and password of the domain user or administrator making the request. The authentication service returns an authentication token that your client can then send to the Email Migration API service along with every subsequent request on behalf of that user.

ClientLogin username/password authentication

To authenticate to the Email Migration service using ClientLogin, create a new MailItemService object, and invoke its setUserCredentials method, as follows:

MailItemService mailItemService = new MailItemService(domain, "Sample Migration Application");
mailItemService.setUserCredentials(userEmail, password);

Replace domain with your domain name, userEmail with the email address of the user to authenticate (usually an administrator), and password with that user's password.

For more information about the ClientLogin authentication system, see the Google Account Authentication for Installed Applications documentation.

Migrating email messages

To migrate mail messages into a hosted Gmail account, start by creating a MailItemEntry object for each message you're migrating, as demonstrated in the following example:

MailItemEntry entry = new MailItemEntry();

entry.Rfc822Msg = new Rfc822MsgElement(rfcTextOfMessage);

entry.MailItemProperties.Add(MailItemPropertyElement.STARRED);
entry.MailItemProperties.Add(MailItemPropertyElement.UNREAD);

entry.Labels.Add(new LabelElement("Friends"));
entry.Labels.Add(new LabelElement("Event Invitations"));

Set or add the following attributes:

  • An Rfc822MsgElement object, containing the RFC 822 content of the email message. (See below for an example.)
  • Optionally, one or more MailItemProperty objects, corresponding to properties that the server should apply to the message when the message is inserted into Gmail. Each MailItemProperty must be one of the following:
    MailItemPropertyElement.DRAFT
    The message should be marked as a draft when inserted.
    MailItemPropertyElement.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.)
    MailItemPropertyElement.SENT
    The message should be marked as "Sent Mail" when inserted.
    MailItemPropertyElement.STARRED
    The message should be starred when inserted.
    MailItemPropertyElement.TRASH
    The message should be marked as "Trash" when inserted.
    MailItemPropertyElement.UNREAD
    The message should be marked as unread when inserted. Without this property, a migrated mail message is marked as read.
  • Optionally, one or more LabelElement objects, corresponding to Gmail labels that should be applied to the message when it is inserted. In the example above, we're specifying that the message should have the "Friends" and "Event Invitations" labels in Gmail.

It's possible to post a single mail item entry at a time, but in most cases when you're migrating mail you'll be migrating multiple entries at once. We therefore recommend that you take advantage of the batch insertion feature of the Email Migration API, which greatly reduces the number of HTTP requests you have to make and thereby lowers your client's bandwidth.

To insert your mail items in a batch, construct an array of MailItemEntry objects (named entries in the following example) and initialize each one as shown above. Then "tag" each entry with a batch ID so you can track the status of each one:

for (int i = 0; i < entries.Length; i++)
{
  entries[i].BatchData = new GDataBatchEntryData();
  entries[i].BatchData.Id = i.ToString();
}

Then post the entries as follows:

MailItemFeed feed = mailItemService.Batch(domain, username, entries);

There are two different groups who can migrate mail:

  • A domain administrator can migrate mail to any mailbox, by specifying a username to be used in the above code.
  • An end user can migrate mail only to their own mailbox, and only if an administrator has enabled end-user access to migration. The username in the above code must be the same as the currently authenticated username.

If your request is successful, the server returns a feed containing the inserted mail item entries. You can check the batch status of each entry in the feed that's returned to determine if the insertion succeeded, as follows:

foreach (AtomEntry entry in batchResult.Entries)
{
    GDataBatchEntryData batchData = entry.BatchData;

    Console.WriteLine("Mail message {0}: {1} {2}",
        batchData.Id, batchData.Status.Code, batchData.Status.Reason);
}

For more information about batched insertion requests, see the reference documentation on batch processing with Google data APIs.

Sample RFC 822 email message

Below is a sample RFC 822 email message that might appear in an <apps:rfc822Msg> element. For more information about this format, including an explanation of how each field is interpreted, refer to the official RFC 822 standard definition.

Received: by 140.23.6.190 with HTTP; Mon, 16 Jul 2007 10:12:26 -0700 (PDT)
Message-ID: <c8acb6980707161012i5d395392p5a6d8d14a8582613@mail.gmail.com>
Date: Mon, 16 Jul 2007 10:12:26 -0700
From: "Elizabeth Bennet" <bennet@example.com>
To: "Fitzwilliam Darcy" <darcy@example.com>
Subject: Lunch on Monday
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Delivered-To: darcy@example.com

This is the body of the email message.  Would you like to have lunch this week?

The client library ensures that characters in the message aren't interpreted as XML, so if you use the .NET client library, you don't need to worry about things like escaping the angle brackets. However, if your message is encoded in a format other than plain ASCII, we recommend using Base64 encoding to ensure proper transmission. To do this, supply the Base64-encoded form of the message in the Rfc822MsgElement constructor as follows:

new Rfc822MsgElement(base64EncodedMessage, Rfc822MsgElement.EncodingMethod.BASE64)

There are a variety of online tools and sample programs that demonstrate the process of encoding text in Base64. If you are using the .NET 2.0 Framework, you can also use the standard Convert.ToBase64String() method to perform the encoding.

Note: Each line in an RFC 822 message should be terminated by a CR+LF (that is, "\r\n") style newline.

Usage notes and troubleshooting

Here are some notes about limits and error situations:

  • You may send a maximum of 32MB of data in each HTTP POST request.
  • The Gmail server may reject malformed messages. In particular, make sure that each message has at least the From:, To:, and Date: header fields required by the RFC822 specification. If a message is rejected as malformed, you'll receive a 400 Bad Request batch status code.
  • 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.