golangとGmail APIで大量の未読メールを既読にする
きっかけ
メールを3年ぶりに整理しようとしたところ、未読メールが20万件ほど溜まっていたので適当に検索して出てきた未読メールの一括既読を試してみたのですが、どうも件数が多すぎてエラーを吐かれているらしい
ブラウザから一括既読する方法についての記事
発生したエラー
上記の方法でも100件ずつすれば問題ないのですが2000回も反復作業はできないので、gmailのAPIを利用して分割して既読にすることにしました
今回作成したコードはこちら
動作環境
~$ go version go version go1.8.3 linux/amd64
OAuth認証
googleのAPIにアクセスするためには認証をしないといけないのでこちらのクイックスタートを見て認証を終えた(認証部分やアクセストークンの保存等の実装は丸まる拝借した)
https://developers.google.com/gmail/api/quickstart/go
後はマニュアルを見つつ、既読にするコードに変更していく
未読メールを100件取得する
メールを取得するメソッドはこちら
https://godoc.org/google.golang.org/api/gmail/v1#UsersMessagesService.List
ただし、上記のメソッドをそのまま利用すると未読既読関係なく最新のメールを100件取得してしまうのでクエリパラメータを加える、それが以下のメソッド
https://godoc.org/google.golang.org/api/gmail/v1#UsersMessagesListCall.Q
上記のメソッドに文字列でブラウザのgmail上で利用できる検索ボックスと同じものを指定して取得するメールを限定できる、今回は未読メールなので is:unread
を指定しました
以上を踏まえて、未読100件のメールを取得するコードは以下のようになる
mes, err := srv.Users.Messages.List(user).Q("is:unread").Do() if err != nil { log.Fatalf("Error: %v", err) }
ちなみに、取得時に件数が0の場合はエラーになる
メールを既読にする
APIのスコープを変更する
未読メールには UNREAD
というラベルが設定されているので、そのラベルをメールから削除して既読にする
チュートリアルのサンプルではAPIのスコープがReadOnlyになっているので、スコープを gmail.GmailModifyScope
に変更しました
config, err := google.ConfigFromJSON(b, gmail.GmailModifyScope) if err != nil { log.Fatalf("Unable to parse client secret file to config: %v", err) }
一度に100件既読にする
メールの状態を変更するメソッドは Modify
と BatchModify
があるが、今回は100件一気に変更したいので BatchModify
を利用する
https://godoc.org/google.golang.org/api/gmail/v1#UsersMessagesService.Modify
https://godoc.org/google.golang.org/api/gmail/v1#UsersMessagesService.BatchModify
先程取得した100件のメールからIDのスライスを作成して UNREAD
ラベルを削除するリクエストの構造体を作成後に実行すれば未読100件の既読が達成できる
ids := []string{} for _, e := range mes.Messages { fmt.Println(e.Id) ids = append(ids, e.Id) } request := &gmail.BatchModifyMessagesRequest{ Ids: ids, AddLabelIds: []string{}, RemoveLabelIds: []string{"UNREAD"}, ForceSendFields: []string{}, NullFields: []string{}, } err = srv.Users.Messages.BatchModify(user, request).Do() if err != nil { log.Fatalf("Error: %v", err) }
未読0件になるまで繰り返す
実は100件の未読メールを取得する際に、取得件数が0の場合はエラーを返すようになっているので、上記の流れをループすればOK
3秒毎に100件ずつ既読にしているので結構時間がかかりますが一日寝かせてみます