How to reply a message with Gmail API in Ruby? - google-api

I have configured Google api's with my Ruby on Rails project. Also, I have set webhooks for incoming emails.
I have successfully implemented login via Google and get user's inbox messages.
Now, I'm implementing a message reply, but I'm getting "BadRequest" in response.
My code.
uri = URI.parse("https://www.googleapis.com/gmail/v1/users/me/messages/send?access_token=#{access_token}")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/json"
request.body = JSON.dump({
"References" => "\u003cCAAY2B8p2CjEjDKz+sXVBQBrda5i5Lz=Dd4fVC21kfx8fhLLCdg#mail.gmail.com\u003e" ,
"In-Reply-To" => "\u003cCAAY2B8p2CjEjDKz+sXVBQBrda5i5Lz=Dd4fVC21kfx8fhLLCdg#mail.gmail.com\u003e" ,
"Subject" => "Re: Test02" ,
"From" => "email#gmail.com" ,
"To" => "email#gmail.com" ,
"threadId"=> "1764cc4c5efa6855",
# "body" => "This is where the response text will go"
})
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
API call response.
response => #<Net::HTTPBadRequest 400 Bad Request readbody=true>
I need to send a reply using google API.
Thanks in advance.

In order to reply to a message using Google API, I have used this method.
client_secrets = Google::APIClient::ClientSecrets.load("#{Rails.root}/config/client_secrets.json")
auth_client = client_secrets.to_authorization
auth_client.update!(
:scope => 'https://mail.google.com/ https://www.googleapis.com/auth/gmail.modify https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/pubsub',
:redirect_uri => 'http://localhost:3000/google_code',
:additional_parameters => {
"access_type" => "offline", # offline access
"include_granted_scopes" => "true" # incremental auth
}
)
auth_client.code = auth_code
gmail = Google::Apis::GmailV1::GmailService.new
gmail.authorization = auth_client
message = Mail.new
message.date = Time.now
message.subject = "Re: Test02"
message.from = "email#gmail.com"
message.to = "email#gmail.com"
message.message_id = "\u003cCAFVVPDvD-zK6Akj8djj+uam35ZxFTf2EW4AefW1Ri7OV7AxFVA#mail.gmail.com\u003e"
message.part content_type: 'multipart/alternative' do |part|
part.html_part = Mail::Part.new(body: "Using service Account.", content_type: 'text/html; charset=UTF-8')
end
msg = message.encoded
message_object = Google::Apis::GmailV1::Message.new(raw:message.to_s, thread_id: "1764cc4c5efa6855", content_type: 'message/rfc822')
gmail.send_user_message('me', message_object)

Related

Auth on site with SSL, cookie, headers - don't work

For authorization on the site https://app.guardsaas.com me need:
Open https://app.guardsaas.com/login and get the value "_csrf_token"
Make a POST request https://app.guardsaas.com/login_check
with parameters:
'_username' = login
'_password' = pass
'_remember_me' = 'on'
'_csfr_token' = token from p.1
I wrote a script that first gets a token, and then it is authorized with the help of the site, but it does not work, the error can be covered in SSL, cookie, tried out a bunch of different options - nothing comes out
My code:
require "net/http"
require 'net/https'
require "uri"
uri = URI('https://app.guardsaas.com/login')
token = ""
text = ""
http = Net::HTTP.start(uri.host, uri.port,
:use_ssl => uri.scheme == 'https',
:verify_mode => OpenSSL::SSL::VERIFY_NONE)
# make a request to get the server's cookies
response = http.get('https://app.guardsaas.com/login')
puts response.code
if (response.code == '200')
all_cookies = response.get_fields('set-cookie')
cookies_array = Array.new
all_cookies.each { | cookie |
cookies_array.push(cookie.split('; ')[0])
}
cookies = cookies_array.join('; ')
text = response.body.to_s
st = text.index('_csrf_token" value=').to_i
token = text[st+20..st+19+40]
puts "token: " + token
data = {
"_username" => 'login',
"_password" => 'pass',
"_remember_me" => 'on',
"_csrf_token" => token
}
data = URI.encode_www_form(data)
headers = {
'Cookie' => cookies,
'Referer' => 'https://app.guardsaas.com',
'Content-Type' => 'application/x-www-form-urlencoded'
}
headers = URI.encode_www_form(headers)
data = http.post('https://app.guardsaas.com/login_check', data, headers)
puts data.body
end

