It's my first time setting up mails in a rails project.
I was told to use SparkPost and to create templates for different languages for several actions.
For simplicity lets say a user_signed_up(user) mail.
Currently I have this setup working:
Gem installed: 'sparkpost'
mail.rb
ActionMailer::Base.smtp_settings = {
address: "smtp.sparkpostmail.com",
port: 587,
enable_starttls_auto: true,
user_name: "SMTP_Injection",
password: SPARKPOST_API_KEY,
domain: 'foo-bar.com'
}
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.default charset: "utf-8"
application_mailer.rb
require 'sparkpost'
class ApplicationMailer < ActionMailer::Base
default from: "Seal Notification <noreply#foobar.com>"
layout 'mailer'
end
signup_mailer.rb
class SignupMailer < ApplicationMailer
def user_signed_up(user)
receiver = user.email
sender = 'myself#test.com'
title = 'Thanks for registering'
body = 'This is a test body'
sparky = SparkPost::Client.new(SPARKPOST_API_KEY)
sparky.transmission.send_message(receiver,sender,title,body)
end
end
And I can successfully send emails.
Although, this is definitely not scaleable due to multi language and body not style-able.
Now I need to setup templates to allow non-technical people to adjust email templates.
But here is where I am stuck and an answer to following questions would help me tremendously:
1) How can I send specific email templates?
2) How do I pass variables to these templates?
3) How do I handle multiple language support?
Thank you.
Here's an intro article on creating templates in SparkPost.
Here's one on previewing your templates and sending test messages - including how variables work (aka 'substitution data').
Long form Ruby-centric answers follow:
A couple of observations on your code first: It looks like you are both configuring SMTP globally but using the REST API in your signup mailer. I'd recommend the REST API over SMTP since it has the templating and other rich capabilities you require.
1) You can manage email templates either the SparkPost UI here or directly by API call as documented here. The template syntax is documented here.
Once you have a created and published a template, you can send using the SparkPost client like this (assuming your template ID is 'your-template-en'):
require 'sparkpost'
host = 'https://api.sparkpost.com'
SparkPost::Request.request("#{host}/api/v1/transmissions", API_KEY, {
recipients: [
{ address: { email: 'recipient#example.com' } }
],
content: {
template_id: 'your-template-en'
}
})
2) SparkPost supports message-level and recipient-level 'substitution_data' which are JSON-formatted variables for use in your templates. Here's a sample transmission request:
SparkPost::Request.request("#{host}/api/v1/transmissions", API_KEY, {
recipients: [
{
address: { email: 'recipient#example.com' },
substitution_data: {
first_name: 'Recip',
favorites: {
color: 'Orange',
ice_cream: 'Vanilla'
}
}
}
],
content: {
template_id: 'your-template-en'
},
substitution_data: {
title: 'Daily News'
}
})
You now use substitution data in your templates. For example:
<h1>{{title}}</h1>
<p>Hi {{first_name or 'there'}}</p>
<p>This {{favorites.color}} bulletin is all about {{favorites.ice_cream}} ice cream</p>
Note: recipient substitution data takes precedence over message-level fields.
3) For the multi-lingual use case, you might consider creating a template per language as many of our other customers do.
Incidentally, this looks like several questions - should we consider splitting them up?
Related
I've recently upgraded to ahoy_email version 2.0.3 from 1.1.1 and i've been refactoring my code to work with the latest version but i'm having a bit of an issue with a piece of functionality i used to have. The problem is the following:
I want to be able to disable tracking for some of the mails that get sent.
With the changes made to ahoy_email in version 2.0.0, all of the class methods that set the ahoy_settings perform add a before_action which merges the options set from on of the three methods, i.e. track_clicks, has_history and utm_params, so since the options only get merged in a before_action i can't do something like the following:
class DigestMailer < ActionMailer::Base
has_history user: -> { #recipient }, extra: -> { {digest_message_id: #digest_message.id} }
track_clicks campaign: "digest"
def digest(digest_message, user, **options)
#recipient = user
#digest_message = digest_message
self.class.has_history options
....
end
end
DigestMailer.digest(DigestMessage.first, User.first, click: false, message: false).deliver_now
The options i've set in the digest action wouldn't actually get merged, since they are supposed to get merged before calling the digest action
What i could do tho, is the following:
class DigestMailer < ActionMailer::Base
has_history user: -> { #recipient }, extra: -> { {digest_message_id: #digest_message.id} }
track_clicks campaign: "digest"
def digest digest_message, user, **options
#recipient = user
#digest_message = digest_message
self.ahoy_options = AhoyEmail.default_options.merge(options)
end
end
DigestMailer.digest(DigestMessage.first, User.first, click: false, message: false).deliver_now
This works, because i'm overriding the ahoy_options attribute after the before_action callback gets called and before the after_action callbacks get called and it works.
So my question is: Is this the right way to go about this?
Because this commit, from 3 years ago, clearly says:
Keep old method of disabling tracking
But it's nowhere to be found in the documentation.
To anyone who runs into the same problem, i've found the solution and it consists of two things:
Using a parametrized mailer and using the :if option of the track_clicks, has_history and utm_params. The code can be rewritten as the following:
class DigestMailer < ActionMailer::Base
has_history(
user: -> { params[:recipient] },
extra: -> { {digest_message_id: params[:digest_message].id} },
if: -> { params[:options].try(:fetch, :message) != false }
)
track_clicks(
campaign: "digest",
if: -> { params[:options].try(:fetch, :track_clicks) != false }
)
def digest
recipient = params[:recipient]
digest_message = params[:digest_message]
Rails.logger.info "Sending digest to #{recipient} with email #{recipient.data.email}"
internal_send_digest_message(digest_message.title)
end
end
DigestMailer.with(digest_message:DigestMessage.first, recipient: User.first, options: {track_clicks: false, message: false}).deliver_now
And it will work as expected.
I want to use the Help Scout Mailbox 2.0 API to send renewal invoices to my clients. I'm working with the Ruby help-scout_sdk gem -- but their API is just a Restful JSON thing, Ruby has little to do with it.
It's easy enough to become authenticated and create a conversation:
https://developer.helpscout.com/mailbox-api/endpoints/conversations/create/
# Auth credentials in an Rails' initializer
data = {
subject: 'Time for renewal - Invoice #INV-XXXX - Account Name',
type: 'email',
mailbox_id: HelpScout.default_mailbox,
status: 'active',
customer: { email: 'email#example.com' },
created_by: 1234,
threads: [
{
type: 'customer',
customer: { email: 'email#example.com' },
text: 'A test thread.'
}
]
}
HelpScout::Conversation.create(data)
However, this example code will create a new issue in the mailbox queue FROM the customer. Anyone know how to create a new conversation from a Help Scout "user" (our support email) to be sent TO a customer (our client)?
Basically, what params need to be passed to have the API work like how "New Conversation" (new-ticket) works in their Web UI. Thanks!
Turns out I was using the wrong thread type.
To create a new conversation FROM a "user" addressed TO a "customer" your thread should use the "reply" type.
data = {
subject: 'Time for renewal - Invoice #INV-XXXX - Account Name',
type: 'email',
mailbox_id: HelpScout.default_mailbox,
status: 'active',
customer: { email: 'email#example.com' },
created_by: 1234,
threads: [
{
type: 'reply',
customer: { email: 'email#example.com' },
text: 'A test thread.'
}
]
}
Thanks to Kristi at Help Scout for her super quick answer to my question.
I'm trying to create a Mailchimp list using Mailchimps API (v3) and the REST Client gem. I've got this working correctly for retrieving list names and ids. However, I'm getting a 401 Unauthorized - API Key Missing response for the creation of a list. I think my post request is malformed but I'm having trouble indentifying where I'm going wrong. My code looks like this:
params_hash = {
name: "#{territory}",
contact: {
company: "Company",
address1: "Address",
city: "City",
state: "State",
zip: "0000",
country: "US"
},
permission_reminder: "You are receiving this email because....",
campaign_defaults: {
from_name: "From Name",
from_email: "contact#contact.com",
subject: "Subject",
language: "en"
},
notify_on_subscribe: "contact1#contact.com",
notify_on_unsubscribe: "contact1#contact.com",
email_type_option: true,
apikey: mailchimp_key
}
RestClient.post("#{mailchimp_url}/lists", { params: params_hash }) { |response, request, result, &block|
}
You should not pass your API key in the payload, instead, you should use HTTP Basic Authentication. RestClient does support this, but it's kind of awkward. If you want to use the RestClient shortcuts, you can modify your URL to include the username/password, like this: https://username:api_key#us1.api.mailchimp.com -- username doesn't matter to MailChimp, but it's required for Basic Auth, so you can pass anything.
Alternately, you can use RestClient's Request class directly, making your request something like this instead:
RestClient::Request.execute(method: :post, url: "#{mailchimp_url}/lists", payload: params_hash, user: 'anything', password: mailchimp_key)
But, honestly? RestClient is not great. I prefer HTTParty, which allows you to create very lightweight wrappers with lots of defaults set for you, OR use it like RestClient, but with a more friendly API:
HTTParty.post("#{mailchimp_url}/lists", body: params_hash, basic_auth: {username: 'whatever', password: mailchimp_key})
I need to send promotional email and fetch there corresponding stats.Currently i am using Gibbon Gem but not able to create campaign through .Is there any way to create campaign and add bulk email in receiver
through Gibbon Gem or there is any other Gem to work for same.I need all stat of a campaign like sent ,bounced, effective email.Which version Of Gibbon Gem should i use to create campaign and contact list through Api
Gibbon does allow you to create and trigger campaigns through the Mailchimp API v3. You have to use Gibbon version >= 2.1.3 to send campaigns, because there was a bug in the earlier versions.
Gibbon's readme file was recently updated with examples.
To create a campaign:
recipients = {
list_id: list_id,
segment_opts: {
saved_segment_id: segment_id
}
}
settings = {
subject_line: "Subject Line",
title: "Name of Campaign",
from_name: "From Name",
reply_to: "my#email.com"
}
body = {
type: "regular",
recipients: recipients,
settings: settings
}
begin
gibbon.campaigns.create(body: body)
rescue Gibbon::MailChimpError => e
puts "Houston, we have a problem: #{e.message} - #{e.raw_body}"
end
To send a campaign:
gibbon.campaigns(campaign_id).actions.send.create
To get stats:
email_stats = gibbon.reports(campaign_id).retrieve["opens"]
Context:
I need to send bulk-email using send grid in a rails app.
I will be sending emails to maybe around 300 subscribers.
I have read that it can be accomplished using
headers["X-SMTPAPI"] = { :to => array_of_recipients }.to_json
I have tried following that.
The following is my ActionMailer:
class NewJobMailer < ActionMailer::Base
default from: "from#example.com"
def new_job_post(subscribers)
#greeting = "Hi"
headers['X-SMTPAPI'] = { :to => subscribers.to_a }.to_json
mail(
:to => "this.will#be.ignored.com",
:subject => "New Job Posted!"
)
end
end
I call this mailer method from a controller
..
#subscribers = Subscriber.where(activated: true)
NewJobMailer.new_job_post(#subscribers).deliver
..
The config for send-grid is specified in the config/production.rb file and is correct, since I am able to send out account activation emails.
Problem:
The app works fine without crashing anywhere, but the emails are not being sent out.
I am guessing the headers config is not being passed along ?
How can I correct this ?
UPDATE:
I checked for email activity in the send grid dashboard.
Here is a snapshot of one of the dropped emails:
You are grabbing an array of ActiveRecord objects with
#subscribers = Subscriber.where(activated: true)
and passing that into the smtpapi header. You need to pull out the email addresses of those ActiveRecord objects.
Depending on what you called the email field, this can be done with
headers['X-SMTPAPI'] = { :to => subscribers.map(&:email) }.to_json