Send sender name with email SendGrid - Rails - ruby-on-rails

I am using SendGrid to send emails from my application. I want to send sender name along with sender email e.g. from: 'Maxcreet <contact#maxcreet.com>'
It is working fine using Letter Opener and MailTrap but SendGrid only show sender email.
Here is my SendGrid functionto send emails.
def deliver!(mail)
email.from = SendGrid::Email.new(email: mail[:from].addrs.first.address)
email.subject = mail.subject
email.add_personalization(build_personalization(mail))
build_content(mail)
send!(email)
end
I have checked mail[:from] values using puts it gives following values:
puts mail[:from] => Maxcreet <support#maxcreet.com>
puts mail[:from].addrs => Maxcreet <support#maxcreet.com>
puts mail[:from].addrs.first => Maxcreet <support#maxcreet.com>
puts mail[:from].addrs.first.address => support#maxcreet.com
Above 3 seems OK for me but when I use any of them in
email.from = SendGrid::Email.new(email: mail[:from].addrs.first.address)
It does not sent my email and even I do not find my email in sendgrid dashboard.
Following this also tried email.fromname but this even did not work.

SendGrid's ruby API has this option with name name and not fromname.
So the following should solve your problem.
email.from = SendGrid::Email.new(
email: mail[:from].addrs.first.address,
name: mail[:from].addrs.first.name
)
I concluded this by trying it from this doc.

It looks like you're mixing gems or objects. SendGrid::Email.new just needs a from String, and might support a name String. You're extracting the address from your mail[:from] Hash with mail[:from].addrs.first.address, but you need to provide the name as a distinct Key.
In the SendGrid Ruby gem 'kitchen sink" example, they don't show a name on the From argument, but they do on the personalization.
Try: email.from = SendGrid::Email.new(email: 'support#maxcreet.com', name: 'Maxcreet'))
or dynamically: email.from = SendGrid::Email.new(email: mail[:from].addrs.first.address, name: mail[:from].addrs.first.name))
if your mail Object recognizes that Key.
Otherwise, you'll need to look at your mail gem's documentation for how to extract a Friendly/Display Name from that mail[:from].addrs Object.

Related

Have to add a simple condition in Rails

I have to setup my rails project to send a confirmation SMS to new users. I have a table phone_calling_codes which has a column sms_enable_flag. In my DB this field has to be checked or not, so it's boolean.
I use Twilio to send SMS but I want to add a condition to send SMS only to the numbers where this sms_enable_flag is checked.
I also use phonelib to parse the number and take the country code from it.
def perform(phone_number, confirmation_code)
logger.info("Job started sending confirmation code")
overrideToPhone = [ "development","upgrade"].include? Rails.env
deliverSMS = !([ "development", "upgrade"].include? Rails.env)
phone=''
if overrideToPhone
e164Prefix = '+'
phone_number = e164Prefix + "17782002024"
else
phone = Phonelib.parse( phone_number)
phone_number = phone.e164
end
sms=phone_calling_codes.find_by calling_code: phone.country_code
if sms
if sms.sms_enabled_flag
from_phone_number = Rails.application.secrets.twilio_number
body = "Valorbit.com - your phone verification code is: #{confirmation_code}"
logger.info("From #{from_phone_number} to #{phone_number} : #{body}")
twilio_client.messages.create(
to: phone_number ,
from: from_phone_number ,
body: body
) if deliverSMS
logger.info("Sent sms to #{phone_number}") if deliverSMS
else
logger.info("SMS is not enabled for #{phone_number}")
end
end
end
Please help me to this. I am a beginner to OOP and I want to understand if it is ok how I have thought.
Thanks! :D
change line
sms=phone_calling_codes.find_by calling_code: phone.country_code
to
sms=PhoneCallingCode.find_by calling_code: phone.country_code
PhoneCallingCode is the model name present in /app/models folder
Below is the query to find data from model:
ModelName.find_by column_name: parameter

How To Search a User in Discourse Using Ruby

