Delayed jobs for sending emails in ruby on rails - ruby-on-rails

I am building the Email where I am parsing the .csv file which consists of email id's.Here is the code
File.open("#{Rails.root.to_s}/public/files/#{params["file"].original_filename}", "wb"){|file| file.write(params["file"].read) }
arr_of_arrs = CSV.read("#{Rails.root.to_s}/public/files/#{params["file"].original_filename}")
puts arr_of_arrs
arr_of_arrs.each do |i|
Here is the Mail sending process which is called in my Controller
Class.method(i[0]).deliver)
And I call the ActionMailer to send emails which are in the .csv file.And I am using AWS SES to send the mails.
My problem is when ever it fails to send an email to a particular address the whole email sending stops and it would not send emails to the rest of the address. But even after it fails it should be able to send the email to the rest of the addresses, how can I handle this issue since I am newbie to the ruby on rails.

This doesn't seem to have anything to do with delayed_job.
To not stop the remaining emails, catch the exception which breaks the loop:
arr_of_arrs.each do |i|
begin
Class.method(i[0]).deliver
rescue => e
# perhaps you'd like to log e's detail here
end
end

Related

Sidekiq: Pass email body and attachments for processing?

I just learned/started using Sidekiq today to handle background processing of incoming email messages and attachments, but am a bit lost on the best way to get the email body and attachments into the worker for processing.
My RoR app is hosted on Heroku and receives incoming emails via Mailgun to a controller, which then kicks off my worker. Within the worker is a call to a 3rd party API to upload my email messages and attachments (think DropBox.)
Mailgun pre-parses everything and sends it over as parameters, but from what I understand about Sidekiq, I don't want to pass along entire objects such as the email body and/or attachments as shown here.
#attach_count = params["attachment-count"]
#from = params["from"]
#subject = params["subject"]
#msgbody = params["body-html"]
ProcessEmailWorker.perform_async(#id, #attach_count, #from, #subject, #msgbody)
What's the best practice for getting these items over to my worker?
I assume Mailgun is POSTing to your controller.
You can send the POST body as a single string parameter to Sidekiq and have it re-parse everything.
You can save the data to Redis or your database for processing in Sidekiq.
You can send the email content as a Hash of Strings:
{ 'subject' => ..., 'body' => ... }
After speaking with another developer I chose to do the following:
Set up a route in Mailgun to store the incoming email message, but to post a notification to my controller
Have my controller grab the incoming message ID and pass that along to my worker
From within my worker, use the message ID to perform a GET to Mailgun to retrieve the stored message (and its attachments)
Process the message/attachments and upload them to my cloud storage provider.

How to get email reply on rails app from email server

I need to implement messaging feature. When I send message to any user from my rails app then it also goes to users email. But what I need to implement if user who got the email make reply from gmail,yahoo..etc then the reply should also come into rails app. could anyone guide me some way.. so I can search it on google.
For Example:
If I send email to user from this email "mc-6bckm434ls#reply.xyz.com" and user replied on gspq5diedss#reply.xyz.com which I set Reply-To in header. Then I need user's reply in my rails application so that I can add this user's reply into my messaging thread.
By this feature which I want to implement User do not need to login in my application to do message, user can do message on current conversation via email reply also.
Since you tagged the question SendGrid, I'm assuming you're using it. You can use SendGrid's Inbound Parse Webhook to handle parsing incoming messages.
We also have a recent tutorial that goes through using the webhook in a rails app: http://sendgrid.com/blog/two-hacking-santas-present-rails-the-inbound-parse-webhook/
It's possible !
You can use mailman for example.
All you have to do is set a Reply-To header in your e-mail to make it unique, so when you fetch messages you know to what it corresponds.
For example, let's say you own the e-mail address foo#bar.com
You could send e-mails with a reply-to header "foo+content_id#bar.com", so you know what the user is replying to.
Then, mailman can fetch the messages from the mailbox and parse the content id in them.
Some services do that as well, handling all the emailing part and sending you notifications for incoming e-mails, for example, postmark
Ruby on Rails introduced Action Mailbox in version 6.0
With ActionMailbox you can easily configure rules where to route incoming emails (examples from the documentation):
# app/mailboxes/application_mailbox.rb
class ApplicationMailbox < ActionMailbox::Base
routing /^save#/i => :forwards
routing /#replies\./i => :replies
end
And how to handle specific messages in a mailbox:
# app/mailboxes/forwards_mailbox.rb
class ForwardsMailbox < ApplicationMailbox
# Callbacks specify prerequisites to processing
before_processing :require_forward
def process
if forwarder.buckets.one?
record_forward
else
stage_forward_and_request_more_details
end
end
private
def require_forward
unless message.forward?
# Use Action Mailers to bounce incoming emails back to sender – this halts processing
bounce_with Forwards::BounceMailer.missing_forward(
inbound_email, forwarder: forwarder
)
end
end
def forwarder
#forwarder ||= Person.where(email_address: mail.from)
end
def record_forward
forwarder.buckets.first.record \
Forward.new forwarder: forwarder, subject: message.subject, content: mail.content
end
def stage_forward_and_request_more_details
Forwards::RoutingMailer.choose_project(mail).deliver_now
end
end
Find the documentation about how to configure Action Mailbox and some examples in the Rails Guides.
See https://github.com/titanous/mailman/blob/master/USER_GUIDE.md
There is a railscast about using the gem but its pay-only :-/ http://railscasts.com/episodes/313-receiving-email-with-mailman,
however, there is the github repo from the railscast which can showcase you an example app that uses mailman (with before & after so you can track the changes) - https://github.com/railscasts/313-receiving-email-with-mailman

How to to mass email (500,000) using rails [duplicate]

I will be sending bulk emails from a Rails app and plan on using SendGrid. I am assuming that it is best to send a separate email to each recipient (as opposed to using BCC for all the recipients). If that is true, should I be using something like DelayedJob to queue the messages going over to SendGrid, or would it be safe to throw 500 messages at it all at once? Thanks!
500 messages really isn't that much to SendGrid. It's not even a blip on their radar. I worked for a company that sent out 2.7 million emails in a single month, and even then it's only just a blip.
With the SendGrid API's capabilities, you wouldn't be sending out 500 emails, you would send one email which has a specific SendGrid API header set. Why? Because have you ever tried to send 500 individual email messages and timed how long that takes? How about a single email? The single email's going to be quicker.
The SendGrid API has a Ruby example which is here:
https://sendgrid.com/docs/Integrate/Code_Examples/SMTP_API_Header_Examples/ruby.html.
That's quite long winded and messy, so let me simplify it for you. Basically, you set this in your email:
headers["X-SMTPAPI"] = { :to => array_of_recipients }.to_json
SendGrid will then parse this and then send that one email you sent it out to that array of recipients. I seem to recall that they ask you to limit this to about 1000 recipients per email, so it would be wise to split it up over multiple emails if you wanted that. That is when you would bring in something like the delayed_job or resque gems to deal with it.
Oh, and by the way you'll still need to specify a to address for this email just to make the Mail gem happy. We had info#ourcompany.com for that.
The SendGrid API will also support filters in their emails, so you can have placeholder strings such as {{ firstname }} and, assuming you send it through with the SMTPAPI header, it will do the "mail merge" on the email and customize them.
It would do you a great deal of good if you read the SendGrid API documentation. It's really useful and what they provide is super powerful.
I recommend using the sendgrid gem ( https://github.com/stephenb/sendgrid ) as it simplifies your calling code.
Here's an example rails 3 action mailer example:
class UserAnnouncementMailer < ActionMailer::Base
include SendGrid
default reply_to: "test#test.com", return_path: "test#test.com", from: "Test"
# bulk emailer
# params - opts a hash of
# emails: array of emails
#
def notice(opts={})
raise "email is nil" unless opts[:emails]
sendgrid_category :use_subject_lines
sendgrid_recipients opts[:emails]
name = "The Man"
to = "test#test.com"
from_name = "#{name} <theman#test.com>"
subject = "Important"
mail({from: from_name, to: to, subject: subject})
end
end
And the corresponding calling code. It's recommended to have the emails array to be < 1000 emails.
emails = ["alice#test.com", "bob#test.com"]
UserAnnouncementMailer.notice({:emails => emails}).deliver
See the sendgrid gem github readme for more details.
Delayed Job and SendGrid sound like the best option from what you say, but have you considered using one of the campaign mailers like Mailchimp instead? If you're sending out a lot of mails that are basically the same, they'll let you setup and campaign template and then fire a CSV of all the variables at it. They then effectively mail merge and fire them all out.
If however, you're only talking a few hundred you're on the right lines. SendGrid can easily handle the load, and you want to use Delayed Job so that you're not impacted by the performance of the SendGrid API should it not be favorable. Alternatively, look at Resque instead for sending mail as it may be more efficient.
I would imagine SendGrid can handle that kind of load. Most relay systems can. Also I would imagine if you sent the 500 in a CC API call, that their system would parse it and send them individually. I use Elastic Email (http://elasticemail.com) - and I know that this is how they handle it and it works great.
This is how I've done it in Rails 4
class NewsMailer < ApplicationMailer
include SendGrid
sendgrid_category :use_subject_lines
default from: 'My App! <support#myapp.com>'
def mass_mailer(news)
# Pass it in template
#news = news
# Custom method to get me an array of emails ['user1#email.com', 'user2#email.com',...]
array_of_emails = #news.recipients.pluck(:email)
# You can still use
# headers["X-SMTPAPI"] = { :to => array_of_emails }.to_json
sendgrid_recipients array_of_emails
mail to: 'this.will.be.ignored#ignore.me', subject: 'Weekly news'
end
end

Configure Rails app to retrieve ALL emails from inbox

I'm using the following code to retrieve emails from my Gmail inbox.
def get_mail
Net::POP3.enable_ssl(OpenSSL::SSL::VERIFY_NONE)
Net::POP3.start('pop.gmail.com', 995, "uname","pass") do |pop|
unless pop.mails.empty?
pop.each_mail do |mail|
email = TMail::Mail.parse(mail.pop)
email_obj=EmailedQueries.new
email_obj.save_email(email.from,email.subject,email.body_html)
end
end
end
end
This works just fine, but it retrieves only new mails from the inbox. Instead, I want a seperate function that will retrieve ALL emails from the inbox. This function will be used rarely. I wont be retrieving all mails all the time. Only when necessary.
Thanks!
You'll need to configure POP settings in GMail.Enable "Pop for all mail" and you're good to go !

Pass data to mailer daemon in Rails?

According to the Rails API (snippet below), the optimal way to receive mail is by creating a single Rails instance within a daemon that gets invoked by a MTA whenever new mail arrives.
My question is: how do you pass data to that daemon when new mail arrives?
========================
Rails API Snippet
To receive emails, you need to implement a public instance method called receive that takes a tmail object as its single parameter. The Action Mailer framework has a corresponding class method, which is also called receive, that accepts a raw, unprocessed email as a string, which it then turns into the tmail object and calls the receive instance method.
Example:
class Mailman < ActionMailer::Base
def receive(email)
page = Page.find_by_address(email.to.first)
page.emails.create(
:subject => email.subject, :body => email.body
)
if email.has_attachments?
for attachment in email.attachments
page.attachments.create({
:file => attachment, :description => email.subject
})
end
end
end
end
This Mailman can be the target for Postfix or other MTAs. In Rails, you would use the runner in the trivial case like this:
./script/runner 'Mailman.receive(STDIN.read)'
However, invoking Rails in the runner for each mail to be received is very resource intensive. A single instance of Rails should be run within a daemon if it is going to be utilized to process more than just a limited number of email.
In the example you provide, there is no daemon running to process email. The documentation is saying you can setup your mailer daemon, Postfix in this case, to invoke a command when mail is received. When you call the command from your mailer:
RAILS_ROOT/script/runner 'Mailman.receive(STDIN.read)'
The content of the email is passed into the receive method. A much better way to handle processing incoming email is to create an actual mailbox that receives email. You can then write a Ruby script that batch checks the mailbox to process the email. You can call that script via cron with lock run around it to insure that there is only one process performing this task.

Resources