An error has occurred that says {"code":"BadArgument","requestId":"XXXX","message":"JSON format error."} on computer vision api of Azure

require 'net/http'
uri = URI('https://westus.api.cognitive.microsoft.com/vision/v1.0/analyze')
uri.query = URI.encode_www_form({
# Request parameters
'visualFeatures' => 'Adult',
'details' => 'Celebrities',
'language' => 'en'
})
request = Net::HTTP::Post.new(uri.request_uri)
# Request headers
request['Content-Type'] = 'application/json'
# Request headers
request['Ocp-Apim-Subscription-Key'] = 'caa91cccdgywtduwdxxf530'
# Request body
request.body = "http://instudy.jp/wp-content/uploads/2015/03/doraemon-coming.jpg"
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
http.request(request)
end
puts response.body
I wanted to check the photo whether adult things or not so I wrote the code.
I think there is nothing wrong so I don't know why error's occurred.
environment: ruby 2.3.1
As per the documentaion, the vision api is expecting an image url in 'url' key of request body. Also in your case, you are not passing a valid json as request body. So, replace
request.body = "http://instudy.jp/wp-content/uploads/2015/03/doraemon-coming.jpg"
with
request_body = Hash.new
request_body[:url] = "http://instudy.jp/wp-content/uploads/2015/03/doraemon-coming.jpg"
request.body = request_body.to_json

Ruby API (RabbitMQ create user)

Started working on Ruby a week back. Writing an API to connect to RabbitMQ messaging queue. The command line for adding a new user works.
$ curl -i -u guest:guest -H "content-type:application/json" -XPUT -d'{"password":"pwd","tags":"administrator"}' http://localhost:15672/api/users/username
I need to make this Http Put request from Ruby. The following is my code:
def test_add_user
uri = URI.parse('http://localhost:15672/api/users/karthik/')
uri.to_s
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Put.new(uri.path)
request.basic_auth 'guest', 'guest'
request['Content-Type'] = 'application/json'
request['Accept'] = 'application/json'
request.set_form_data({'password' => 'secret', 'tags' => 'management'})
http.start do |http|
res = http.request(request)
puts res
end
end
This is the result I get
o.test_add_user
#<Net::HTTPUnsupportedMediaType:0x007fd7fb6fe1d8>
=> nil
Does Media type exception relate with Content-Type?
Only application/json is allowed
Should I use anything like to_json? If yes, where should it be used? Thanks in advance.
Regards
Karthik
Thank you Hector and ptd. Fixed it. Attached the working code for future reference.
def test_add_user
uri = URI.parse('http://localhost:15672/api/users/Test1/')
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Put.new(uri.path)
request.basic_auth 'guest', 'guest'
request['Content-Type'] = 'application/json'
request['Accept'] = 'application/json'
request.body = {'password' => 'secret', 'tags' => 'management'}.to_json
http.start do |http|
res = http.request(request)
puts res
end
end
Adds a new user to the RabbitMQ queue

How to POST to exchange a 23andme auth code for a token