I am trying to find and delete unwanted user in my discourse using ruby
puts "Search Member you want to Delete"
puts "Search By E-Mail"
usermail = gets
puts client.search(usermail)
in result it takes me to discourse page
is there any possible ways to search and find the exact user by email.
thanks for your nice and helpful comments
i think we cannot search users by email and we can just use the following for geting users list
require 'rest-client'
RestClient.get 'http://example.com/resource', {params: {id: 50, 'foo' => 'bar'}}
we can get a user by name using Http gem
require 'http'
username = 'username'
response = HTTP.get("https://discourse.example.com/user/#{username}.jason?api_key=Your_Discourse_api_key")
puts response.body.to_s
it worked for me

How do I pass unique_args to the SendGrid::TemplateMailer API from Ruby on Rails

I've been implementing the sendgrid-ruby gem to send email via SendGrid. I'm using templates exclusively for my messages to send. I've got everything working on the outbound side using the TemplateMailer implementation.
This is the code:
unique_args = {unique_args: {MyAuditNumber: "9999999"}}
# Create a sendgid recipient list
recipients = []
recipient = SendGrid::Recipient.new(to_email)
merge_vars.each do |mv|
Rails.logger.debug(mv)
recipient.add_substitution('*|' + mv["name"] + '|*', mv["content"])
end
recipients << recipient
# Create a sendgrid template
template = SendGrid::Template.new(template_id)
# Create a client
client = SendGrid::Client.new(api_key: Rails.configuration.sendgridkey)
mail_defaults = {
from: from_email,
from_name: from_name,
to: to_email,
to_name: to_name,
bcc: bcc,
html: ' ',
text: ' ',
subject: subject
}
mailer = SendGrid::TemplateMailer.new(client, template, recipients)
# send it
lres = mailer.mail(mail_defaults)
The last thing I want to do is to add a unique identifier to each message that I send.
I've read both the SendGrid documentation as well as several questions and other articles (
how to get response of email sent using sendgrid in rails app to save in database
http://thepugautomatic.com/2012/08/sendgrid-metadata-and-rails/
https://sendgrid.com/docs/Integrate/Code_Examples/SMTP_API_Header_Examples/ruby.html
)
I can tell that I need to add unique_args to the smtp API. But what I can't figure out is how to pass that into the SendGrid routines.
I've tried things like:
recipient.add_to_smtpapi( unique_args )
and
recipient.add_to_smtpapi( unique_args.to_json )
and
mail_defaults = {
smtpapi: unique_args,
from: from_email,
...
and
mail_defaults = {
smtpapi: unique_args.to_json,
from: from_email,
...
These attempts generally result in an error message like:
undefined method `add_filter' for "{\"unique_args\":{\"MyAuditNumber\":\"9999999\"}}":String
Does anyone know how to pass unique_args when using the TemplateMailer?
Based on gem documentation, what you should do is the following:
header = Smtpapi::Header.new
header.add_unique_arg("MyAuditNumber", "9999999")
mail_defaults = {
smtpapi: header
...

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 create a multipart ical email? [Rails]

What I want to achieve is the following:
Send an email with delayed_job containing:
plain-text
html (will be displayed by regular clients which don't understand the inline ical)
"inline" ical which is recognized by Outlook and Thunderbird (with Lightning).
a "regular" ical attachment (for #2)
What works so far/what does'nt:
I am able to send the email via delayed_job with all parts, however:
in Apple's Mail 2 attachments show up (instead of one):
(the html is displayed fine)
in Thunderbird (Lightning) I do get an invitation, just like I want. But the Alarm does not show up.
I have to do some REALLY disgusting gsubs on the rendered iCal in order for the ATTENDEES to show up. (see code snippet)
My thinking:
The first thing to keep in mind is: in order to send an email with attachments from delayed_job
To fix this, remember to add this line to your mailer: content_type "multipart/mixed"
As far as I understand the correct MIME-Type hierarchy would therefore be:
multipart/mixed
multipart/alternative
text/plain
text/html
text/calendar (with: method=REQUEST)
application/ics
Warning! code incoming.
I currently construct this email in the following manner:
Edit: I updated the mailer for Rails 4.2 (attachments must be placed before mail)
in my mailer.rb
def invitation_email(...)
subject = "I suck at email..."
attachments["invite.ics"] = { mime_type: "application/ics",
content: ical_attachment }
email = mail(from: me, to: you, subject: subject)
add_ical_part_to(email)
email
end
def add_ical_part_to(mail)
outlook_body = ical_attachment
mail.add_part(Mail::Part.new do
content_type "text/calendar; method=REQUEST"
body outlook_body
end)
end
and this is how I construct the ical attachments:
def ical_attachment
params_participant = {
"ROLE" => "REQ-PARTICIPANT",
"RSVP" => "FALSE",
"PARTSTAT" => "ACCEPTED"
}
params_invite = {
"CUTYPE" => 'INDIVIDUAL',
"ROLE" => "REQ-PARTICIPANT",
"PARTSTAT" => "NEEDS-ACTION",
"RSVP" => "TRUE"
}
cal = Icalendar::Calendar.new
event = Icalendar::Event.new
event.dtstart #party.from.to_datetime, { "VALUE" => "DATE" }
event.dtend #party.to.to_datetime, { "VALUE" => "DATE" }
event.summary #party.title
event.description #party.description
event.klass "PRIVATE"
event.organizer "cn=#{#user.name} #{#user.surname}:mailto:#{#user.email}"
# THIS DOES NOT WORK
event.alarm.trigger = "-PT5M" # 5 Minutes before...
#party.participations.each do |participation|
str = "cn=#{participation.user.name} #{participation.user.surname}:mailto:#{participation.user.email}"
event.add_attendee(str, params_participant)
end
#party.invitations.each do |invitee|
event.add_attendee("mailto:#{invitee.email}", params_invite)
end
cal.add_event(event)
cal.publish
# I KNOW THIS IS HORRIBLE AND I HATE IT, BUT OTHERWISE THE ATTENDEES DO NOT SHOW UP
cal.to_ical.gsub("ORGANIZER:", "ORGANIZER;").gsub("ACCEPTED:", "ACCEPTED;").gsub("TRUE:", "TRUE;").gsub("PUBLISH", "REQUEST")
end
Any help would be really appreciated!
The email that is being generated: http://pastebin.com/patf05zd
Oh and I'm on:
Rails 3.2.13
The Icalendar gem I'm using
In case someone else happens to come across this, here is what I did:
Instead of the icalendar gem I now use ri_cal. Although I was skeptical because the last commit to that repo was 3 years ago, the google group was a very helpful resource.
Here is how I generate the ical attachment (both inline and normal), which seems to be working fine (although it obviously needs some refactoring :))
def to_ical
# this is horrible
klass = self
cal = RiCal.Calendar do
event = event do
organizer "CN=#{klass.user.name} #{klass.user.surname}:mailto:#{klass.user.email}"
summary klass.party.title
description klass.ical_description
dtstart klass.party.from.utc.to_datetime
dtend klass.party.to.utc.to_datetime
location "See url in description"
security_class klass.security_class
# this is horrible
h = self
klass.party.participations.each do |participation|
h.add_attendee klass.prepare_participant(participation)
end
klass.party.invitations.each do |invitee|
h.add_attendee klass.prepare_invitee(invitee.email)
end
unless klass.party.reminder == 0
alarm do
description "Alarm description"
trigger klass.convert_trigger # -PT1H
action "DISPLAY"
end
end
end
end
# THE HORROR
cal.to_s.gsub("ATTENDEE:", "ATTENDEE")
.gsub("ORGANIZER:", "ORGANIZER;")
.gsub("CALSCALE:GREGORIAN", "CALSCALE:GREGORIAN\nMETHOD:REQUEST\n")
end
The 2 Attachments in Apples Mail still show up, I don't think that can be fixed.
Your second B64 encoded attachment contains a lot of garbage towards the end (attendee field).
That would explain the Thunderbird issue.
Please note that some clients will ignore any alarm you may set on a REQUEST: As an organizer, you should not dictate when each attendee should be reminded of the meeting. That would be a rather rude thing to do.
Regarding the Apple iCal issue, there is not much you can do I'm afraid: Some clients want the ics within, some as an attachment so you have to provide both. Does it show the accept/decline panel on iCal ?

Resources