Send image inline in email using Rails 2 - ruby-on-rails

I am working on rails 2 application with sending email functionality. Now, I need to send inline image with the email.
I am using Mailer to send email. I tried lots of time using different ways but not succeed to send image inline in email. Below code i am using to send email.
# Controller
Mailer.delivery_my_opinion_reply(user, my_opinion, answer)
# Model / Mailer.rb
def my_opinion_reply(user, my_opinion, answer)
#subject = "My opinion"
#from = "#{Settings.site_name}"
#recipients = user.email
#content_type = "multipart/alternative"
#attachments.inline['test.jpg'] = File.read(RAILS_ROOT + "/public/system/att_images/728/original/ball1.jpg")
#body = {:question => my_question, :user => user}
end
I got error "undefined method inline for nil class"

try this way
#attachments.inline['image.png'] = File.read("app/assets/images/image.png")
mail(to: email, subject: "subject", content_type: "text/html")

Related

Emails with SendGrid Web API in Rails

I'm following this tutorial: https://github.com/sendgrid/sendgrid-ruby/. Very straightforward. However, I want to avoid having a big chunk of code in my controller to send an email. It currently looks like this:
from = Email.new(email: 'some#email.com')
to = Email.new(email: 'some#email.com')
subject = 'Sending with SendGrid is Fun'
content = Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
mail = Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: 'key')
response = sg.client.mail._('send').post(request_body: mail.to_json)
Ideally, I'd like to be able to trigger it from a service like: SendMail.new.perform() or some nice one-liner in the controller.
How would I abstract this code away from the controller and how would I call that new service/abstraction?
Twilio SendGrid developer evangelist here.
You can absolutely extract that from your controller, this is normally described as a service object.
I like to keep service objects in the app folder. You can do so by creating the directory app/services. Then create a file for the class, app/services/email_service.rb for example. In that file add the code to send the email, maybe something like this:
class EmailService
def self.call(from:, to:, subject:, content:)
self.new.send_email(from: from, to: to, subject: subject, content:
end
def initialize()
#sendgrid = SendGrid::API.new(api_key: Rails.application.credentials.sendgrid)
end
def send_email(from:, to:, subject:, content:)
from = Email.new(email: from)
to = Email.new(email: to)
content = Content.new(type: 'text/plain', value: content)
mail = Mail.new(from, subject, to, content)
response = #sendgrid.client.mail._('send').post(request_body: mail.to_json)
end
end
You can then call this service from your controller with the one liner:
EmailService.call(from: "me#mydomain.com", to: "you#yourdomain.com", subject: "My new email service", content: "It's pretty wonderful")
As a bonus, it's also easier to unit test the EmailService separate to the controller and to mock it out in controller tests.
If you are using rails, you can define it in your environment file and use one line code to send email from your controller.
production.rb
config.action_mailer.delivery_method = :sendmail
# Defaults to:
# config.action_mailer.sendmail_settings = {
# location: '/usr/sbin/sendmail',
# arguments: '-i'
# }
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.default_options = {from: 'no-reply#example.com'}
and in your controller
mail( :to => #user.email,
:subject => 'Thanks for signing up for our amazing app' )
best case for using sendmail is using it with an ActionMailer class. You can look it up at rails documentation.

How to Skip Devise Confirmation email using SeedFu gem

I'm using the Seed-Fu gem to populate my database. So, I have this in one of my seed files:
User.seed_once(:email) do |user|
user.id = 1
user.email = "test#test.com"
user.first_name = "First"
user.last_name = "Last"
user.confirmation_sent_at = Time.zone.now - 1.hour
user.confirmed_at = Time.zone.now
user.roles = [root,staff]
user.permissions = Permission.all
end
From what I've read, that should prevent Devise from sending a confirmation email. However, it is not, so (since I'm using the Letter Opener gem) my browser is being flooded with confirmation emails. Anyone know why this is happening and how I can convince Devise to not send these emails whilst I'm seeding?
SOLUTION:
Based on anothermh's answer below, I added Devise::Mailer.perform_deliveries = false to the top of this fixture file. Then, I found my final fixture file and added Devise::Mailer.perform_deliveries = true to the end of that to make sure emails would be sent when actually using the app. Thank you so much, folks!
You just need to call the confirm method on user object. See the below code
user.confirm
So in your case the code will be like
User.seed_once(:email) do |user|
user.id = 1
user.email = "test#test.com"
user.first_name = "First"
user.last_name = "Last"
user.confirm
user.roles = [root,staff]
user.permissions = Permission.all
end
You can turn off email sends from Devise in tests. Specifically, you'll need to have this set somewhere:
Devise::Mailer.delivery_method = :test
Devise::Mailer.perform_deliveries = false
For example, if you're doing this with rspec then you would likely put it into spec/rails_helper.rb.

ROR sending email based on account number

