Official email validation in Ruby - ruby-on-rails

I only want official email addresses such as xyz#company.com to sign up on my service rather than other generic email addresses such as gmail.com or Yahoo mail.com
Is there a ruby gem to achieve this kind of email validation? If not, how to make this happen?

You could write a custom validation in the appropriate model as shown here: http://www.rails-dev.com/custom-validators-in-ruby-on-rails-4
The basic idea in the article is as follows:
Make your validation method, and put it in a new directory called 'validators'
# app/validators/email_validator.rb
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value =~ /\A([^#\s]+)+#yourdomain.com\z/i
record.errors[attribute] << (options[:message] || "wrong email address")
end
end
end
(I have not tested this regex! Please use something like http://rubular.com/ and plug in your own email domain pattern to make sure it's working correctly.)
Then make sure Rails knows to load the new validators directory:
# config/application.rb
config.autoload_paths += %W["#{config.root}/app/validators/"]
Then add the new validation (email) to the appropriate model:
#MyModel.rb
validates :my_email_field, email: true

There is a free MailboxValidator web service that you can perform real-time email address validation in Ruby.
https://github.com/MailboxValidator/mailboxvalidator-ruby
require "mailboxvalidator_ruby"
apikey = "MY_API_KEY"
email = "example#example.com"
mbv = MailboxValidator::MBV.new()
mbv.apikey = apikey
mbv.query_single(email)
if mbv.error != nil
puts "Error: #{mbv.error}"
elsif mbv.result != nil
puts "email_address: #{mbv.result.email_address}"
puts "domain: #{mbv.result.domain}"
puts "is_free: #{mbv.result.is_free}"
puts "is_syntax: #{mbv.result.is_syntax}"
puts "is_domain: #{mbv.result.is_domain}"
puts "is_smtp: #{mbv.result.is_smtp}"
puts "is_verified: #{mbv.result.is_verified}"
puts "is_server_down: #{mbv.result.is_server_down}"
puts "is_greylisted: #{mbv.result.is_greylisted}"
puts "is_disposable: #{mbv.result.is_disposable}"
puts "is_suppressed: #{mbv.result.is_suppressed}"
puts "is_role: #{mbv.result.is_role}"
puts "is_high_risk: #{mbv.result.is_high_risk}"
puts "is_catchall: #{mbv.result.is_catchall}"
puts "mailboxvalidator_score: #{mbv.result.mailboxvalidator_score}"
puts "time_taken: #{mbv.result.time_taken}"
puts "status: #{mbv.result.status}"
puts "credits_available: #{mbv.result.credits_available}"
puts "error_code: #{mbv.result.error_code}"
puts "error_message: #{mbv.result.error_message}"
end

Related

Parse API and Show Output in Rails View

So, I wrote a program that sends a get request to HappyFox (a support ticket web app) and I get a JSON file, Tickets.json.
I also wrote methods that parse the JSON and return a hash with information that I want, i.e tickets with and without a response.
How do I integrate this with my Rails app? I want my HappyFox View (in rails) to show the output of those methods, and give the user the ability to refresh the info whenever they want.
Ruby Code:
require 'httparty'
def happy_fox_call()
auth = { :username => 'REDACTED',
:password => 'REDACTED' }
#tickets = HTTParty.get("http://avatarfleet.happyfox.com/api/1.1/json/tickets/?size=50&page=1",
:basic_auth => auth)
tickets = File.new("Tickets.json", "w")
tickets.puts #tickets
tickets.close
end
puts "Calling API, please wait..."
happy_fox_call()
puts "Complete!"
require 'json'
$data = File.read('/home/joe/API/Tickets.json')
$tickets = JSON.parse($data)
$users = $tickets["data"][3]["name"]
Count each status in ONE method
def count_each_status(*statuses)
status_counters = Hash.new(0)
$tickets["data"].each do |tix|
if statuses.include?(tix["status"]["name"])
#puts status_counters # this is cool! Run this
status_counters[tix["status"]["name"]] += 1
end
end
return status_counters
end
Count tickets with and without a response
def count_unresponded(tickets)
true_counter = 0
false_counter = 0
$tickets["data"].each do |tix|
if tix["unresponded"] == false
false_counter += 1
else true_counter += 1
end
end
puts "There are #{true_counter} tickets without a response"
puts "There are #{false_counter} ticket with a response"
end
Make a function that creates a count of tickets by user
def user_count(users)
user_count = Hash.new(0)
$tickets["data"].each do |users|
user_count[users["user"]["name"]] += 1
end
return user_count
end
puts count_each_status("Closed", "On Hold", "Open", "Unanswered",
"New", "Customer Review")
puts count_unresponded($data)
puts user_count($tickets)
Thank you in advance!
You could create a new module in your lib directory that handles the API call/JSON parsing and include that file in whatever controller you want to interact with it. From there it should be pretty intuitive to assign variables and dynamically display them as you wish.
https://www.benfranklinlabs.com/where-to-put-rails-modules/

How can I force an ActionMailer error for testing?

I have this code that sends an email based on conditions. If there is an error its supposed to catch the account that wasn't able to be sent in an array like so:
def process_email(delivery_method_name)
begin
Account::Access.new(account).spam! if delivery_method_name == 'mark_as_spam'
AccountMailer.send("#{delivery_method_name}", account).deliver_now
rescue
#first_notification_error << account.id
#second_notification_failure << account.id
#third_notification_failure << account.id
#fourth_notification_error << account.id
#fourth_notification_failure << account.id
return
end
update_reverification_fields
end
So in my test.rb file I want to be able to test that the account.id was caught inside of the #first_notification_error and other containers. It's not exactly clear to me though how to do this though. I read in another post to place this code in development.rb and/or test.rb config.action_mailer.raise_delivery_errors = true but I don't think this is what I'm looking for. Is there a way I can raise the error in my test, perhaps with a stub or something similar?
You need to mock AccountMailer. Put this line before calling the code you're testing:
delivery_method = 'some method on mailer that you want to mock'
allow(AccountMailer).to receive(delivery_method).and_raise("boom")

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.

Rails rspec after_save reference self

I want to add a profanity check on my website.
I'm taking a TD approach and I'm trying the following:
check if profanity exists in specific profile fields
create a flag
create a flag if one does not exist
create a flag if one exists, but has been dismissed
Here is my spec so far:
describe Painter do
before do
#painter = FactoryGirl.create(:painter_flag)
end
context "blacklist flag" do
it "check if profanity exists" do
#painter.experience = "test"
#painter.save
expect {#painter.blacklist_flags?}.to be_true
end
it "create flag if profanity exists" do
#painter.experience = "test"
#painter.save
BlacklistFlag.count.should be > 0
end
end
end
Painter related code:
after_save :create_flag, if: :blacklist_flags?
def blacklist_flags?
list = ""
list << skills
#list << experience
#list << first_name
#list << last_name
#list.downcase.scan(/(badword|badword)/).size > 0
end
def create_flag
end
If I comment out the following code above the two test pass:
list << skills
When I leave the code in I receive the following error:
2) Painter blacklist flag create flag if profanity exists
Failure/Error: #painter = FactoryGirl.create(:painter_flag)
TypeError:
can't convert nil into String
It seems there's a problem with referencing self because skills, experience, etc are part of the model. I'm not sure how to fix this. Please advise.
Update:
FactoryGirl.define do
factory :painter do
first_name "Brian"
last_name "Rosedale"
state "OH"
zip_code "43081"
sequence(:email) {|n| "nobody#{n}#painterprofessions.com" }
phone "12345566"
pdca_member false
password "123456"
factory :painter_flag do
skills = "badword"
end
end
end
Just use this line in your factory for :painter_flag, without the = sign.
skills "badword"
I think what's causing the error is because the callback is been executed on the line #painter = FactoryGirl.create(:painter_flag).
You might want to use FactoryGirl.build method if you want to test the callback.

rails 3, trying to confirm that an email address is in the dbm, but getting a wrong number of args error

My source is at: https://gist.github.com/f01685376a02a577a9cb
the method in question:
def is_valid_email?(address)
User.find_by_email(address)
end
I think the solution is to change the value for User.find_by_email(address) to something like User.find_by_email(next_approver_email) = (address) but I know that doesn't work.
Next_approver_email is what we are tying to check against the user.email db column
any ideas?
You need to pass the email into is_valid_email? at the end of line 5
def validate_each(approval, attribute, value)
approval.errors[attribute] << "must be a valid e-mail address in our system" unless is_valid_email?(value)
end

Resources