Skip to content

Instantly share code, notes, and snippets.

@tshakah
Forked from zealot128/imap-stats.rb
Last active December 1, 2015 13:38
Show Gist options
  • Save tshakah/990b4effaab8b7b3aa6d to your computer and use it in GitHub Desktop.
Save tshakah/990b4effaab8b7b3aa6d to your computer and use it in GitHub Desktop.
Imap mail statistic with Ruby
#!/usr/bin/env ruby
# This groups emails into senders and then calculates some basic stats for the
# times of those emails - the earliest, latest and average
#
# Note that there is some oddity relating to my specific needs around timezone
# handling - this is in the code below the comment starting "Normalise"
# These two are for debugging
#require 'awesome_print'
#require 'byebug'
require 'net/imap'
require 'progressbar'
require 'active_support/all'
require 'yaml'
require 'yaml/store'
begin
# Make sure we have everything we need to connect
fail IOError unless File.exist?('settings.yml')
settings = YAML.load_file('settings.yml')
password = ENV['ES_PASSWORD']
fail ArgumentError unless password
fail NameError unless settings['server'] && settings['email']
# Connect and login to the server
imap = Net::IMAP.new(settings['server'], 993, true)
imap.login(settings['email'], password)
imap.select('INBOX.Prices')
# Get all mail in the folder
mail_ids = imap.search(['ALL'])
puts "Found #{mail_ids.count} emails. Fetching mail headers..."
# Create a new progressbar
bar = ProgressBar.new 'progress', mail_ids.count
time_regex = /\d{2}:\d{2}:\d{2}\s([+-]\d{4}|UTC)/
# Fetch mail details
stats = imap.fetch(mail_ids, 'ENVELOPE').map do |mail|
bar.inc
sender = mail.attr['ENVELOPE'].sender.first
time = Time.parse(mail.attr.first.second.date.match(time_regex).to_s).utc
# Normalise the days for my use case
time += 1.day if time.hour < 6 && time.day == Date.current.day ||
time.day == Date.yesterday.day
["#{sender.mailbox}@#{sender.host}", time.to_i]
end
# Calculate the stats for the emails
stats = stats.group_by { |sender, _| sender }
parsed_stats = Hash[stats.map do |group, details|
times = details.map(&:last).sort
[group, {
earliest: Time.at(times.first),
latest: Time.at(times.last),
average: Time.at(times.sum.to_f / times.count)
}]
end]
# Output results
bar.finish
puts ''
parsed_stats.map do |address, numbers|
puts address
puts '-----------------------------'
puts numbers[:earliest].strftime('%H:%M')
puts numbers[:latest].strftime('%H:%M')
puts numbers[:average].strftime('%H:%M')
puts ''
end
rescue IOError
# The setting file doesn't exist, so create it
store = YAML::Store.new('settings.yml')
store.transaction do
store['server'] = nil
store['email'] = nil
end
puts 'Created configuration file - please update it and try again.'
rescue ArgumentError
# Probably no password supplied
puts 'Password not supplied - please supply a value in the ES_PASSWORD ' \
'environment variable'
rescue NameError
# Probably invalid settings
puts 'Settings are invalid. Please check the settings file for server and ' \
'email options'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment