How send email with BCC header via GMAIL API? - ruby-on-rails

How can I send email with BCC via GMAIL API? I send emails to TO or CC but BCC doesn't work. I use Base64.urlsafe_encode64(email.to_s)and this code create string without BCC. My working code example:
email = Mail.new
email.date = Time.now
email.subject = subject
email.to = email_array_to_email_to(to)
email.cc = email_array_to_email_to(cc)
email.bcc = email_array_to_email_to(bcc)
email.reply_to = email_array_to_email_to(reply_to)
email.html_part do
body message
end
request = {
api_method: #google_api.users.messages.to_h['gmail.users.messages.send'],
parameters: { userId: 'me' },
body_object: {
raw: Base64.urlsafe_encode64(email.to_s)
},
}
Do I have to call again GMAIL API and send this email with thread id and BCC as TO?
I use google-api-client 0.7.1
EDIT:
Mail object:
#<Mail::Message:70336725981360,
Multipart: true,
Headers: <Date: Tue,
01 Dec 2015 14:09:08 +0100>,
<Reply-To: >,
<To: ["quatermain32 <my_email#gmail.com>"]>,
<Cc: ["quatermain32 <my_email#gmail.com>"]>,
<Bcc: ["my_email#gmail.com"]>,
<Subject: Test subject>,
<Content-Type: multipart/mixed>>
Mail object with to_s:
"Date: Tue, 01 Dec 2015 14:09:08 +0100\r\n
To: my_email <my_email#gmail.com>\r\n
Cc: my_email <my_email#gmail.com>\r\n
Message-ID: <565d9c6e3cf0b_058b7#Olivers-MacBook-Pro.local.mail>\r\n
Subject: Test subject\r\n
Mime-Version: 1.0\r\n
Content-Type: multipart/mixed;\r\n
boundary=\"--==_mimepart_565d9bf468e77_cb0d35e200577a\";\r\n
charset=UTF-8\r\n
Content-Transfer-Encoding: 7bit\r\n
\r\n
\r\n
----==_mimepart_565d9bf468e77_cb0d3ff88645e200577a\r\n
Content-Type: text/html;\r\n
charset=UTF-8\r\n
Content-Transfer-Encoding: 7bit\r\n
\r\n
<p>Test content</p>\r\n
----==_mimepart_565d9bf468e77_cb0d3ff88645e200577a--\r\n
"

You have to manually add the bcc header to the email, it will not be sent to the recipients. Same as gmail-ruby-api does it https://github.com/jhk753/gmail-ruby-api/blob/e0d62a751bc31397926c5800532f26e185e00b16/lib/gmail/message.rb
encoded = mail.encoded
if bcc = mail.bcc.join(",").presence
encoded.prepend "Bcc: #{bcc}\n"
end
... send email ...

Related

Ruby on Rails: How to attach a file to an email

I am trying to send an email with an attachment from my Rails project. I am using the Google API specifically the gmail_v1 API.
I have been able to get my code to send an email with a subject and a body, but have not been able to attach a CSV. The name of the CSV is "results.csv"
m = Mail.new(
to: "to#gmail.com",
from: "from#gmail.com",
subject: "Test Subject",
body:"Test Body")
m.attachments['shoes.csv'] = {mime_type: 'results.csv', content: CSV}
message_object = Google::Apis::GmailV1::Message.new(raw:m.to_s)
service.send_user_message("me", message_object)
Without the line:
m.attachments['shoes.csv'] = {mime_type: 'results.csv', content: CSV}
The code works, but without the attachment. What is the correct way to add the attachment?
You are sending wrong arguments to the attachments.
attachments should be send as below
attachments['shoes.csv'] = { mime_type: 'text/csv', content: File.read("path/to/csv/or/generator/methos") }
Updated code will be as
m = Mail.new(
to: "to#gmail.com",
from: "from#gmail.com",
subject: "Test Subject",
body:"Test Body")
m.attachments['shoes.csv'] = { mime_type: 'text/csv', content: File.read("path/to/csv/or/generator/methos") }
message_object = Google::Apis::GmailV1::Message.new(raw:m.to_s)
service.send_user_message("me", message_object)
Hope this will help

