2012/12/19

PowerShellでGoogle Apps Email Migration APIを呼び出す

PowerShell Advent Calendar 2012参加企画。

この記事では、PowerShellでGoogle Apps Email Migration APIを呼び出すC#サンプルスクリプトをPowerShellに移植したものを紹介する。

PowerShellの利点はいくつもあるが、特筆すべきは以下の点だろう。
  • 対話的コマンドラインインターフェース(CLI)を備えている
  • プログラミング言語として現代的な文法を備えている
  • .NET Frameworkを扱うことができる
最初と二番目は、PowerShellは、CMD.exeでできたことを網羅しつつ、現代的な文法を備えたスクリプト言語、と言うことだ。Windows標準環境では、CMD.exeを使うことができたが、文法が貧弱でプログラミングが困難だった。同じくWindows標準環境では、VBScriptやJScriptなどの現代的なスクリプト言語が使えたが、対話的CLIが無かった。
三番目だが、Windows標準環境では、.NET Frameworkの重要度が上がっているが、CMD.exeではこれを直接扱う方法が無かった。PowerShellでは可能になった。

そこで、この記事では、PowerShellから.NET Frameworkへアクセスするスクリプトを紹介する。ただ、PowerShellから標準的な.NET Frameworkのライブラリにアクセスする方法は、他にもいい記事があるので、改めて紹介する意味は薄い。ここでは少し趣向を変え、PowerShellからGoogle Apps Email Migration APIを使う例を紹介する。Google Apps Email Migration APIのクライアントライブラリは、Java版・Python版の他に.NET版も提供されている。このサンプルスクリプトmigrationsample.csをPowerShellに移植した。コードmigrationsample.ps1(ダウンロード)は以下の通り。
<#
.SYNOPSIS
Sample script to demonstrate the use of the Google Apps Domain Migration API client library.

.DESCRIPTION
Sample script to demonstrate the use of the Google Apps Domain Migration API client library.
The original C# version is from https://developers.google.com/google-apps/email-migration/.

.INPUTS
Nothing.

.OUTPUTS
Nothing.
#>

