Problem:

Solution:

$ gmail-grouper -c ~/credentials.json -l 1000 | sort | uniq -c | sort -n
..
  9 Netflix <[email protected]>
  10 "Amazon.com" <[email protected]>
  10 "Cars.com" <[email protected]>
  10 "Chewy.com" <[email protected]>
  10 NYT Cooking <[email protected]>
  10 Wayfair <[email protected]>
  11 Patreon <[email protected]>
  12 "Tenri (via Twitter)" <[email protected]>
  14 Humble Bundle <[email protected]>
  15 Glassdoor Jobs <[email protected]>
  16 Flour Bakery <[email protected]>
  17 Reddit <[email protected]>

Why?

The way I usually go about cleaning up my Gmail is like this:

  1. Find the most recent message in my inbox that looks like spam
  2. Search for that sender and archive anything important (receipts, etc)
  3. Delete the rest of the messages

I like to hit the biggest offenders first - it's much more satisfying to remove 30 messages, over removing a paltry 5. However, Gmail has no functionality that lets me group messages by sender, i.e. see who has sent me the most messages. Gmail API to the resc!

Exploring the Gmail API

The Golang SDK docs are very helpful. A quick cut-and-paste job and retrieval of credentials is i all you need. From there, the API Reference is pretty straight ahead.

I was able to find the command to list messages pretty easily:

messageList, err := srv.Users.Messages.List("me").Do()

I was a bit confused at this point, because it's not incredibly clear from the docs where parameters should be called - you would be too if you've ever tried to understand an SDK from looking at a GoDoc page - until I realized this looked exactly like an instance of method chaining. Whammo:

messageList, err := srv.Users.Messages.List("me").MaxResults(int64(pageLength)).PageToken(token).IncludeSpamTrash(false).Do()

Great! Got all the messages... until I realized that the Gmail API doesn't return any data along with the messages (including the sender). This is... gigantically expensive:

for _, msg := range *messageList {
		fullMsg, err := srv.Users.Messages.Get("me", msg.Id).Do()
		...
}

Unfortunately, there's not much I can do about this, unless I do something like this instead:

  1. Grab the first page of messages