rails no bitesize error to 3rd party API response

I have a rails app and I'm trying to get calendar freebusy events from google. When I run the following code I get undefined method "bytesize" for #<Hash.. error for the result = client.execute(.... method. I checked out some other stackoverflow answers, but I can't see what I'm doing wrong. Anyone can tell me how I should deal with this problem?
controller
include GoogleCalendarApi
......
#user = current_user
#google = #user.socials.where(provider: "google_oauth2").first
unless #google.blank?
# #client = get_busy_events(#google)
# #result = open_gcal_connection(get_busy_events, #client, #google)
#result = get_busy_events(#google)
end
.....
lib/google_calendar_api.rb
def init_google_api_calendar_client(google_account)
#method only called if google_oauth2 social exists
client = Google::APIClient.new
client.authorization.access_token = google_account.token
client.authorization.client_id = ENV['GOOGLE_API_KEY']
client.authorization.client_secret = ENV['GOOGLE_API_SECRET']
client.authorization.refresh_token = google_account.refresh_token
return client
end
def get_busy_events(social_object)
client = init_google_api_calendar_client(social_object)
old_token = client.authorization.access_token
service = client.discovered_api('calendar', 'v3')
result = client.execute(
api_method: service.freebusy.query,
body: { timeMin: '2015-12-24T17:06:02.000Z',
timeMax: '2016-01-30T17:06:02.000Z',
items: [{ id: social_object.email }]},
headers: {'Content-Type' => 'application/json'})
new_token = client.authorization.access_token
if old_token != new_token
social_object.update_attribute(token: new_token)
end
return result
end
full error:
Google::APIClient - Initializing client with options {}
21:33:15 puma.1 | Google::APIClient - Please provide :application_name and :application_version when initializing the client
21:33:15 puma.1 | Google::APIClient::Request Sending API request get https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest {"User-Agent"=>"google-api-ruby-client/0.8.6 Mac OS X/10.10.4\n (gzip)", "Accept-Encoding"=>"gzip", "Content-Type"=>""}
21:33:15 puma.1 | Decompressing gzip encoded response (12528 bytes)
21:33:15 puma.1 | Decompressed (103479 bytes)
21:33:15 puma.1 | Google::APIClient::Request Result: 200 {"expires"=>"Thu, 31 Dec 2015 05:36:09 GMT", "date"=>"Thu, 31 Dec 2015 05:31:09 GMT", "etag"=>"\"ye6orv2F-1npMW3u9suM3a7C5Bo/U5WRLEvUgzkUohB7qwzTs2ir15o\"", "vary"=>"Origin, X-Origin", "content-type"=>"application/json; charset=UTF-8", "x-content-type-options"=>"nosniff", "x-frame-options"=>"SAMEORIGIN", "x-xss-protection"=>"1; mode=block", "content-length"=>"12528", "server"=>"GSE", "age"=>"126", "cache-control"=>"public, max-age=300, must-revalidate, no-transform", "alternate-protocol"=>"443:quic,p=1", "alt-svc"=>"quic=\":443\"; ma=604800; v=\"30,29,28,27,26,25\"", "connection"=>"close"}
21:33:15 puma.1 | Google::APIClient::Request Sending API request post https://www.googleapis.com/calendar/v3/freeBusy {"User-Agent"=>"google-api-ruby-client/0.8.6 Mac OS X/10.10.4\n (gzip)", "Content-Type"=>"application/json", "Accept-Encoding"=>"gzip", "Authorization"=>"Bearer ya29.WQKv43gUEb0Jt3jTBevBs0_Z9VurfGxmbH8Knv8E9Sqbw4zxeCHjydwUeyo3MSAotYj0", "Cache-Control"=>"no-store"}
21:33:15 puma.1 | Completed 500 Internal Server Error in 382ms (ActiveRecord: 0.8ms)
21:33:15 puma.1 |
21:33:15 puma.1 | NoMethodError - undefined method `bytesize' for #<Hash:0x007fb6d25b9330>:
21:33:15 puma.1 | /Users/Silo/.rvm/rubies/ruby-2.2.3/lib/ruby/2.2.0/net/http/generic_request.rb:182:in `send_request_with_body'
21:33:15 puma.1 | /Users/Silo/.rvm/rubies/ruby-2.2.3/lib/ruby/2.2.0/net/http/generic_request.rb:120:in `exec'
From Pardeep's link, try
result = client.execute(
api_method: service.freebusy.query,
body: URI.encode_www_form({ timeMin: '2015-12-24T17:06:02.000Z',
timeMax: '2016-01-30T17:06:02.000Z',
items: [{ id: social_object.email }]}),
headers: {'Content-Type' => 'application/json'})
The problem is that the body could not be sent as a hash. You should encode as an string.

Sending HTML email using gmail API in ruby

I am creating a ruby script and it should do the above. Over the day I was trying to crack I way to send an HTML email to a selected number of emails addresses. There is no clear documentation on how I should do, So please I will appreciate you helping.
Here is my code, The script is successfully authorizing a user and picking the code to access his/her gmail account. Now I want to send the HTML email on behalf of that user.
require 'rubygems'
require 'google/api_client'
require 'launchy'
CLIENT_ID = 'my_app_Id_on_gmail_developers_console'
CLIENT_SECRET = 'the_secret_key'
OAUTH_SCOPE = 'https://mail.google.com/'
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
# Create a new API client & load the Google Drive API
client = Google::APIClient.new(:application_name => 'Ruby Gmail sample',
:application_version => '1.0.0')
gmail = client.discovered_api('gmail', "v1")
# Request authorization
client.authorization.client_id = CLIENT_ID
client.authorization.client_secret = CLIENT_SECRET
client.authorization.scope = OAUTH_SCOPE
client.authorization.redirect_uri = REDIRECT_URI
uri = client.authorization.authorization_uri
Launchy.open(uri)
# Exchange authorization code for access token
$stdout.write "Enter authorization code: "
client.authorization.code = gets.chomp
client.authorization.fetch_access_token!
#testing if it is working well by counting the emails.
#emails = client.execute(
api_method: gmail.users.messages.list,
parameters: {
userId: "me"},
headers: {'Content-Type' => 'application/json'}
)
count = #emails.data.messages.count
puts "you have #{count} emails "
# Pretty print the API result
jj #emails.data.messages
how can I do this? is there a way I can an external html file which is the email file to be sent. then I can sent this file using the script?
I partially accept the answer above since you can send an email through STMP pretty easily but with the gmail API it's even easier. According your code it should looks like this:
message = Mail.new
message.date = Time.now
message.subject = 'Supertramp'
message.body = "<p>Hi Alex, how's life?</p>"
message.content_type = 'text/html'
message.from = "Michal Macejko <michal#macejko.sk>"
message.to = 'supetramp#alex.com'
service = client.discovered_api('gmail', 'v1')
result = client.execute(
api_method: service.users.messages.to_h['gmail.users.messages.send'],
body_object: {
raw: Base64.urlsafe_encode64(message.to_s)
},
parameters: {
userId: 'michal#macejko.sk'
},
headers: { 'Content-Type' => 'application/json' }
)
response = JSON.parse(result.body)
For multi-part email with the attachment:
message = Mail.new
message.date = Time.now
message.subject = 'Supertramp'
message.from = "Michal Macejko <michal#macejko.sk>"
message.to = 'supetramp#alex.com'
message.part content_type: 'multipart/alternative' do |part|
part.html_part = Mail::Part.new(body: "<p>Hi Alex, how's life?</p>", content_type: 'text/html; charset=UTF-8')
part.text_part = Mail::Part.new(body: "Hi Alex, how's life?")
end
open('http://google.com/image.jpg') do |file|
message.attachments['image.jpg'] = file.read
end
Just my input. I was able to create a script that emailed html to multiple users in about 100 lines. Without using an api. You need to look into using smtp. It is very simple. You define a server for it to use and then you use it's "send_message" method. Here's a link to a good site! GOOD SITE
I can't post my whole code here for security reasons however this should get you started
class Email_Client
attr_accessor :message_contents, :subject
def initialize(sender_name, receiver_name, sender_email, receiver_email)
#sender_name = sender_name
#receiver_name = receiver_name
#sender_email = sender_email
#receiver_email = receiver_email
end
def send_html
message = <<MESSAGE
From: #{#sender_name} <#{#sender_email}>
To: #{#receiver_name} <#{#receiver_email}>
MIME-Version: 1.0
Content-type: text/html
Subject: #{subject}
#{message_contents}
MESSAGE
Net::SMTP.start('SeRvEr_HeRe') do |smtp|
smtp.send_message message,
#sender_email,
#receiver_email
end
end

Rails gmail gem: Get correct address of sender and message body

I'm using nu7'hatch/gmail gem to get into my Gmail account and get the e-mails. I can grab the Date and Subject correctly, but for the From and Body I also get these characters and I'm not able to simply get the text:
From:
--- - !ruby/struct:Net::IMAP::Address name: [NAME_OF_SENDER_IS_HERE] route: mailbox: [USERNAME_OF_SENDER_IS_HERE] host: gmail.com
Body:
--- !ruby/object:Mail::Body boundary: preamble: epilogue: charset: US-ASCII part_sort_order: - text/plain - text/enriched - text/html parts: !ruby/array:Mail::PartsList [] raw_source: [MESSAGE_GOES_HERE] encoding: 7bit
Is there any way to correctly get the From and Body text, without these characters?
A work-around that I found is with Net::IMAP.
Note that the email needed from From is done mail.from[0].
imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs = nil, verify = false)
imap.login(USERNAME, PASSWORD)
imap.select('Inbox')
imap.search(["ALL"]).each do |message_id|
emails = imap.fetch(message_id,'RFC822')[0].attr['RFC822']
mail = Mail.read_from_string emails
#email = Email.create(:subject => mail.subject, :message => mail.body.decoded, :sender => mail.from[0], :date => mail.date)
end
imap.disconnect
You could do something like
This line returns the complete struct:
gmail.inbox.find(subject: "yoursubject").first.envelope
...on the struct you can:
gmail.inbox.find(subject: "yoursubject").first.envelope.reply_to[0].mailbox
gmail.inbox.find(subject: "yoursubject").first.envelope.reply_to[0].name
gmail.inbox.find(subject: "yoursubject").first.envelope.reply_to[0].host
...and then do your manipulations to combine into a single string which would be evaluated to:
name <sample#sample.com>

ruby mailman remove header from email body

I am trying to display an email body in my RoR project.
class IncomingMail
def initialize(message, params)
if person = Person.find_by_email(message.from)
changeMessage = Message.where({person_id: person.id})
#message = message.subject.force_encoding("UTF-8")
message = message.body.encoded
changeMessage.first.text = message
changeMessage.first.backInMinutes = 0
changeMessage.first.showText = 1
changeMessage.first.doNotDisturb = 0
changeMessage.first.save
end
end
but i also get the email header
> --e89a8ff1c0465030f204c082e054 Date: Mon, 21 May 2012 04:45:12 +0200 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1
> Content-Transfer-Encoding: 7bit Content-ID:
> <4fb9ac38c71d2_1e1343dd8042105b#ubuntu.mail> Text of the mail
how can I remove the header ?
with the subject it works like this
message = message.subject.force_encoding("UTF-8")
But not with the body.
I have found the solution!!!
change:
message = message.body.encoded
to:
message = message.text_part.body.decoded
that cuts all the header details away and gives me only the TEXT of the email.
It took a long time but it worked I hope it also helps other users

Resources