[CmdletBinding()param(
    # The hosted domain (e.g. example.com) in which the migration will occur.
    [String]
    [parameter(Mandatory=$true)]
    $domain,

    # The username of the administrator or user migrating mail.
    [String]
    [parameter(Mandatory=$true)]
    $adminUsername,

    # The password of the administrator or user migrating mail.
    [String]
    [parameter(Mandatory=$true)]
    $adminPassword,

    # The username to which emails should be migrated.
    # End users can only transfer mail to their own mailboxes.
    # If unspecified, will default to login_email.
    [String]
    [parameter(Mandatory=$true)]
    $destinationUser = ''
)

#####
$REDIST_PATH = "$Env:ProgramFiles\Google\Google Data API SDK\Redist"
Add-Type -Path "$REDIST_PATH\Google.GData.Apps.dll"
Add-Type -Path "$REDIST_PATH\Google.GData.Client.dll"
Add-Type -Path "$REDIST_PATH\Google.GData.Extensions.dll"

$LabelFriend = New-Object Google.GData.Extensions.Apps.LabelElement("Friends")
$LabelEventInvitations = New-Object Google.GData.Extensions.Apps.LabelElement("Event Invitations")

$PropertyElementINBOX = [Google.GData.Extensions.Apps.MailItemPropertyElement]::INBOX
$PropertyElementSTARRED = [Google.GData.Extensions.Apps.MailItemPropertyElement]::STARRED
$PropertyElementUNREAD = [Google.GData.Extensions.Apps.MailItemPropertyElement]::UNREAD


[String]$rfcTxt = @"
Received: by 10.143.160.15 with HTTP; Mon, 16 Jul 2007 10:12:26 -0700 (PDT)
Message-ID: <_message_id_ mail.gmail.com="mail.gmail.com">
Date: Mon, 16 Jul 2007 10:12:26 -0700
From: "Mr. Serious" <serious adomain.com="adomain.com">
To: "Mr. Admin" <testadmin apps-provisioning-test.com="apps-provisioning-test.com">
Subject: Random Subject
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Delivered-To: testadmin@apps-provisioning-test.com

This is a message delivered via DMAPI
"@

$random = New-Object Random


if($destinationUser -eq '') {
    $destinationUser = $adminUsername
}


$mailItemService = New-Object Google.GData.Apps.Migration.MailItemService($domain, "Sample Migration Application")
$mailItemService.setUserCredentials("$adminUsername@$domain", $adminPassword)


<#
.DESCRIPTION
Generates a random RFC822 message based on the template in rfcTxt.
We have to randomly modify the subject and message ID to prevent duplicate
supression by the Gmail server.

.INPUTS
Nothing.

.OUTPUTS
The randomly-modified RFC822 message.
#>
Function GenerateRandomRfcText
{
    ($rfcTxt -replace "Random Subject", "Random Subject $($random.Next())") `
        -replace "_message_id_", "$($random.Next())"
}


<#
.DESCRIPTION
Helper method to set up a new MailItemEntry.

.INPUTS
Nothing.

.OUTPUTS
The newly created MailItemEntry.
#>
Function SetupMailItemEntry
{
    param(
        # The batch ID for this entry.
        [String]$batchId
    )

    $entry = New-Object Google.GData.Apps.Migration.MailItemEntry

    [void]$entry.Labels.Add($LabelFriend)
    [void]$entry.Labels.Add($LabelEventInvitations)

    [void]$entry.MailItemProperties.Add($PropertyElementINBOX)
    [void]$entry.MailItemProperties.Add($PropertyElementSTARRED)
    [void]$entry.MailItemProperties.Add($PropertyElementUNREAD)

    $entry.Rfc822Msg = New-Object Google.GData.Extensions.Apps.Rfc822MsgElement(GenerateRandomRfcText)

    $entry.BatchData = New-Object Google.GData.Client.GDataBatchEntryData
    $entry.BatchData.Id = $batchId

    $entry
}


<#
.DESCRIPTION
Demonstrates inserting several mail items in a batch.

.INPUTS
Nothing.

.OUTPUTS
A MailItemFeed with the results of the insertions.
#>
Function BatchInsertMailItems
{
    param(
        # The number of entries to insert.
        [Int]$numToInsert
    )

    [Google.GData.Apps.Migration.MailItemEntry[]]$entries = @()

    # Set up the mail item entries to insert.
    foreach($index in 0..($numToInsert-1)) {
        $entries += SetupMailItemEntry([String]$index)
    }

    # Execute the batch request and print the results.
    [Google.GData.Apps.Migration.MailItemFeed]$batchResult = $mailItemService.Batch($domain, $destinationUser, $entries)
    [Google.GData.Client.AtomEntry]$entry = $Null
    foreach($entry in $batchResult.Entries) {
        [Google.GData.Client.GDataBatchEntryData]$batchData = $entry.BatchData

        Write-Host "Mail message $($batchData.Id): $($batchData.Status.Code) $($batchData.Status.Reason)"
    }

    $batchResult
}

try {
    # Insert several emails in a batch.
    [Google.GData.Apps.Migration.MailItemFeed]$batchResults = BatchInsertMailItems(10)
} catch [Google.GData.Client.GDataRequestException] {
    Write-Host ("Operation failed ({0}): {1}" -f $Error[0].Message, $Error[0].ResponseString)
}

使い方は次の通り。
migrationsample.ps1 domain userEmail password [destinationEmail]
ここで、domainは、Google Appsのドメイン名、userEmailpasswordは、対象となるユーザの資格情報。もしdestinationEmailを与えると、対象となるユーザを指定したことになり、その場合、userEmailpasswordは、Google Appsのドメイン管理者の資格情報を与える必要がある。

以下はその実行例。
PS C:\Users\user01> .\migrationsample.ps1 example.co.jp appsmaster 'password' appsuser
Mail message : 201 Created
Mail message : 201 Created
Mail message : 201 Created
Mail message : 201 Created
Mail message : 201 Created
Mail message : 201 Created
Mail message : 201 Created
Mail message : 201 Created
Mail message : 201 Created
Mail message : 201 Created
PS C:\Users\user01>
この例では、10通すべてのメールデータの処理結果が状態コード201で、Google Apps上に移行されたことが判る。

なお、このコードを実行するためには、事前に次の作業を実行しておく必要がある。
  1. Google Data APIクライアントライブラリのダウンロードおよびインストール
  2. PowerShell実行ポリシの変更

実際のメールデータ移行作業での注意点については、こちらを参照して欲しい。

0 件のコメント: