Ruby on Rails: How to attach a file to an email - ruby-on-rails

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

Related

couldn't send mail from mandrill in ruby on rails

Hello I am newbie to ruby on rails, I am trying to send mail from mandrill and following this documentation https://mailchimp.com/developer/transactional/guides/send-first-email/
but somehow I am getting this error
Error: {:status=>500, :response_body=>"{\"status\":\"error\",\"code\":-1,\"name\":\"ValidationError\",\"message\":\"You must specify a message value\"}"}
here is my code
client = MailchimpTransactional::Client.new('xxxxxxxxxRWX-nA')
message = {
from_email: "hello#xxxxx.co",
subject: "Hello world",
text: "Welcome to Mailchimp Transactional!",
to: [
{
email: "xxxxxx#gmail.com",
type: "to"
}
]
}
begin
response = client.messages.send(message)
p response
rescue MailchimpTransactional::ApiError => e
puts "Error: #{e}"
end

Add attachment to email with SendGrid using rails

I've created a hello_world method which sends an email with Sendgrid. I am trying to include an attachment. I've found the following line in another stackoverflow answer: mail.attachments['test.txt'] = File.read("#{Rails.root}/public/test.txt")
This however generates the following error:
Completed 500 Internal Server Error in 17ms (ActiveRecord: 3.4ms)
TypeError - no implicit conversion of String into Integer:
app/controllers/messages_controller.rb:32:in `hello_world'
app/controllers/messages_controller.rb:65:in `create'
Mailing code in controller:
def hello_world(company, message)
from = Email.new(email: "test+#{current_user.auth_token}#example.com")
to = Email.new(email: 'hello#pim.gg')
subject = 'TEST from dev'
content = Content.new(type: 'text/plain', value: "#{company.email} #{current_user} #{current_user.first_name} #{current_user.last_name} #{message.text}")
mail = SendGrid::Mail.new(from, subject, to, content)
mail.attachments['test.txt'] = File.read("#{Rails.root}/public/test.txt")
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
puts response.body
puts response.headers
end
According to documentation of sendgrid-ruby gem adding-attachments should be like this:
attachment = SendGrid::Attachment.new
attachment.content = Base64.strict_encode64(File.open(fpath, 'rb').read)
attachment.type = 'application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet'
attachment.filename = fname
attachment.disposition = 'attachment'
attachment.content_id = 'Reports Sheet'
mail.add_attachment(attachment)

Issue including calendar attachment in Mandrill Mailer and Rails

I'm currently using the icalendar gem to create a new ical calendar and then send it via the mandrill_mailer gem as an attachment. I've tried a variety of different methods - so far I believe I've gotten closest with:
Event.rb
require 'base64'
def self.export_events(user)
#event = Event.last
#calendar = Icalendar::Calendar.new
event = Icalendar::Event.new
event.summary = #event.title
event.dtstart = #event.start_time.strftime("%Y%m%dT%H%M%S")
event.dtend = #event.end_time.strftime("%Y%m%dT%H%M%S")
event.description = #event.desc
event.location = #event.location
#calendar.add_event(event)
encoded_cal = Base64.encode64(#calendar.to_ical)
CalendarMailer.send_to_ical(user, encoded_cal).deliver
end
calendar_mailer.rb
class CalendarMailer < MandrillMailer::TemplateMailer
default from: "blah#blah.com"
# iCal
def send_to_ical(user, encoded_cal)
mandrill_mail template: "ical-file",
subject: "Your iCal file",
to: { email: user.email, name: user.name },
inline_css: true,
async: true,
track_clicks: true,
attachments: [
{
type: "text/calendar",
content: encoded_cal,
name: "calendar.ics",
}
]
end
end
I know my mailer stuff is set up correctly since I'm able to send other types of transactional emails successfully. Also, according to this S.O. post I can't send it directly as a .ics file which is why I'm sending the base64 encoded version of it. Here is the error I keep getting regardless of what I do (whether it's the above or creating a tmp file and opening/reading the newly created tmp file in calendar_mailer.rb):
TypeError: no implicit conversion of nil into String
from /usr/local/rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/base64.rb:38:in pack'
from /usr/local/rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/base64.rb:38:inencode64'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/mandrill_mailer-0.4.13/lib/mandrill_mailer/core_mailer.rb:263:in block in mandrill_attachment_args'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/mandrill_mailer-0.4.13/lib/mandrill_mailer/core_mailer.rb:258:inmap'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/mandrill_mailer-0.4.13/lib/mandrill_mailer/core_mailer.rb:258:in mandrill_attachment_args'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/mandrill_mailer-0.4.13/lib/mandrill_mailer/template_mailer.rb:191:inmandrill_mail'
from /Users/alansalganik/projects/glyfe/app/mailers/calendar_mailer.rb:8:in send_to_ical'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/mandrill_mailer-0.4.13/lib/mandrill_mailer/core_mailer.rb:283:incall'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/mandrill_mailer-0.4.13/lib/mandrill_mailer/core_mailer.rb:283:in method_missing'
from (irb):763
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/railties-4.1.1/lib/rails/commands/console.rb:90:instart'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/railties-4.1.1/lib/rails/commands/console.rb:9:in start'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/railties-4.1.1/lib/rails/commands/commands_tasks.rb:69:inconsole'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/railties-4.1.1/lib/rails/commands/commands_tasks.rb:40:in run_command!'
from /usr/local/rvm/gems/ruby-2.0.0-p481#rails-4.0.2/gems/railties-4.1.1/lib/rails/commands.rb:17:in'
from bin/rails:4:in `require'
Thanks in advance.
Probably not the best code in the world, but an example:
class Outlook
def self.create_cal
#calendar = Icalendar::Calendar.new
event = Icalendar::Event.new
event.summary = "SUMMARY"
event.dtstart = Time.now.strftime("%Y%m%dT%H%M%S")
event.dtend = (Time.now + 1.hour).strftime("%Y%m%dT%H%M%S")
event.description = "DESC"
event.location = "Holborn, London WC1V"
#calendar.add_event(event)
return #calendar.to_ical
end
end
And
ics_file = Outlook.create_cal
mandrill_mail(
(...)
attachments: [
{ content: ics_file, name: 'ical.ics', type: 'text/calendar' }
]
)

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>

Resources