Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@peterc
Last active April 30, 2020 22:12
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save peterc/3a76f82c2c73807f4f1d9494f54304aa to your computer and use it in GitHub Desktop.
Save peterc/3a76f82c2c73807f4f1d9494f54304aa to your computer and use it in GitHub Desktop.
A Ruby script that checks a Gmail inbox for new mail and shares info about how it was classified
# inboxcheck.rb monitors a Gmail account for new mails and returns
# info (as JSON) about the first new mail from a specified address
#
# This is used to see if our newsletter testing mails arrive at
# Gmail and then if they go into spam, promotions or the normal inbox.
#
# To use or work on this script for yourself, follow steps 1 and 2 at
# https://developers.google.com/gmail/api/quickstart/ruby to get set
# up with the Google API stuff. Make sure client_secret.json ends up
# in the same directory as this script, then you're good to go.
#
# GmailV1 Ruby API docs I found useful:
# http://www.rubydoc.info/github/google/google-api-ruby-client/Google/Apis/GmailV1
#
# P.S. I know the structure and style of this script is hideous,
# but it works for now =)
#
# Peter Cooper (January 12, 2017)
# WTFPL License, except for 'authorize' method which is Apache 2
# licensed by Google (as it's based on their sample code!)
require 'google/apis/gmail_v1'
require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'fileutils'
require 'json'
MAX_TIME_TO_RUN = 600
SLEEP_TIME = 18
MAX_AGE_OF_EMAIL = 0
FROM_EMAIL = ARGV.first || '' # No email specified? Check for any address
SERVICE = Google::Apis::GmailV1::GmailService.new
SERVICE.client_options.application_name = 'InboxChecker'
def authorize
credentials_path = File.join(Dir.home, '.credentials','gmail-api.yaml')
FileUtils.mkdir_p(File.dirname(credentials_path))
client_id = Google::Auth::ClientId.from_file(__dir__ + "/client_secret.json")
token_store = Google::Auth::Stores::FileTokenStore.new(file: credentials_path)
authorizer = Google::Auth::UserAuthorizer.new(client_id, Google::Apis::GmailV1::AUTH_GMAIL_READONLY, token_store)
user_id = 'default'
credentials = authorizer.get_credentials(user_id)
if credentials.nil?
url = authorizer.get_authorization_url(base_url: 'urn:ietf:wg:oauth:2.0:oob')
puts "Open the following URL in the browser and enter the resulting code after authorization:"
puts url
code = gets
credentials = authorizer.get_and_store_credentials_from_code(user_id: user_id, code: code, base_url: 'urn:ietf:wg:oauth:2.0:oob')
end
credentials
end
def get_emails
emails = []
user_id = 'me'
messages = SERVICE.list_user_messages(user_id, include_spam_trash: true, max_results: 8).messages
messages.each do |msg|
id = msg.id
message = SERVICE.get_user_message(user_id, id, format: 'metadata')
headers = Hash[message.payload.headers.map { |h| [h.name, h.value] }]
date = Time.at(message.internal_date.to_i / 1000)
labels = message.label_ids
snippet = message.snippet
from = headers["From"]
subject = headers["Subject"]
status = :unknown
status = :personal if message.label_ids.include?('CATEGORY_PERSONAL')
status = :social if message.label_ids.include?('CATEGORY_SOCIAL')
status = :updates if message.label_ids.include?('CATEGORY_UPDATES')
status = :forums if message.label_ids.include?('CATEGORY_FORUMS')
status = :promotions if message.label_ids.include?('CATEGORY_PROMOTIONS')
status = :spam if message.label_ids.include?('SPAM')
email = { age: (Time.now - date).to_i / 60, from: from, subject: subject, status: status, snippet: snippet }
emails << email
end
emails
end
# --- main program starts here
SERVICE.authorization = authorize
result = nil
start_time = Time.now.to_i
while Time.now.to_i - start_time < MAX_TIME_TO_RUN
STDERR.puts "Fetching email."
emails = get_emails
# Is there a mail < 1 minute old from the address we want?
break if result = emails.detect { |e| e[:age] <= MAX_AGE_OF_EMAIL && e[:from].include?(FROM_EMAIL) }
STDERR.puts "No email found. Waiting #{SLEEP_TIME} seconds."
sleep SLEEP_TIME
end
puts result ? result.to_json : "{}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment