Last active
April 30, 2020 22:12
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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