We have an application built in rails 3.2.8. We are sending emails to customers. I want to block certain emails addressses. Basically mailer just ignore those particular email addresses.
For example: My company name is abc and I dont want to send emails to all my employees ie john#abc.com or rayn#abc.com ie *#abc.com
How can I do this?
PS: I am using sendgrid, they are not providing anything like this.
EDIT:
Placing this code in initializers directory:
class EmailAddressFilter
def self.delivering_email(message)
message.perform_deliveries = false
end
end
ActionMailer::Base.register_interceptor(EmailAddressFilter)
Should block all the emails. But still I can see emails in my development log.
PS: I have restarted my server.
In a file in config/initializers you can add something like this
class EmailAddressFilter
def self.delivering_email(message)
# permit or deny the message using its "to", "body" etc properties
# note message.to is an array (multiple emails)
message.perform_deliveries = Email.whitelisted?(message.to)
end
end
ActionMailer::Base.register_interceptor(EmailAddressFilter)
Related
Want to use Griddler for uploading attachments etc in my rails app but only want a certain email address to be forwarded to my rails app is this possible cant find and docs on this as an option
I don't believe there is from the SendGrid side of the workflow, but you can always in your Rails application look at the To tag in the email object and see if it matches the email you'd like.
class EmailProcessor
def initialize(email)
#email = email
end
def process
if #email.to == 'special#email.com'
# do something
else
# handle invalid email
end
end
end
I use this class for Action Mailer:
class UserMailer < ActionMailer::Base
default from: "something#example.com",
reply_to: 'whatever#example.com'
def mail_method
mail(to: 'email#example.com', subject: "SUBJECT")
end
end
So like this I got many classes and methods which send emails like this from smtp delivery method.
But now I want to perform_deliveries , i.e. send emails only on production environment not in development or test environment.
So for that I want to use my email only, which is why I need to override mail method.
Things I have tried.
-> Making a function to return email, where function name is get_right_email
class UserMailer < ActionMailer::Base
default from: "something#example.com",
reply_to: 'whatever#example.com'
def mail_method
mail(to: get_right_email('email#example.com'), subject: "SUBJECT")
end
end
And definition of get_right_email is as follows:
def get_right_email(email)
if(Rails.env=='production')
return email
else
return 'myPersonalEmail#example.com'
end
end
It would need some refactoring but it is still manageable. Will take a few hours and I can do, but is there a quicker way where I can just override mail function.
In your config > enviroments folder you should have a file for production, development and test. Here you can specify your settings for each one.
Settings in these folders overide those in config > application.rb
For example when testing I don't usually actually send the emails but I do want to be able to test the emails so I use
config.action_mailer.delivery_method = :test
This makes the emails accessible by calling ActionMailer::Base.deliveries
You can set the default from email address in these files as well using:
config.action_mailer.default_options = {
:from => "foo#bar.com"
}
Theres a gem called letter_opener managed by the fantastic Ryan Bates which instead of sending an email in development opens the email in a new tab. This makes testing out emails in development a breeze.
Letter Opener
UPDATE BELOW ------
Apologies, I didn't quite follow what you were looking for.
Rails has webhooks you can use to intercept emails and redirect them. You'll want to use an environment different than production.
The test environment is typically used for automated testing, to keep things clear you might want to consider setting up a new environment (eg: staging).
To create a new environment just create a new file in config/environments/ and give it a suitable name - eg: staging.rb
You can then call Rails.env.staging? where ever you like.
Anyway back to the main event...
To intercept the emails first create an intercept class:
class StagingEmailInterceptor
def self.delivering_email(message)
message.to = ['my#email.com']
end
end
and then create an initializer file, eg:
config/initializers/staging_email_interceptor.rb
and inside do this:
if Rails.env.staging?
ActionMailer::Base.register_interceptor(StagingEmailInterceptor)
end
That way all emails sent in the staging environment will be sent to your email.
Background: in a Rails 3.2 app, I have an ActionMailer purchase confirmation email that is manipulated in a "stage" environment so that email destined for addresses associated with payment processor sandbox accounts will actually be sent to the email addresses of the people who manage the sandbox accounts. This is currently done inside the mailer class:
# app/mailers/purchase_mailer.rb
class PurchaseMailer < ActionMailer::Base
default :from => "\"#{SiteConfig.name}\" <#{SiteConfig.support_email}>"
def purchase_notification(purchase)
#purchase = purchase
mail :to => "\"#{purchase.customer_name}\" <#{address_filter(purchase.customer_email)}>",
:subject => "[#{SiteConfig.name}] Purchase Confirmation"
end
private
def address_filter(email_address)
# Check for and remove sandbox identifiers
if Rails.env.stage?
email_address.sub(/_\d+_p(er|re)#/, '#')
else
email_address
end
end
end
But, hey, that looks like a great use case for an interceptor, no? So I pulled out the address_filter method above and added this to the Rails app.
# config/initializers/mail.rb
Mail.register_interceptor(StageMailInterceptor) if Rails.env.stage?
# lib/stage_mail_interceptor.rb
class StageMailInterceptor
def self.delivering_email(message)
receivers = []
message.to.each do |to|
receivers << to.sub(/_\d+_p(er|re)#/, '#')
end
message.to = receivers
end
end
At first glance, this appears to work great. In the stage environment, the email is intercepted and the "to" address becomes the email address I want the email to go to. The person managing the sandbox account used to make the purchase receives the email. Perfect... except the name of the sandbox account is gone. What once was "Joe Example" <joe_1338142567_per#example.com> changed to "Joe Example" <joe#example.com> is now changed to joe#example.com
...the name is now gone.
Looking at the Mail message interface, I see that message.to= can be set with a name, but calling message.to gets me an array of just email addresses without names, whether the name was provided or not.
Question: what is the correct way to alter an email address without altering the name associated with the email address in a mail interceptor?
This doesn't seem like it's the "right" way to do this, but grabbing the "To" header of the message, doing the replacement, and setting with message.to= allows me to preserve the names while altering the email address. So my interceptor became:
# lib/stage_mail_interceptor.rb
class StageMailInterceptor
def self.delivering_email(message)
message.to = message.header["To"].to_s.gsub(/_\d+_p(er|re)#/, '#')
end
end
Is there a gem to do this, and if not, what is the best approach. I'm assuming i'd store the emails in a newsletter database, and would want a form that emails everyone at once. thanks!
No gem for this that I know of.
Actually, due to processing issues, the best way would be to use external bulk email service provider via provider's API.
However, building your own newsletter system is no different from building your regular MVC. Only addition are mailers and mailer views.
(1) So you create model that deals with registration data (:name, :email, :etc...) and model that deals with newsletter itself.
(2) Controller that deals with it (CRUD) + (:send). Send takes each recipient, sends data to mailer which creates email and then sends it.
def send
#newsletter = Newsletter.find(:params['id'])
#recipients = Recipient.all
#recipients.each do |recipient|
Newsletter.newsletter_email(recipient, #newsletter).deliver
end
end
(3) Mailer builds an email, makes some changes in each email if you want to do something like that and returns it to controller action send for delivery.
class Newsletter < ActionMailer::Base
default :from => "my_email#example.com", :content_type => "multipart/mixed"
def newsletter_email(recipient, newsletter)
# these are instance variables for newsletter view
#newsletter = newsletter
#recipient = recipient
mail(:to => recipient.email, :subject => newsletter.subject)
end
end
(4) Ofc, you need mailer views which are just like regular views. Well in multipart there is:
newsletter_email.html.erb (or haml)
newsletter_email.txt.erb
When you want to send both html and text only emails. Instance variables are defined in mailer ofc.
And... that is it. Well you could use delayed job to send them since sending more than several hundred emails can take a while. Several ms times n can be a lot of time.
Have fun.
Please check the maktoub gem there is a blog post over it.
No gem that I know of too and building on #Krule's answer, here's a screencast of setting up mailers in Rails.
How to create, preview and send email from your rails app
I was looking for something similar when I found this. I think with a bit of customization, it can easily be used to create newsletter emails too.
Save money! Spend somewhere else.
I'm wondering if it's possible to configure a Rails email derived from ActionMailer to send to a different recipient based on the environment. For example, for development I'd like it to send mail to my personal email so I don't clog up our company email account with "Testing" emails; for production however I want it to use the real address.
How can I achieve this?
The mail_safe plugin might be a little over kill.
A simple initializer will do
Rails 2.x
if Rails.env == 'development'
class ActionMailer::Base
def create_mail_with_overriding_recipients
mail = create_mail_without_overriding_recipients
mail.to = "mail#example.com"
mail
end
alias_method_chain :create_mail, :overriding_recipients
end
end
Rails 3.x
if Rails.env == 'development'
class OverrideMailReciptient
def self.delivering_email(mail)
mail.to = "mail#example.com"
end
end
ActionMailer::Base.register_interceptor(OverrideMailReciptient)
end
By default the development environment isn't setup to actually send emails (it just logs them).
Setting up alternate accounts can be done in many different ways. You can either use some logic in your mailer like so...
recipients (Rails.env.production? ? "email#company.com" : "test#non-company.org")
Or you can define the recipient as a constant in the environment files like so:
/config/environment/production.rb
EMAIL_RECIPIENT = "email#company.com"
/config/environment/development.rb
EMAIL_RECIPIENT = "test#non-company.org"
and then use the constant in your mailer. example:
recipients EMAIL_RECIPIENT
Also, there are several plugins that do this. The best one that I've found of the three I looked at was mail_safe.