We're using Ruby 1.9 and Rails 3.2 We use AS/400 for our database. We've tried using Active Record for this before, and it doesn't want to work because of our versions of Ruby and Rails being older combined with getting it to connect with the 400.
We have an online ordering site that you have to have an account set up to access. Depending on what type of account you are set up as, you might have to have your order approved by someone. I.e. if I am a drop ship account, my distributor has to approve what I'm ordering. The way it had been set up, the distributor wasn't getting any kind of approval email.
We've been trying the line of code below in console, and have it working. If we enter an account number instead of leaving it blank, it returns a list of the email addresses that would be getting the approval email. Fantastic! If it's left blank as shown below, it returns a blank array. Makes sense, we haven't logged in, so it doesn't know our account number yet. When the user logs in, their account number should automatically be substituted in.
Contact.find_by_sql ["SELECT EMAL23 FROM WEBOEL23 WHERE ACT223 = ‘’”]
However, when we add that code snippet into the order.rb file, it returns an error:
wrong number of arguments (1 for 4)
Clearly, the way we have the line set up isn't right:
Mailer.deliver_order_distributor_approval_email('Contact.find_by_sql (SELECT EMAL23 FROM WEBOEL23 WHERE ACT223 = "30153"')
It's just getting confusing... we seem to be going in circles with the errors. We try to fix it, but then we just get new errors that still have to do with that line.
The deliver_order_distributor_approval_email method is in the mailer.rb file below:
class Mailer < ActionMailer::Base
##################################################################################
##################################################################################
# NOTE: in all cases, use sanitize_email to ensure nothing goes out by accident. #
##################################################################################
##################################################################################
def order_confirmation_email(recipient_email, from_email, subject, email_details)
recipient_email = Mailer.sanitize_email(recipient_email)
# Get the template of the email body from the database and then perform all replacements.
email_body = Setting.first.email_order_body
email_details.each {|key, value| email_body.gsub!("##" + key.upcase.gsub("_"," ") + "##", value)}
recipients recipient_email
from from_email
subject subject
bcc Setting.first[:email_admin_to]
part :content_type => "text/html",
:body => email_body
#f=File.open("/var/www/onlineordering.example.com/log/debugger.txt")
#f.puts get_email = $get_email
#f.close
end
def order_coastal_notify_email(from_email, subject, email_details)
# Get the template of the email body from the database and then perform all replacements.
email_body = Setting.first.email_order_coastal_notify
email_details.each {|key, value| email_body.gsub!("##" + key.upcase.gsub("_"," ") + "##", value)}
recipients Setting.first[:email_order_placed_to]
from from_email
subject subject
bcc Setting.first[:email_admin_to]
part :content_type => "text/html",
:body => email_body
end
def order_distributor_approval_email(recipient_email, from_email, subject, email_details)
recipient_email = Mailer.sanitize_email(recipient_email)
# Get the template of the email body from the database and then perform all replacements.
# We run the attachment and the email body through replacement tags.
email_body = Setting.first.email_order_attachment_body
email_attachment_body = Setting.first.email_order_attachment
email_details.each {|key, value| email_body.gsub!("##" + key.upcase.gsub("_"," ") + "##", value)}
email_details.each {|key, value| email_attachment_body.gsub!("##" + key.upcase.gsub("_"," ") + "##", value)}
# If their email is blank, we'll send it to admin.
recipients recipient_email.blank? ? Setting.first[:email_admin_to] : recipient_email
from from_email
subject subject
bcc Setting.first[:email_order_placed_to]
part :content_type => "text/html",
:body => email_body
attachment "application/pdf" do |a|
a.body = WickedPdf.new.pdf_from_string(email_attachment_body)
a.filename = "Drop Ship Approval Form.pdf"
end
end
def order_again_reminder_email(name, recipient_email, from_email, subject)
recipient_email = Mailer.sanitize_email(recipient_email)
recipients recipient_email
from from_email
bcc Setting.first[:email_admin_to]
subject subject
body :content => Setting.first.email_reminder_body.gsub!(/##NAME##/, name.to_s.titleize)
end
def forgot_password_email(recipient_email, from_email, subject, password)
recipient_email = Mailer.sanitize_email(recipient_email)
recipients recipient_email
from from_email
bcc Setting.first[:email_admin_to]
subject subject
body :password => password
end
def register_email(recipient_email, from_email, subject, params)
recipient_email = Mailer.sanitize_email(recipient_email)
recipients recipient_email
from from_email
bcc Setting.first[:email_admin_to]
subject subject
body :params => params
end
private
def self.sanitize_email(recipient_email)
# Comma separate multiple email addresses.
case ENV['RAILS_ENV']
when 'production'
recipient_email = recipient_email
when 'development'
recipient_email = "John Doe<john#example.com>"
else
# This is really the production, since they don't have a true production server
# should resolve to "dev".
recipient_email = recipient_email
end
recipient_email
end
end
If the order.rb file would be helpful, I can attach it... it's just kind of lengthy, so I didn't include it in the post. If you have any suggestions as to how to change the mailer.deliver_order_distributor_approval_email line, please let me know.. I'd really appreciate it! Thank you in advance!
Edit
Mailer.deliver_order_distributor_approval_email ('Contact.find_by_sql SELECT EMAL23 FROM WEBOEL23 WHERE ACT223 = "30153"'),"Coastal Pet Online Ordering<noreply#coastalpet.com>", "Order Confirmation-customer", email_details
With this (after some tweaking), we were able to submit an order without any errors, but we aren't getting any emails. Odd. It almost seems like we might be missing some mailer calls or something?
Edit
After modifying the script suggested a little, we came up with this...
target_email = Contact.find_by_sql ["SELECT EMAL23 FROM WEBOEL23 WHERE ACT223 = ''"]
Mailer.deliver_order_confirmation_email(target_email, "Coastal Pet Online Ordering<noreply#coastalpet.com>", "Order Confirmation-customer", email_details)
It "works" without errors - we can log in and submit an order, but still fail to get any email.
Oddly enough, that snippet returns the error below when ran through the console.
ActiveRecord::StatementInvalid: 37000 (-10) [IBM][iSeries Access ODBC Driver][DB 2 UDB]SQL0010 - String constant beginning ' ' not delimited.
If we put in an account number like below, it runs through and submits.. but still no email. It returns an error on the console, too.
target_email = Contact.find_by_sql ["SELECT EMAL23 FROM WEBOEL23 WHERE ACT223 ='30153'"]
Mailer.deliver_order_confirmation_email(target_email, "Coastal Pet Online Ordering<noreply#coastalpet.com>", "Order Confirmation-customer", email_details)
Error:
NameError: undefined local variable or method `email_details' for main:Object
Ideas?
The error message you are getting:
wrong number of arguments (1 for 4)
indicates that you have called a method that expects four arguments, but you only provided one. Here's your method call:
Mailer.deliver_order_distributor_approval_email('Contact.find_by_sql (SELECT EMAL23 FROM WEBOEL23 WHERE ACT223 = "30153"')
As written, you've provided one argument: the string 'Contact.find_by_sql (SELECT EMAL23 FROM WEBOEL23 WHERE ACT223 = "30153"'.
When you call the method Mailer.deliver_order_distributor_approval_email, it eventually passes the arguments it is given to the order_distributor_approval_email method you've defined in your Mailer class. That method requires four arguments, but you're only giving it one, hence the error. You need to provide all four arguments to make the method call work.
Update:
You are passing the string 'Contact.find_by_sql SELECT EMAL23 FROM WEBOEL23 WHERE ACT223 = "30153"' as the first argument, so the mailer is trying to treat that string as an email address, which naturally isn't going to work. Presumably you want to actually call the find_by_sql method on Contact to get the real email address, in which case you'll want something like this:
target_email = Contact.find_by_sql('SELECT EMAL23 FROM WEBOEL23 WHERE ACT223 = "30153"').first
Mailer.deliver_order_distributor_approval_email(target_email, "Coastal Pet Online Ordering<noreply#coastalpet.com>", "Order Confirmation-customer", email_details)
This should perform the query and attempt to send the email to the first result. You will need to make further adjustments to send to multiple recipients or to send multiple emails.

how to get subject, from and body from mailman rails

i have code like this
Mailman::Application.run do
to 'email#local.com' do
## how to get subject, from and body in here
end
end
how to get subject, from and body from email in rails?
Use mail gem https://github.com/mikel/mail/
Mailman::Application.run do
default do
mail = Mail.new(message)
from = message.from.first
content = mail.parts[1].body.decoded
subject = message.subject
//your other code
end
end

Rails 3.0.7 ActionMailer attachment issue

I'm trying to attach a file to an outgoing email but the attachment size ends up being 1 byte. It doesn't matter what attachment I'm forwarding it always ends up in the email 1 byte in size (corrupt). Everything else looks ok to me.
The email information is pulled from an IMAP account and stored in the database for browsing purposes. Attachments are stored on the file system and it's file name stored as an associated record for the Email.
In the view there's an option to forward the email to another recipient. It worked in Rails 2.3.8 but for Rails 3 I've had to change the attachment part of the method so now it looks like...
def forward_email(email_id, from_address, to_address)
#email = Email.find(email_id)
#recipients = to_address
#from = from_address
#subject = #email.subject
#sent_on = Time.now
#body = #email.body + "\n\n"
#email.attachments.each do |file|
if File.exist?(file.full_path)
attachment :filename => file.file_name, :body => File.read(file.full_path)
else
#body += "ATTACHMENT NOT FOUND: #{file.file_name}\n\n"
end
end
end
I've also tried it with...
attachments[file.file_name] = File.read(file.full_path)
and adding :mime_type and :content_type to no avail.
Any help would be a appreciated.
Thanks!
This is what I tried and worked for me
attachments.each do |file|
attachment :content_type => MIME::Types.type_for(file.path).first.content_type, :body => File.read(file.path)
end
Is the file readable? Can you debug the issue by placing something like this?
logger.debug "File: #{file.full_path.inspect} : #{File.read(file.full_path).inspect[0..100]}"
Is there anything in your development.log?
Well, someone from the rails team answered my question. The problem lies with adding body content (#body) other than the attachment inside the method. If you're going to attach files you have to use a view template.

Resources