2012年2月10日 星期五

Google Mail Contacts Retrieve by Java

說明如何透過 Google Data API 取得 Gmail 的通訊錄,因需求只在通訊錄所以將重點放在通訊錄,以API的規格看來可以操作Gmail的空間應該是不少。


準備執行環境

官網文件上說明需準備以下環境及.jar檔,Servlet只有二個sample會用到,Ant是為 build samples 做準備
  • JDK (Java Development Kit) version 1.5+
  • Apache Ant version 1.7+
  • mail.jar in Sun's JavaMail API 1.4+
  • activation.jar in Sun's JavaBeansActivationFramework. This is only required for media specific APIs including Document List Data API, Picasa Web Album API, and YouTube Data API.
  • servlet.jar in Sun's Servlet API version 2.3+. This is required only if executing code samples in 'sample.authsub' or 'sample.gbase.recipe' packages.

下載Google Data Client Library
  • 下載Google Data Client Library的client library (gdata-src.java-1.x.x.java.zip) 和 samples file (gdata-samples.java-1.x.x.java.zip),下載的版本為1.45.0,將二個zip file解壓縮。




Build & Running Google Data Client Library Samples

  1. 修改 gdata/java/build-src/build.properties (在解壓縮檔中),指定 servlet.jar、mail.jar、activation.jar 在本機的路徑 ,並修改Gmail的帳號及密碼
  2. # Points to a external library dependancies
    servlet.jar=D:\\software\\Google\\GoogleDataProtocol\\servlet-api.jar
    mail.jar=D:\\software\\Google\\GoogleDataProtocol\\mail.jar
    activation.jar=D:\\software\\Google\\GoogleDataProtocol\\activation.jar
    
    # Authentication credentials to use for the samples
    # EDIT-THIS: Add your own Google credentials to run the samples.
    sample.credentials.username=abc@gmail.com
    sample.credentials.password=test1234
    

  3. 因為只取得通訊錄因此只 build contacts sample ,切換到 gdata/java 路徑執行下列指令
  4. ant -f build-samples.xml sample.contacts.run

  5. 執行contacts sample,將mail.jar、activation.jar  copy到gdata的同一層目錄,並在此目錄執行下列指令
  6. java -classpath .;./activation.jar;./mail.jar;./gdata/java/deps/google-collect-1.0-rc1.jar;./gdata/java/deps/jsr305.jar;./gdata/java/lib/gdata-core-1.0.jar;./gdata/java/lib/gdata-client-1.0.jar;./gdata/java/lib/gdata-contacts-3.0.jar;./gdata/java/sample/contacts/lib/ContactsExample.jar sample.contacts.ContactsExample --action=list --username=abc@gmail.com --password=test1234
    --action=listContactsExample的選項,為取得全部的Contacts內容,還有query、add、delete、update可操作。

    顯示其中一筆Contact內容如下:
    Id: http://www.google.com/m8/feeds/contacts/abc%40gmail.com/base/26bdc0708aaed5ed
    Contact name: 萬俟星瑤
    Last updated: 2011-10-06 08:30
    email addresses:
      nfskrbwyr9@tempalias.com rel:http://schemas.google.com/g/2005#home
    group membership info:
      http://www.google.com/m8/feeds/groups/abc%40gmail.com/base/6
    structured name:
     full name: 萬俟星瑤 given name: 星瑤 family name: 萬俟
    Photo link: https://www.google.com/m8/feeds/photos/media/abc%40gmail.com/26bdc0708aaed5ed
      Photo ETag: (No contact photo uploaded)
    Self link: https://www.google.com/m8/feeds/contacts/abc%40gmail.com/thin/26bdc0708aaed5ed
    Edit link: https://www.google.com/m8/feeds/contacts/abc%40gmail.com/thin/26bdc0708aaed5ed
    ETag: "Rno7ejVSLit7I2A9WhdUGEUDTwA."
    

執行此 sample 每次 query contact 都只會顯示25筆,這是API的預設值,下一章節會針對這部份說明如何取得所有的 contact

Retrieve All Contacts by Java


Google Contacts Data API 的 Developer's Guide 有提供 Retrieving all contacts Java Sample ,但因有 Issue 152:printAllContacts example in GData Java documentation is incorrect 這個 Issue ,所以選擇用Issue裡提供的RetrieveTest.java,以下說明用 RetrieveTest.java 為範本來修改成符合自己的需求
import com.google.gdata.client.*;
import com.google.gdata.client.contacts.*;
import com.google.gdata.data.*;
import com.google.gdata.data.contacts.*;
import com.google.gdata.data.extensions.Name;
import com.google.gdata.data.extensions.Email;
import com.google.gdata.data.extensions.Im;
import com.google.gdata.data.extensions.ExtendedProperty;
import com.google.gdata.util.*;
import java.io.IOException;
import java.net.URL;

public class RetrieveTest{
  public static void printEmailContacts(ContactsService myService, String username)
  throws ServiceException, IOException {
    // Request the feed
    URL feedUrl = new URL("http://www.google.com/m8/feeds/contacts/" + username + "@gmail.com/full");
    ContactFeed resultFeed = myService.getFeed(feedUrl, ContactFeed.class);
    // Print the results
    System.out.println(resultFeed.getTitle().getPlainText());
    for (int i = 0; i < resultFeed.getEntries().size(); i++) {
      ContactEntry entry = resultFeed.getEntries().get(i);

      if (entry.hasName()) {
        Name name = entry.getName();
        if (name.hasFullName()) {
          String fullNameToDisplay = name.getFullName().getValue();
          if (name.getFullName().hasYomi()) {
            fullNameToDisplay += " (" + name.getFullName().getYomi() + ")";
          }
          System.out.println(fullNameToDisplay);
        } else {
          System.out.println("<<no full name found>>");
        }

      } else {
        System.out.println("(no name found)");
      }

      System.out.println("Email addresses:");
      for (Email email : entry.getEmailAddresses()) {
        System.out.print("\t" + email.getAddress());
        System.out.print("\n");
        System.out.println("");
      }

      if(i+1 == resultFeed.getEntries().size())
        System.out.println("Total Contact Num: " + resultFeed.getEntries().size());
    }
  }

  public static void main(String[] a) throws com.google.gdata.util.AuthenticationException, com.google.gdata.util.ServiceException, IOException  {
    System.out.print("Username: ");
    String username = System.console().readLine();
    System.out.print("Password: ");
    char[] password = System.console().readPassword();

    ContactsService svc = new ContactsService("Testing");
    svc.setUserCredentials(username, new String(password));
    if(password != null)
      java.util.Arrays.fill(password, '\0');

    printEmailContacts(svc, username);

  }
}

先來執行 RetrieveTest.java 再回過頭來解釋
Compiler RetrieveTest.java
javac -classpath .;./activation.jar;./mail.jar;./gdata/java/deps/google-collect-1.0-rc1.jar;./gdata/java/deps/jsr305.jar;./gdata/java/lib/gdata-core-1.0.jar;./gdata/java/lib/gdata-client-1.0.jar;./gdata/java/lib/gdata-contacts-3.0.jar RetrieveTest.java

Run RetrieveTest.java
java -classpath .;./activation.jar;./mail.jar;./gdata/java/deps/google-collect-1.0-rc1.jar;./gdata/java/deps/jsr305.jar;./gdata/java/lib/gdata-core-1.0.jar;./gdata/java/lib/gdata-client-1.0.jar;./gdata/java/lib/gdata-contacts-3.0.jar RetrieveTest

其中一筆執行結果,同 ContactsExample 一樣只能顯示25筆
萬俟星瑤
Email addresses:
        nfskrbwyr9@tempalias.com
....
Total Contact Num: 25

如要調整顯示的筆數在line-17加上參數max-results,就改為顯示上限是50筆
URL feedUrl = new URL("http://www.google.com/m8/feeds/contacts/" + username + "@gmail.com/full?max-results=50");

如要改為可以換頁在line-17加上參數start-index,下面例子就顯示第11筆~60筆,start-index1開始起跳
URL feedUrl = new URL("http://www.google.com/m8/feeds/contacts/" + username + "@gmail.com/full?start-index=11&max-results=50");

不管是 Client Library Samples 還是 Retrieving all contacts Java Sample 或是 RetrieveTest.java 都是同樣在操作 Google Data Client Library ,只是選擇 RetrieveTest.java 來做說明比較方便理解 API,也符合筆者的需求。

另外有讀者要籍此提醒一下,Google 雖立意良善提供此API,但在茫茫網海如任意提供自己的帳號/密碼不只通訊錄,要取得你所有mail也是可以達成的。



相關設定可參考:
Getting Started with the Google Data Java Client Library
Google Contacts Data API Reference Guide

沒有留言:

張貼留言