golang gmail API

doyle posted @ 2014年10月23日 10:30 in golang with tags go, gmail, google-api , 2603 阅读
Loading
package main

import (
"flag"
"fmt"
"log"
"net/http"
"strings"

"code.google.com/p/goauth2/oauth"
gmail "code.google.com/p/google-api-go-client/gmail/v1"
)

var (
code      = flag.String("code", "", "Authorization Code")
cachefile = flag.String("cache", "cache.json", "Token cache file")
)

const usageMsg = `
To obtain a request token you must specify both -id and -secret.

To obtain Client ID and Secret, see the "OAuth 2 Credentials" section under
the "API Access" tab on this page: https://console.developers.google.com/

Once you have completed the OAuth flow, the credentials should be stored inside
the file specified by -cache and you may run without the -id and -secret flags.
`

func main() {
flag.Parse()
var config = &oauth.Config{
ClientId:     "",// https://console.developers.google.com/ 新建一个project 后,申请一个oauth 的clientId
ClientSecret: "",// 和ClientSecret
Scope:        gmail.MailGoogleComScope,
RedirectURL:  "urn:ietf:wg:oauth:2.0:oob",
AuthURL:      "https://accounts.google.com/o/oauth2/auth",
TokenURL:     "https://accounts.google.com/o/oauth2/token",
TokenCache:   oauth.CacheFile(*cachefile),
}

client, err := GetOauthClient(config)
if err != nil {
return
}
svc, err := gmail.New(client)
labelId := GetLabelId(svc, "LabelName") // LabelName 替换为gmail 中的label
ScanMessage(svc, labelId)
}

// chan 的设置仍然大了点,超过了google 的api rate limit……
var ch_pages = make(chan string, 5) // NextPageToken的chan
var ch_messageIds = make(chan string, 5) // MessageId的chan

var done = make(chan int) // 未正确使用……

func ScanMessage(svc *gmail.Service, labelId string) {
resp, err := svc.Users.Messages.List("me").LabelIds(labelId).Do()
if err != nil {
log.Fatal(err)
}

if len(resp.NextPageToken) > 0 {
ch_pages <- resp.NextPageToken
}

go func(svc *gmail.Service) {
for {
select {
case resp := <-ch_pages:
go GetPages(svc, resp, labelId)
case msgId := <-ch_messageIds:
go CheckMailMessage(svc, msgId)
}
}
}(svc)

for _, message := range resp.Messages {
ch_messageIds <- message.Id
}

<-done
log.Println("all mail chceked!")
}

// 请求下一页
func GetPages(svc *gmail.Service, pageToken string, labelId string) {
log.Println("PageToken:", pageToken)
resp, err := svc.Users.Messages.List("me").LabelIds(labelId).PageToken(pageToken).Do()
if err != nil {
log.Fatal(err)
}
for _, message := range resp.Messages {
ch_messageIds <- message.Id
}
if len(resp.NextPageToken) > 0 {
ch_pages <- resp.NextPageToken
} else {
done <- 1
}
}

// 请求具体的Message,这里只获取一下From 和Subject 作为判断依据
func CheckMailMessage(svc *gmail.Service, msgId string) {
log.Println("Message.Id:", msgId)
msg, err := svc.Users.Messages.Get("me", msgId).Do()
if err != nil {
log.Fatal(err)
}
var from, subject string
for _, h := range msg.Payload.Headers {
if h.Name == "From" {
lIdx := strings.Index(h.Value, "<")
rIdx := strings.Index(h.Value, ">")
if lIdx > 0 && rIdx < len(h.Value) {
from = strings.TrimSpace(h.Value[lIdx+1 : rIdx])
}
}
if h.Name == "Subject" {
tmp := strings.Split(h.Value, " ")
subject = tmp[len(tmp)-1]
}
}

log.Println(subject, from)

trash := Check(from, subject)
if trash {
log.Println(subject, from, trash)
svc.Users.Messages.Trash("me", msg.Id).Do()
}
}

// 具体的判断规则
func Check(from, subject string) bool {
if from == "xxx@gmail.com" {
return true
}
return false
}

// 根据labelName 获得LabelId
func GetLabelId(svc *gmail.Service, label string) (labelId string) {
list, err := svc.Users.Labels.List("me").Do()
if err != nil {
log.Fatal(err)
}
for _, lbl := range list.Labels { // 可以修改这里,看看你gmail 中所有label 对应的label id
if lbl.Name == label {
labelId = lbl.Id
break
}
}
return
}

// 抄来的oauth 登陆部分
func GetOauthClient(config *oauth.Config) (*http.Client, error) {
transport := &oauth.Transport{Config: config}
// Try to pull the token from the cache; if this fails, we need to get one.
token, err := config.TokenCache.Token()
if err != nil {
if *code == "" {
// Get an authorization code from the data provider.
// ("Please ask the user if I can access this resource.")
url := config.AuthCodeURL("")
fmt.Print("Visit this URL to get a code, then run again with -code=YOUR_CODE\n\n")
fmt.Println(url)
return nil, err
}
// Exchange the authorization code for an access token.
// ("Here's the code you gave the user, now give me a token!")
token, err = transport.Exchange(*code)
if err != nil {
log.Fatal("Exchange:", err)
}
// (The Exchange method will automatically cache the token.)
fmt.Printf("Token is cached in %v\n", config.TokenCache)
}

// Make the actual request using the cached token to authenticate.
// ("Here's the token, let me in!")
transport.Token = token

// Make the request.
return transport.Client(), nil
}