the-refinery / sparkpost_rails Goto Github PK
View Code? Open in Web Editor NEWSparkpost delivery method for ActionMailer
License: MIT License
Sparkpost delivery method for ActionMailer
License: MIT License
It would be really useful for Ruby newbies like me to have a working Rails example if possible :)
I've set up a basic Rails project and used the example code in the Readme, but when I call deliver!
on my SparkPost mailer I get an SMTP error:
Net::SMTPAuthenticationError: 535 5.7.8 Sorry.
Complete examples of the steps needed to configure SparkPost Rails would be most welcome!
I'm getting this message when I try to send an email:
SparkPostRails::DeliveryException ([{"message"=>"invalid data format/type", "description"=>"content.headers json dictionary value has type 'json_array' when expecting type 'string'", "code"=>"1300"}]):
Mailer:
mail(to: @user.email, subject: "subject", sparkpost_data: {track_opens: true, track_clicks: true})
Controller:
result = CertificateMailer.email_certificate(current_user).deliver!
The new Rails 5.2 was released today. I believe the only change that would need to be done is on the gemspec restriction.
If a delivery error occurs and this is set to false, a DeliveryException should probably NOT be thrown.
attempting to isolate the problem, I have disabled tracking
# config/environments/production.rb
Rails.application.configure do
config.action_mailer.delivery_method = :sparkpost
# config/initializers/sparkpost_rails.rb
SparkPostRails.configure do |c|
c.api_key = ENV.fetch('SPARKPOST_API_KEY')
c.sandbox = false
c.track_clicks = false
c.track_opens = false
c.transactional = false
end
Emails sent with our custom mailer are sending fine, however Devise generated emails: Forgot password, are sending as plaintext when they should be html.
I'm trying to figure out what devise is doing with type
, still looking...
Could we please have an update to support Rails 5.1?
I'm sending multiple email addresses but the problem i'm running into is that everyone in the "TO" list sees their email address there and others who are known to be supposed to be "TO" field are not getting the email because they don't see them there.
So there is way to display all "To" recipients ?
Hi,
I'd like to propose that we don't raise an exception in SparkPostRails::DeliveryMethod#process_result()
def process_result result
result_data = JSON.parse(result.body)
if result_data["errors"]
@response = result_data["errors"]
raise SparkPostRails::DeliveryException, @response
else
@response = result_data["results"]
end
end
The reason is that this might not work well if we're sending to multiple recipients. For example, if we are sending to 100 recipients, of which 1 of them produces an error. If we raise an exception in this case, this could result in unexpected behaviour.
Particularly, if we use a background worker such as sidekiq, sidekiq will attempt to retry the execution and we might end up resending the same email to those 99 recipients again.
So my suggestion is that we don't raise an exception and instead we recommend developers to use SparkPost's webhook (https://support.sparkpost.com/customer/portal/articles/1929974-defining-webhooks) to handle errors asynchronously.
Thanks
Is there anyway to pass return_path
, campaign_id
from mailer, not in initializer?
Thanks.
Just wondering if there are any known breaking changes, as I didn't see 1.5.5 listed in the changeling. Thank you for your work maintaining this project!
Is there a reason this isn't on RubyGems?
Great library and thanks for sharing.
I've heard some speculation that Base64.encode64
might add \r\n
on some platforms in which case this code may not be sufficient:
But while looking at this I found Base64.strict_encode64
which maybe a better overall solution.
Hi, thanks so much for your work on sparkpost_rails!
I'm trying to include inline images like this:
message[:attachments].each do |ad|
attachments.inline[ad.original_filename] = {
mime_type: ad.content_type,
content: File.read(ad.tempfile),
cid: 'some-name'
}
end
However, the message arrives with a randomly generated Content-Id rather than the specified cid:
parameter, and a missing image icon appears where the <img>
tag is in HTML, with the attachment at the bottom of the message.
In this case, the email is received from Sparkpost webhook, so the content-id is already set in the incoming email. I parse it out, and then use that value in the cid: parameter in attachments.inline[] = {}. If it were actually used, the image would display inline where specified by the <img>
tag, but the cid parameter seems to be ignored.
If perform_deliveries
is set to true on the message, by a mail interceptor for example, sparkpost_rails should respect this by not calling the sparkpost api to transmit.
I'm getting this message when I try to send an email:
Completed 500 Internal Server Error in 1174ms (ActiveRecord: 40.8ms)
SparkPostRails::DeliveryException ([{"message"=>"Unauthorized."}])
but the main problem is when I try with same data after some time it resolves automatically. I don't know what to do with this any suggestions how can I solve this?
Seems in the created mail, the sparkpost_data has no effect.
I am trying to set metadata
sparkpost_data = {
"id"=> @message.id, #@message.id, #maybe we can specifuy the same id Sparkpost uses as our id, will make it easier to search transmissions in sparkpost for debuggin
"content"=> {}, # no need as that data is sent in the mail method below - actually I could not get options in here to work like reply_to
"options"=>{}, # see config/initializers/sparkpost_rails.rb:3,
"metadata"=>{"message_id"=> @message.id}#@message.id} #this data will be returned by sparkpost webhooks
}
mail(to:@message.recipient, subject: @message.subject, from: from_addr,sparkpost_data: sparkpost_data).deliver!
it is not just metadata, it also failed for all content attrs, and I would guess all attrs in sparkpost_data altogether but have not tested them all.
Using rails-4.2.9
sparkpost_rails-1.5.0
actionmailer-4.2.9
Didn't see this; Any plans to add this? If this is within the scope of the project I can submit a PR. :)
Rails 7.0.0 final was released yesterday, and will soon become the new standard. I'm hoping we can see a PR like #89 get merged soon. Is this something that can be expected before long?
I don't quite get how to attach files to an email, I checked the API and it says it should be under the content.attachments
section as an array, yet doing this doesn't seem to work, this is how I'm sending my email:
def buyer_tickets_email(order)
@order = order
data = {
substitution_data: purchase_order_details(@order),
content: {
attachments: order.tickets.map do |ticket|
{
name: "#{ticket_file_name(ticket)}.pdf",
type: "application/pdf",
data: ticket.to_pdf
}
end
},
template_id: 'buyer-tickets-email'
}
mail to: @order.email, subject: I18n.t('tickets_mailer.subject'), sparkpost_data: data
end
Am I missing something? The email arrives correctly yet without the attached pdfs
Maybe this is intended, but I had set my ENV variable for the API key and was planning on just using the default config that ships with this gem, and there were errors that prevented this from working unless the initializer actually existed.
Here's the one that I saw, but there may be more:
WARN: NoMethodError: undefined method `sandbox' for nil:NilClass
WARN: sparkpost_rails-2bbfc0a590cf/lib/sparkpost_rails/delivery_method.rb:219:in `prepare_sandbox_mode_from'
Hi there ! I received this email from Sparkpost
TLS v1.1 Deprecation Notice
Dear valued customer,On September 1, 2020, SparkPost will be deprecating TLSv1.1 fallback across all of our systems. This is an older security standard for sending email and contains vulnerabilities that directly impact the integrity and security of your communications; vulnerabilities which cannot be fixed in these older implementations.
As long as connections are made using TLSv1.2, this change will result in zero impact to your ongoing use of our service; however if connections are made using TLSv1.1, you will observe a failure to connect to API and SMTP endpoints. To ensure that there is no impact to existing processes, it is best to verify that your clients support TLSv1.2. You can verify the version of TLS that your client is using by collecting local packet captures of network traffic and inspecting which version of TLS is being used to establish a secure connection to SparkPost (handshake).
If you are using TLSv1.1, then you should take the following steps:
If you are using proprietary code, have your in-house development team update the code to use TLSv1.2.
If you are using 3rd party software, verify that your client supports TLSv1.2, and upgrade the client.
Do you have any idea if sparkpost_rails is using TLS > v1.2 ? Sorry if my question is not relevant, I'm not sure do understand very nice this protocol thing...
This is my config/environments/development.rb
config.action_mailer.delivery_method = :sparkpost
config.action_mailer.smtp_settings = {
:address => 'smtp.sparkpostmail.com',
:port => 587,
:domain => 'gmail.com', #you can also use google.com
:enable_starttls_auto => true,
:encryption => 'STARTTLS'
}
I put my api_key
in config/initializer/sparkpost_rails.rb
i getting my email but my it uses html format
I am not sure what setup I have missed. But for some reasons running the code below (sending template_id
with sparkpost_data
) gives ActionView::MissingTemplate Error
data = {
template_id: 'my-template',
substitution_data:
first_name: user.first_name
}
}
mail(to: '[email protected]', sparkpost_data: data)
I have
config.action_mailer.delivery_method = :sparkpost
in the application environment configuration file
'SPARKPOST_API_KEY' set in environment variables and this in initializers/sparkposts_rails.rb
SparkPostRails.configure do |c|
c.transactional = true
end
Hi guys!
First of all thank you for the gem, it's awesome!
There is a little mistake in manual for the gem. As I see you use sparkpost_data[:recipient_list_id] as a pointer to SparkPost recipient list. But in manual you recommend to use :list_id โ https://github.com/the-refinery/sparkpost_rails#recipient-lists
Could you please fix this topic?
Hi,
Is it possible to turn off this gem on the fly? In my case, I want people to use their own SMTP settings but when I try emails are still sent through SparkPost.
Thanks
I just needed this gem to change an older rails app from smtp to the api because the smtp server takes too long (from Europe). (was using mandrill)
However, I needed to go down quite a few commits to find a working version as the gemspec is requiring Rails 4 as a minimum. Is there a specific reason for that?
This version at least works like a charm: https://github.com/the-refinery/sparkpost_rails/tree/d509d44566808f8f06e8b2a87e97da4e1822f8e3
Hi, I am using sparkpost_rails 1.4.0 with rails 4.2.8
When I try to include an Ruby Array of Emails for the "cc" parameter for Action Mailer, I receive this error from SparkPost during delivery:
{"message"=>"invalid data format/type", "description"=>"content.headers json dictionary value has type 'json_array' when expecting type 'string'", "code"=>"1300"}
However, when I use the same exact array for a "bcc" parameter, the mail successfully goes through and the BCC work as I would expect.
Could there be a problem in how these headers are constructed?
Thanks in advance.
I followed the instructions in the README, setting up action_mailer.rb file to catch SparkPostRails::DeliveryException
but it doesn't seem to work.
The issue is that if you use sparkpost with devise, and a user tries to register with an email that doesn't have any MX records... (example: [email protected]) sparkpost throws a DeliveryException, and my app crashes. Am I doing something wrong? Here's my action_mailer.rb file
ActionMailer::DeliveryJob.rescue_from(SparkPostRails::DeliveryException) do |exception|
redirect_to '/logout', alert: "Please use a valid email address."
# do something special with the error
end
Doing this:
mail(subject: subject, sparkpost_data: {transactional: false, date: time})
Gives us this error:
SyntaxError: (eval):1: syntax error, unexpected tCONSTANT, expecting =>
{:transactional=>false, :date=>Sat, 13 May 2017 12:10:15 UTC +00:00}
^
from /Users/david/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sparkpost_rails-1.4.0/lib/sparkpost_rails/delivery_method.rb:46:in `eval'
from /Users/david/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sparkpost_rails-1.4.0/lib/sparkpost_rails/delivery_method.rb:46:in `find_sparkpost_data_from'
from /Users/david/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/sparkpost_rails-1.4.0/lib/sparkpost_rails/delivery_method.rb:14:in `deliver!'
from /Users/david/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/mail-2.6.5/lib/mail/message.rb:253:in `deliver!'
from /Users/david/.rbenv/versions/2.3.1/lib/ruby/2.3.0/delegate.rb:83:in `method_missing'
Looks like the time gets converted to a string which is then subsequently not parsable by eval
:
[3] pry(#<SparkPostRails::DeliveryMethod>)> mail[:sparkpost_data]
=> #<Mail::Field 0x7f9d7e8891e0 @name="sparkpost-data" @value={:transactional=>false, :date=>Sat, 13 May 2017 12:10:37 UTC +00:00} @raw_value=nil @charset="UTF-8" @field_order_id=100 @field=#<Mail::OptionalField:0x007f9d6352a4b0 @errors=[], @charset="UTF-8", @name="sparkpost-data", @length=nil, @tree=nil, @element=nil, @value="{:transactional=>false, :date=>Sat, 13 May 2017 12:10:37 UTC +00:00}">>
So I think this is actually a Ruby / Net::HTTP issue but I thought I'd post this here in case other people run into the same problem. Here's the issue I opened on the Ruby issue tracker ( https://bugs.ruby-lang.org/issues/15472 ):
It seems that invalid (JSON) data is being sent once the request's body passes a size threshold. I'm sending emails via the sparkpost.com API using the sparkpost_rails gem ( https://github.com/the-refinery/sparkpost_rails ). That gem uses Net::HTTP to make its API calls.
I upgraded my app from Ruby 2.5.3 to Ruby 2.6.0 on December 25th. Yesterday, on the 26th, my app attempted to send its nightly emails to users. I was flooded with these errors from the API:
{ "errors": [ { "message": "invalid data format\/type", "description": "Problems parsing request as json", "code": "1300" } ] }
After some debugging / trial & error I discovered that the length of the email messages seemed to be the problem. I haven't nailed down the exact maximum length that will work but I know that if the request body is 16,511 characters long the message will be sent. If it's 17,396 characters it will fail.
I've also tried replacing Net::HTTP with the rest_client gem. The full-sized messages get sent with no problems using RestClient.
So I can replace this (https://github.com/the-refinery/sparkpost_rails/blob/master/lib/sparkpost_rails/delivery_method.rb#L379):
def post_to_api
url = "https://api.sparkpost.com/api/v1/transmissions"
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.path, @headers)
request.body = JSON.generate(@data)
http.request(request)
end
with
def post_to_api
url = "https://api.sparkpost.com/api/v1/transmissions"
RestClient.post(url, JSON.generate(@data), @headers)
end
and my (full-length, much larger than 17,396 characters) messages get sent with no problem.
I also tried logging the actual HTTP requests using the httplog gem (https://github.com/trusche/httplog) in Ruby 2.5.3 and 2.6.0. Unfortunately that showed the request payloads were identical. But I suspect that gem's logging does some conversion that isn't actually happening in the real data being sent to the SparkPost API.
We are using sparkpost_rails with DelayedJob. DelayedJob serializes the mail object to a database table using YAML, for later execution. When the job is deserialized from YAML, its enclosed Mail::Message
instance is also deserialized, however the sparkpost_data
method is undefined. Since this method is defined inside of the mail
method in DataOptions::InstanceMethods
, any Mail::Message
instance created outside of this method (e.g. through deserialization) will not have the method present. This means all of our emails fail to send, with (e.g.) #<NoMethodError: undefined method
sparkpost_data' for #Mail::Message:0x00007f90cdcc22d8>`.
I'll fork the code and experiment with some possible fixes, but if there's an obvious/ preferred approach, please do let me know and I'll pursue it.
Well, as far as I see from docs, inline_css
is an option for transmission
https://developers.sparkpost.com/api/#/reference/transmissions
and it appear to be false by default.
Now, when I use sparkpost_rails to send email with template saved in the sparkpost account, it looks like the email do not apply inline css styles to elements.
Is it any way to pass inline_css
to sparkpost via sparkpost_rails? Should it be set somewhere here?
After I send an email using:
result = MyMailer.some_message(some_var).deliver!
how can I get this response?
{"total_rejected_recipients"=>0, "total_accepted_recipients"=>1, "id"=>"00000000000000"}
The result
variable is an instance of Mail::Message
, so I can not get these values from that.
I need an id
as I am using webhooks to track delivery, opens/clicks and so on...
Email with HTML content is delivered as plain text with HTML tags.
Fixed it by changing lib/sparkpost_rails/delivery_method.rb
But don't know whether it is the correct approach or not . #30
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.