Howto read and save gmail attachments using Gmail API

September 10, 2019

# First of all you have to generate credentials.json file by enabling Gmail API.
# After running sciprt first time used should approve the request and token.yaml file will be generated.
# After that script can work without user interaction.
# To activate GMAIL API please open this URL and click 'Enable The Gmail API'
# https://developers.google.com/gmail/api/quickstart/ruby
# gmail api gem documentation - https://www.rubydoc.info/github/google/google-api-ruby-client/Google/Apis/GmailV1/GmailService

require "google/apis/gmail_v1"
require "googleauth"
require "googleauth/stores/file_token_store"
require "fileutils"

OOB_URI = "urn:ietf:wg:oauth:2.0:oob".freeze
APPLICATION_NAME = "Gmail API Ruby Quickstart".freeze
CREDENTIALS_PATH = "credentials.json".freeze
# The file token.yaml stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
TOKEN_PATH = "token.yaml".freeze
SCOPE = Google::Apis::GmailV1::AUTH_GMAIL_READONLY

##
# Ensure valid credentials, either by restoring from the saved credentials
# files or intitiating an OAuth2 authorization. If authorization is required,
# the user's default browser will be launched to approve the request.
#
# @return [Google::Auth::UserRefreshCredentials] OAuth2 credentials
def authorize
  client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH
  token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH
  authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store
  user_id = "default"
  credentials = authorizer.get_credentials user_id
  if credentials.nil?
    url = authorizer.get_authorization_url base_url: OOB_URI
    puts "Open the following URL in the browser and enter the " \
         "resulting code after authorization:\n" + url
    code = gets
    credentials = authorizer.get_and_store_credentials_from_code(
      user_id: user_id, code: code, base_url: OOB_URI
    )
  end
  credentials
end

def filesize(size)
  units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'Pib', 'EiB']

  return '0.0 B' if size == 0
  exp = (Math.log(size) / Math.log(1024)).to_i
  exp = 6 if exp > 6

  '%.1f %s' % [size.to_f / 1024 ** exp, units[exp]]
end

# Initialize the API
service = Google::Apis::GmailV1::GmailService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize

user_id = "me"
query   = "from:TARGET@EMAIL.com has:attachment"
result  = service.list_user_messages(user_id, q: query)

message_ids = result.messages.map(&:id)

message_ids.each_with_index do |id, index|
  attachment_id = service.get_user_message(user_id, id).payload.body.attachment_id
  attachment    = service.get_user_message_attachment(user_id, id, attachment_id)

  File.open("attachment_#{index}.csv", "wb") {|f| f.puts attachment.data }
  puts "Saved attachment size is: #{filesize(attachment.size)}"
end
Howto read and save gmail attachments using Gmail API - September 10, 2019 - {"name"=>"Stanislav Knyazev", "email"=>"extazystas@gmail.com"}