1
2
3
4
5 package main
6
7 import (
8 "bufio"
9 "fmt"
10 "log"
11 "net/http"
12 "os"
13 "sort"
14 "strings"
15
16 gmail "google.golang.org/api/gmail/v1"
17 )
18
19 func init() {
20 registerDemo("gmail", gmail.MailGoogleComScope, gmailMain)
21 }
22
23 type message struct {
24 size int64
25 gmailID string
26 date string
27 snippet string
28 }
29
30
31
32
33
34
35
36
37
38
39 func gmailMain(client *http.Client, argv []string) {
40 if len(argv) != 0 {
41 fmt.Fprintln(os.Stderr, "Usage: gmail")
42 return
43 }
44
45 svc, err := gmail.New(client)
46 if err != nil {
47 log.Fatalf("Unable to create Gmail service: %v", err)
48 }
49
50 var total int64
51 msgs := []message{}
52 pageToken := ""
53 for {
54 req := svc.Users.Messages.List("me").Q("larger:5M")
55 if pageToken != "" {
56 req.PageToken(pageToken)
57 }
58 r, err := req.Do()
59 if err != nil {
60 log.Fatalf("Unable to retrieve messages: %v", err)
61 }
62
63 log.Printf("Processing %v messages...\n", len(r.Messages))
64 for _, m := range r.Messages {
65 msg, err := svc.Users.Messages.Get("me", m.Id).Do()
66 if err != nil {
67 log.Fatalf("Unable to retrieve message %v: %v", m.Id, err)
68 }
69 total += msg.SizeEstimate
70 date := ""
71 for _, h := range msg.Payload.Headers {
72 if h.Name == "Date" {
73 date = h.Value
74 break
75 }
76 }
77 msgs = append(msgs, message{
78 size: msg.SizeEstimate,
79 gmailID: msg.Id,
80 date: date,
81 snippet: msg.Snippet,
82 })
83 }
84
85 if r.NextPageToken == "" {
86 break
87 }
88 pageToken = r.NextPageToken
89 }
90 log.Printf("total: %v\n", total)
91
92 sortBySize(msgs)
93 reader := bufio.NewReader(os.Stdin)
94 count, deleted := 0, 0
95 for _, m := range msgs {
96 count++
97 fmt.Printf("\nMessage URL: https://mail.google.com/mail/u/0/#all/%v\n", m.gmailID)
98 fmt.Printf("Size: %v, Date: %v, Snippet: %q\n", m.size, m.date, m.snippet)
99 fmt.Printf("Options: (d)elete, (s)kip, (q)uit: [s] ")
100 val := ""
101 if val, err = reader.ReadString('\n'); err != nil {
102 log.Fatalf("unable to scan input: %v", err)
103 }
104 val = strings.TrimSpace(val)
105 switch val {
106 case "d":
107 if err := svc.Users.Messages.Delete("me", m.gmailID).Do(); err != nil {
108 log.Fatalf("unable to delete message %v: %v", m.gmailID, err)
109 }
110 log.Printf("Deleted message %v.\n", m.gmailID)
111 deleted++
112 case "q":
113 log.Printf("Done. %v messages processed, %v deleted\n", count, deleted)
114 os.Exit(0)
115 default:
116 }
117 }
118 }
119
120 type messageSorter struct {
121 msg []message
122 less func(i, j message) bool
123 }
124
125 func sortBySize(msg []message) {
126 sort.Sort(messageSorter{msg, func(i, j message) bool {
127 return i.size > j.size
128 }})
129 }
130
131 func (s messageSorter) Len() int {
132 return len(s.msg)
133 }
134
135 func (s messageSorter) Swap(i, j int) {
136 s.msg[i], s.msg[j] = s.msg[j], s.msg[i]
137 }
138
139 func (s messageSorter) Less(i, j int) bool {
140 return s.less(s.msg[i], s.msg[j])
141 }
142
View as plain text