The 23andme web site has an API and they give the following instructions:
Send a POST /token/ request with these parameters (client_id and client_secret are on your dashboard):
curl https://api.23andme.com/token/
-d client_id=xxx \
-d client_secret=yyy \
-d grant_type=authorization_code \
-d code=zzz \
-d "redirect_uri=https://localhost:5000/receive_code/"
-d "scope=basic%20rs3094315"
If successful, you'll get a 200 JSON response like this:
{"access_token":"89822b93d2",
"token_type":"bearer",
"expires_in": 86400,
"refresh_token":"33c53cd7bb",
"scope":"rs3094315 basic"}
So, here's what I tried, but it didn't work. I know Ruby, but have never used net/http or uri.
def self.get_token(code)
uri = URI.parse("https://api.23andme.com/token")
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri.path)
request["client_id"] = 'my client id goes here'
request["client_secret"] = 'my client secret goes here'
request["grant_type"] = 'authorization_code'
request["code"] = code
request["redirect_uri"] = 'http://localhost:3000'
request["scope"] = 'names basic haplogroups relatives'
response = https.request(request)
return response.to_s
end
You are doing it right using curl with the -d option to set the parameter in the body of the POST request. However, with the Net::HTTP::Post object, the syntax request["key"] = value is used to set the headers of the Http object.
Use set_form_data to set all the parameters into the body of the POST request.
For example, use it in this way:
request.set_form_data({"client_id" => "my client id goes here", "code" => code})
The following will clarify the above:
$ > request["client_id"] = 'my client id goes here'
# => "my client id goes here"
$ > request.body
# => nil # body is nil!!!
$ > request.each_header { |e| p e }
# "client_id"
# => {"client_id"=>["my client id goes here"]}
$ > request.set_form_data("client_secret" => 'my client secret goes here')
# => "application/x-www-form-urlencoded"
$ > request.body
# => "client_secret=my+client+secret+goes+here" # body contains the added param!!!
I just wanted to post the code that worked. Thanks to Rafa.
def self.get_token(code)
uri = URI.parse("https://api.23andme.com/token")
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(uri.path,
initheader = {'Content-Type' =>'application/json'})
request.set_form_data({"client_id" => 'my client id',
"client_secret" => 'my client secret',
"grant_type" => 'authorization_code',
"code" => code,
"redirect_uri" => 'http://localhost:3000/receive_code/',
"scope" => 'names basic haplogroups relatives'})
response = https.request(request)
data = JSON.load response.read_body
return data["access_token"]
end

devise authentication via ruby script

I have small application, and I will have some external applications put data to this service over http with rest. I already have it working but without authentication. In portal I use devise, and my question is: how to (example desired) authenticate to portal from ruby script level? What to add to following script to authenticate first? I want to protect this controller with devise and then I need authentication part to following script.
require "net/http"
require "json"
#host = "localhost"
#port = 3000
#post_ws = "/external/rd"
#req_body = {
"device" => {
"name" => "device_json",
"operating_system_id" => "7",
"hash_string" => "jfsg3k4ovj0j02jv",
"user_id" => "1"
}
}.to_json
req = Net::HTTP::Post.new(#post_ws, initheader = {'Content-Type' =>'application/json'})
req.body = #req_body
response = Net::HTTP.new(#host, #port).start {|http| http.request(req) }
Regards,
Mateusz
Here is solution:
I used token_authenticatable from devise.
Here is one great answer how to implement it with json. I had some trouble and described them in this question. There is also answer.
Here goes example code:
require "net/http"
require "json"
#host = "localhost"
#port = 3000
#post_sign = "/users/sign_in.json"
#post_ws = "/external/rd"
#req_sign = {
"user" => {
"email" => "some#email.com",
"password" => "123456"
}
}.to_json
sig = Net::HTTP::Post.new(#post_sign, initheader = {'Content-Type' => 'application/json'})
sig.body = #req_sign
http = Net::HTTP.new(#host, #port).start
resp1 = http.request(sig)
puts "Response: #{resp1.code} , Message: #{resp1.message} , Body: #{resp1.body}"
if resp1.code == "200" then
puts "logged in"
json_resp = JSON.parse(resp1.body)
#auth_token = json_resp['auth_token']
#req_body = {
"device" => {
"name" => "device_json",
"operating_system_id" => "7",
"hash_string" => "jfsg3k4ovj0j02jv"
},
"auth_token" => #auth_token
}.to_json
req = Net::HTTP::Post.new(#post_ws, initheader = {'Content-Type' =>'application/json'})
req.body = #req_body
response = http.request(req)
puts "Response: #{response.code} , Message: #{response.message} , Body: #{response.body}"
end
Regards,
Mateusz

Resources