sendgrid 0.0.1 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "json"
4
+
5
+ # Add dependencies required to use your gem here.
6
+ # Example:
7
+ # gem "activesupport", ">= 2.3.5"
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ group :development do
12
+ gem "shoulda", ">= 0"
13
+ gem "bundler", "~> 1.0.0"
14
+ gem "jeweler", "~> 1.5.1"
15
+ # gem "rcov", ">= 0"
16
+ end
17
+
18
+ group :test do
19
+ gem "actionmailer", ">= 2.3.2"
20
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,67 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (3.1.5)
5
+ actionpack (= 3.1.5)
6
+ mail (~> 2.3.3)
7
+ actionpack (3.1.5)
8
+ activemodel (= 3.1.5)
9
+ activesupport (= 3.1.5)
10
+ builder (~> 3.0.0)
11
+ erubis (~> 2.7.0)
12
+ i18n (~> 0.6)
13
+ rack (~> 1.3.6)
14
+ rack-cache (~> 1.2)
15
+ rack-mount (~> 0.8.2)
16
+ rack-test (~> 0.6.1)
17
+ sprockets (~> 2.0.4)
18
+ activemodel (3.1.5)
19
+ activesupport (= 3.1.5)
20
+ builder (~> 3.0.0)
21
+ i18n (~> 0.6)
22
+ activesupport (3.1.5)
23
+ multi_json (>= 1.0, < 1.3)
24
+ builder (3.0.0)
25
+ erubis (2.7.0)
26
+ git (1.2.5)
27
+ hike (1.2.1)
28
+ i18n (0.6.0)
29
+ jeweler (1.5.2)
30
+ bundler (~> 1.0.0)
31
+ git (>= 1.2.5)
32
+ rake
33
+ json (1.5.1)
34
+ mail (2.3.3)
35
+ i18n (>= 0.4.0)
36
+ mime-types (~> 1.16)
37
+ treetop (~> 1.4.8)
38
+ mime-types (1.18)
39
+ multi_json (1.2.0)
40
+ polyglot (0.3.3)
41
+ rack (1.3.6)
42
+ rack-cache (1.2)
43
+ rack (>= 0.4)
44
+ rack-mount (0.8.3)
45
+ rack (>= 1.0.0)
46
+ rack-test (0.6.1)
47
+ rack (>= 1.0)
48
+ rake (0.8.7)
49
+ shoulda (2.10.3)
50
+ sprockets (2.0.4)
51
+ hike (~> 1.2)
52
+ rack (~> 1.0)
53
+ tilt (~> 1.1, != 1.3.0)
54
+ tilt (1.3.3)
55
+ treetop (1.4.10)
56
+ polyglot
57
+ polyglot (>= 0.3.1)
58
+
59
+ PLATFORMS
60
+ ruby
61
+
62
+ DEPENDENCIES
63
+ actionmailer (>= 2.3.2)
64
+ bundler (~> 1.0.0)
65
+ jeweler (~> 1.5.1)
66
+ json
67
+ shoulda
data/README.md ADDED
@@ -0,0 +1,127 @@
1
+ sendgrid
2
+ =========
3
+
4
+ _Now updated to work with Rails 3._
5
+
6
+ What is SendGrid?
7
+ -----------------
8
+
9
+ SendGrid is an awesome service that helps you send large amounts of email (bells and whistles included) without spending large amounts of money. This gem allows for painless integration between ActionMailer and the SendGrid SMTP API. The current scope of this gem is focused around setting configuration options for outgoing email (essentially, setting categories, filters and the settings that can accompany those filters). SendGrid's service allows for some other cool stuff (such as postback notification of unsubscribes, bounces, etc.), but those features are currently outside the scope of this gem.
10
+
11
+ Visit [SendGrid](http://sendgrid.com) to learn more.
12
+
13
+ Getting Started
14
+ ---------------
15
+
16
+ First of all, you'll need the gem. It's at http://rubygems.org/gems/sendgrid. If you're using Bundler, just add the following to your Gemfile.
17
+
18
+ gem 'sendgrid'
19
+
20
+
21
+ Before you can do anything with the sendgrid gem, you'll need to create your very own SendGrid account. Go ahead and do so at [http://sendgrid.com](http://sendgrid.com) (there's even a FREE account option).
22
+
23
+ Next, update your application's SMTP settings to use SendGrid's servers (see [SendGrid's getting started guide](http://wiki.sendgrid.com/doku.php?id=get_started) for instructions).
24
+
25
+ Example:
26
+
27
+ ActionMailer::Base.smtp_settings = {
28
+ :address => "smtp.sendgrid.net",
29
+ :port => 25,
30
+ :domain => "mysite.com",
31
+ :authentication => :plain,
32
+ :user_name => "sendgrd_username",
33
+ :password => "sendgrid_password"
34
+ }
35
+
36
+ Using the sendgrid Gem
37
+ ----------------------
38
+
39
+ If you do not already have an ActionMailer class up and running, then check out [this guide.](http://guides.rubyonrails.org/action_mailer_basics.html#walkthrough-to-generating-a-mailer)
40
+
41
+ 1) add the following line within your mailer class:
42
+
43
+ include SendGrid
44
+
45
+
46
+ 2) customize your sendgrid settings:
47
+
48
+ There are 2 main types of settings
49
+
50
+ * Category settings
51
+ * Enable/disable settings
52
+
53
+ You can set both global and per-email settings - the same syntax is used in either case.
54
+ Here is an example of what typical usage may look like:
55
+
56
+ class MyMailer < ActionMailer::Base
57
+ include SendGrid
58
+ sendgrid_category :use_subject_lines
59
+ sendgrid_enable :ganalytics, :opentrack
60
+ sendgrid_unique_args :key1 => "value1", :key2 => "value2"
61
+
62
+ def welcome_message(user)
63
+ sendgrid_category "Welcome"
64
+ sendgrid_unique_args :key2 => "newvalue2", :key3 => "value3"
65
+ mail :to => user.email, :subject => "Welcome #{user.name} :-)"
66
+ end
67
+
68
+ def goodbye_message(user)
69
+ sendgrid_disable :ganalytics
70
+ mail :to => user.email, :subject => "Fare thee well :-("
71
+ end
72
+ end
73
+
74
+ Category settings can be any text you like and SendGrid's website will allow you to view email statistics per-category (very nice). There is also a custom global setting that will automatically use the subject line of each email as the sendgrid\_category:
75
+
76
+ sendgrid_category :use_subject_lines
77
+
78
+ If you have any dynamic subject lines, you'll want to override this setting within the mailer method. Calling sendgrid\_category from within one of your mailer methods will override this global setting. Similarly, calling sendgrid\_enable/sendgrid\_disable from within a mailer method will add or remove from any defaults that may have been set globally.
79
+
80
+ Here are a list of supported options for sendgrid\_enable and sendgrid\_disable:
81
+
82
+ * :opentrack
83
+ * :clicktrack
84
+ * :ganalytics
85
+ * Call sendgrid\_ganalytics\_options(:utm_source => 'welcome_email', :utm_medium => 'email', :utm_campaign => 'promo', :utm_term => 'intro+text', :utm_content => 'header_link') to set custom Google Analytics variables.
86
+ * :gravatar
87
+ * :subscriptiontrack
88
+ * Call sendgrid\_subscriptiontrack\_text(:html => 'Unsubscribe <% Here %>', :plain => 'Unsubscribe Here: <% %>') to set a custom format for html/plain or both.
89
+ * OR Call sendgrid\_subscriptiontrack\_text(:replace => '|unsubscribe\_link|') to replace all occurrences of |unsubscribe\_link| with the url of the unsubscribe link
90
+ * :footer
91
+ * Call sendgrid\_footer\_text(:html => 'My HTML footer rocks!', :plain => 'My plain text footer is so-so.') to set custom footer text for html, plain or both.
92
+ * :spamcheck
93
+ * Call sendgrid\_spamcheck\_maxscore(4.5) to set a custom SpamAssassin threshold at which SendGrid drops emails (default value is 5.0).
94
+
95
+ For further explanation see [SendGrid's wiki page on filters.](http://wiki.sendgrid.com/doku.php?id=filters)
96
+
97
+ Custom parameters can be set using the sendgrid_unique_args methods. Any key/value pairs defined thusly will
98
+ be included as parameters in SendGrid post backs. These are especially useful in cases where the recipient's
99
+ email address is not unique or when multiple applications/environments are using the same SendGrid account.
100
+
101
+
102
+ Delivering to multiple recipients
103
+ ---------------------------------
104
+
105
+ There is a per-mailer-method setting that can be used to deliver campaigns to multiple (many) recipients in a single delivery/SMTP call.
106
+ It is quite easy to build a robust mass-delivery system utilizing this feature, and it is quite difficult to deliver a large email campaign quickly without this feature.
107
+ Note: While it may be worth asking yourself, a SendGrid engineer told me it's best to keep the number of recipients to <= 1,000 per delivery.
108
+
109
+
110
+ sendgrid_recipients ["email1@blah.com", "email2@blah.com", "email3@blah.com", ...]
111
+
112
+
113
+ One issue that arises when delivering multiple emails at once is custom content. Luckily, there is also a per-mailer-method setting that can be used to substitute custom content.
114
+
115
+
116
+ sendgrid_substitute "|subme|", ["sub text for 1st recipient", "sub text for 2nd recipient", "sub text for 3rd recipient", ...]
117
+
118
+
119
+ In this example, if <code>|subme|</code> is in the body of your email SendGrid will automatically substitute it for the string corresponding the recipient being delivered to. NOTE: You should ensure that the length of the substitution array is equal to the length of the recipients array.
120
+
121
+
122
+ TODO
123
+ ----
124
+
125
+ * Test coverage (I would appreciate help writing tests).
126
+ * Possibly integrate with SendGrid's Event API and some of the other goodies they provide.
127
+
data/Rakefile CHANGED
@@ -10,8 +10,8 @@ begin
10
10
  SendGrid is an email deliverability API that is affordable and has lots of bells and whistles.}
11
11
  gem.email = "stephenrb@gmail.com"
12
12
  gem.homepage = "http://github.com/stephenb/sendgrid"
13
- gem.authors = ["Stephen Blankenship"]
14
- # gem.add_development_dependency "thoughtbot-shoulda"
13
+ gem.authors = ["Stephen Blankenship", "Marc Tremblay", "Bob Burbach"]
14
+ gem.add_dependency "json"
15
15
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
16
  end
17
17
  Jeweler::GemcutterTasks.new
@@ -39,20 +39,20 @@ rescue LoadError
39
39
  end
40
40
  end
41
41
 
42
- task :test => :check_dependencies
42
+ task :test
43
43
 
44
44
  task :default => :test
45
45
 
46
- require 'rake/rdoctask'
47
- Rake::RDocTask.new do |rdoc|
48
- if File.exist?('VERSION')
49
- version = File.read('VERSION')
50
- else
51
- version = ""
52
- end
46
+ # require 'rake/rdoctask'
47
+ # Rake::RDocTask.new do |rdoc|
48
+ # if File.exist?('VERSION')
49
+ # version = File.read('VERSION')
50
+ # else
51
+ # version = ""
52
+ # end
53
53
 
54
- rdoc.rdoc_dir = 'rdoc'
55
- rdoc.title = "sendgrid #{version}"
56
- rdoc.rdoc_files.include('README*')
57
- rdoc.rdoc_files.include('lib/**/*.rb')
58
- end
54
+ # rdoc.rdoc_dir = 'rdoc'
55
+ # rdoc.title = "sendgrid #{version}"
56
+ # rdoc.rdoc_files.include('README*')
57
+ # rdoc.rdoc_files.include('lib/**/*.rb')
58
+ # end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 1.2.4
@@ -0,0 +1,11 @@
1
+ require 'rails'
2
+
3
+ module SendGrid
4
+ class Railtie < Rails::Railtie # :nodoc:
5
+
6
+ initializer "send_grid.action_mailer" do
7
+ ActiveSupport.on_load(:action_mailer) { ActionMailer::Base.send(:include, SendGrid) }
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module SendGrid #:nodoc:
2
+ VERSION = "2.0.0"
3
+ end
data/lib/sendgrid.rb CHANGED
@@ -9,22 +9,40 @@ module SendGrid
9
9
  :gravatar,
10
10
  :subscriptiontrack,
11
11
  :footer,
12
- :spamcheck
12
+ :spamcheck,
13
+ :bypass_list_management
13
14
  ]
14
-
15
+
16
+ VALID_GANALYTICS_OPTIONS = [
17
+ :utm_source,
18
+ :utm_medium,
19
+ :utm_campaign,
20
+ :utm_term,
21
+ :utm_content
22
+ ]
23
+
15
24
  def self.included(base)
16
25
  base.class_eval do
17
26
  class << self
18
27
  attr_accessor :default_sg_category, :default_sg_options, :default_subscriptiontrack_text,
19
- :default_footer_text, :default_spamcheck_score
28
+ :default_footer_text, :default_spamcheck_score, :default_sg_unique_args
20
29
  end
21
- attr_accessor :sg_category, :sg_options, :sg_disabled_options, :subscriptiontrack_text, :footer_text, :spamcheck_score
30
+ attr_accessor :sg_category, :sg_options, :sg_disabled_options, :sg_recipients, :sg_substitutions,
31
+ :subscriptiontrack_text, :footer_text, :spamcheck_score, :sg_unique_args, :sg_send_at
22
32
  end
33
+
34
+ # NOTE: This commented-out approach may be a "safer" option for Rails 3, but it
35
+ # would cause the headers to get set during delivery, and not when the message is initialized.
36
+ # If base supports register_interceptor (i.e., Rails 3 ActionMailer), use it...
37
+ # if base.respond_to?(:register_interceptor)
38
+ # base.register_interceptor(SendgridInterceptor)
39
+ # end
40
+
23
41
  base.extend(ClassMethods)
24
42
  end
25
-
43
+
26
44
  module ClassMethods
27
-
45
+
28
46
  # Sets a default category for all emails.
29
47
  # :use_subject_lines has special behavior that uses the subject-line of
30
48
  # each outgoing email for the SendGrid category. This special behavior
@@ -33,7 +51,7 @@ module SendGrid
33
51
  def sendgrid_category(category)
34
52
  self.default_sg_category = category
35
53
  end
36
-
54
+
37
55
  # Enables a default option for all emails.
38
56
  # See documentation for details.
39
57
  #
@@ -51,14 +69,17 @@ module SendGrid
51
69
  end
52
70
 
53
71
  # Sets the default text for subscription tracking (must be enabled).
54
- # Should be a hash containing the html/plain text versions:
55
- # {:html => "html version", :plain => "plan text version"}
72
+ # There are two options:
73
+ # 1. Add an unsubscribe link at the bottom of the email
74
+ # {:html => "Unsubscribe <% here %>", :plain => "Unsubscribe here: <% %>"}
75
+ # 2. Replace given text with the unsubscribe link
76
+ # {:replace => "<unsubscribe_link>" }
56
77
  def sendgrid_subscriptiontrack_text(texts)
57
78
  self.default_subscriptiontrack_text = texts
58
79
  end
59
-
80
+
60
81
  # Sets the default footer text (must be enabled).
61
- # Should be a hash containing the html/plain text versions:
82
+ # Should be a hash containing the html/plain text versions:
62
83
  # {:html => "html version", :plain => "plan text version"}
63
84
  def sendgrid_footer_text(texts)
64
85
  self.default_footer_text = texts
@@ -68,6 +89,13 @@ module SendGrid
68
89
  def sendgrid_spamcheck_maxscore(score)
69
90
  self.default_spamcheck_score = score
70
91
  end
92
+
93
+ # Sets unique args at the class level. Should be a hash
94
+ # of name, value pairs.
95
+ # { :some_unique_arg => "some_value"}
96
+ def sendgrid_unique_args(unique_args = {})
97
+ self.default_sg_unique_args = unique_args
98
+ end
71
99
  end
72
100
 
73
101
  # Call within mailer method to override the default value.
@@ -75,45 +103,118 @@ module SendGrid
75
103
  @sg_category = category
76
104
  end
77
105
 
106
+ # Call within mailer method to set send time for this mail
107
+ def sendgrid_send_at(utc_timestamp)
108
+ @sg_send_at = utc_timestamp
109
+ end
110
+
111
+ # Call within mailer method to set unique args for this email.
112
+ # Merged with class-level unique args, if any exist.
113
+ def sendgrid_unique_args(unique_args = {})
114
+ @sg_unique_args = unique_args
115
+ end
116
+
78
117
  # Call within mailer method to add an option not in the defaults.
79
118
  def sendgrid_enable(*options)
80
119
  @sg_options = Array.new unless @sg_options
81
120
  options.each { |option| @sg_options << option if VALID_OPTIONS.include?(option) }
82
121
  end
83
-
122
+
84
123
  # Call within mailer method to remove one of the defaults.
85
124
  def sendgrid_disable(*options)
86
125
  @sg_disabled_options = Array.new unless @sg_disabled_options
87
126
  options.each { |option| @sg_disabled_options << option if VALID_OPTIONS.include?(option) }
88
127
  end
89
128
 
129
+ # Call within mailer method to add an array of recipients
130
+ def sendgrid_recipients(emails)
131
+ @sg_recipients = Array.new unless @sg_recipients
132
+ @sg_recipients = emails
133
+ end
134
+
135
+ # Call within mailer method to add an array of substitions
136
+ # NOTE: you must ensure that the length of the substitions equals the
137
+ # length of the sendgrid_recipients.
138
+ def sendgrid_substitute(placeholder, subs)
139
+ @sg_substitutions = Hash.new unless @sg_substitutions
140
+ @sg_substitutions[placeholder] = subs
141
+ end
142
+
90
143
  # Call within mailer method to override the default value.
91
144
  def sendgrid_subscriptiontrack_text(texts)
92
145
  @subscriptiontrack_text = texts
93
146
  end
94
-
147
+
95
148
  # Call within mailer method to override the default value.
96
149
  def sendgrid_footer_text(texts)
97
150
  @footer_text = texts
98
151
  end
99
-
152
+
100
153
  # Call within mailer method to override the default value.
101
154
  def sendgrid_spamcheck_maxscore(score)
102
155
  @spamcheck_score = score
103
156
  end
157
+
158
+ # Call within mailer method to set custom google analytics options
159
+ # http://sendgrid.com/documentation/appsGoogleAnalytics
160
+ def sendgrid_ganalytics_options(options)
161
+ @ganalytics_options = []
162
+ options.each { |option| @ganalytics_options << option if VALID_GANALYTICS_OPTIONS.include?(option[0].to_sym) }
163
+ end
104
164
 
105
- private
165
+ # only override the appropriate methods for the current ActionMailer version
166
+ if ActionMailer::Base.respond_to?(:mail)
167
+
168
+ protected
169
+
170
+ # Sets the custom X-SMTPAPI header after creating the email but before delivery
171
+ # NOTE: This override is used for Rails 3 ActionMailer classes.
172
+ def mail(headers={}, &block)
173
+ m = super
174
+ if @sg_substitutions && !@sg_substitutions.empty?
175
+ @sg_substitutions.each do |find, replace|
176
+ raise ArgumentError.new("Array for #{find} is not the same size as the recipient array") if replace.size != @sg_recipients.size
177
+ end
178
+ end
179
+ puts "SendGrid X-SMTPAPI: #{sendgrid_json_headers(message)}" if Object.const_defined?("SENDGRID_DEBUG_OUTPUT") && SENDGRID_DEBUG_OUTPUT
180
+ self.headers['X-SMTPAPI'] = sendgrid_json_headers(message)
181
+ m
182
+ end
183
+
184
+ else
185
+
186
+ # Sets the custom X-SMTPAPI header after creating the email but before delivery
187
+ # NOTE: This override is used for Rails 2 ActionMailer classes.
188
+ def create!(method_name, *parameters)
189
+ super
190
+ if @sg_substitutions && !@sg_substitutions.empty?
191
+ @sg_substitutions.each do |find, replace|
192
+ raise ArgumentError.new("Array for #{find} is not the same size as the recipient array") if replace.size != @sg_recipients.size
193
+ end
194
+ end
195
+ puts "SendGrid X-SMTPAPI: #{sendgrid_json_headers(mail)}" if Object.const_defined?("SENDGRID_DEBUG_OUTPUT") && SENDGRID_DEBUG_OUTPUT
196
+ @mail['X-SMTPAPI'] = sendgrid_json_headers(mail)
197
+ end
106
198
 
107
- # Sets the custom X-SMTPAPI header before sending the email
108
- def perform_delivery_smtp(mail)
109
- headers['X-SMTPAPI'] = sendgrid_json_headers(mail)
110
- super
111
199
  end
112
200
 
201
+ private
202
+
113
203
  # Take all of the options and turn it into the json format that SendGrid expects
114
204
  def sendgrid_json_headers(mail)
115
205
  header_opts = {}
116
206
 
207
+ #if not called within the mailer method, this will be nil so we default to empty hash
208
+ @sg_unique_args = @sg_unique_args || {}
209
+
210
+ # set the unique arguments
211
+ if @sg_unique_args || self.class.default_sg_unique_args
212
+ unique_args = self.class.default_sg_unique_args || {}
213
+ unique_args = unique_args.merge(@sg_unique_args)
214
+
215
+ header_opts[:unique_args] = unique_args unless unique_args.empty?
216
+ end
217
+
117
218
  # Set category
118
219
  if @sg_category && @sg_category == :use_subject_lines
119
220
  header_opts[:category] = mail.subject
@@ -125,35 +226,59 @@ module SendGrid
125
226
  header_opts[:category] = self.class.default_sg_category
126
227
  end
127
228
 
128
- # Set enables
129
- header_opts[:filters] = {} unless header_opts.has_key?(:filters)
130
- if (@sg_options && !@sg_options.empty?) || (@sg_disabled_options && !@sg_disabled_options.empty?)
229
+ #Set send_at if set by the user
230
+ header_opts[:send_at] = @sg_send_at unless @sg_send_at.blank?
231
+
232
+ # Set multi-recipients
233
+ if @sg_recipients && !@sg_recipients.empty?
234
+ header_opts[:to] = @sg_recipients
235
+ end
236
+
237
+ # Set custom substitions
238
+ if @sg_substitutions && !@sg_substitutions.empty?
239
+ header_opts[:sub] = @sg_substitutions
240
+ end
241
+
242
+ # Set enables/disables
243
+ enabled_opts = []
244
+ if @sg_options && !@sg_options.empty?
131
245
  # merge the options so that the instance-level "overrides"
132
- merged = self.class.default_sg_options
133
- merged += @sg_options if @sg_options
134
- merged.reject! { |option| @sg_disabled_options.include?(option) } if @sg_disabled_options
135
- header_opts[:filters] = filters_hash_from_options(merged)
136
- else
137
- header_opts[:filters] = filters_hash_from_options(self.class.default_sg_options)
246
+ merged = self.class.default_sg_options || []
247
+ merged += @sg_options
248
+ enabled_opts = merged
249
+ elsif self.class.default_sg_options
250
+ enabled_opts = self.class.default_sg_options
251
+ end
252
+ if !enabled_opts.empty? || (@sg_disabled_options && !@sg_disabled_options.empty?)
253
+ filters = filters_hash_from_options(enabled_opts, @sg_disabled_options)
254
+ header_opts[:filters] = filters if filters && !filters.empty?
138
255
  end
139
256
 
140
- header_opts.to_json
257
+ header_opts.to_json.gsub(/(["\]}])([,:])(["\[{])/, '\\1\\2 \\3')
141
258
  end
142
-
143
- def filters_hash_from_options(opts)
259
+
260
+ def filters_hash_from_options(enabled_opts, disabled_opts)
144
261
  filters = {}
145
- opts.each do |opt|
262
+ enabled_opts.each do |opt|
146
263
  filters[opt] = {'settings' => {'enable' => 1}}
147
264
  case opt.to_sym
148
265
  when :subscriptiontrack
149
266
  if @subscriptiontrack_text
150
- filters[:subscriptiontrack]['settings']['text/html'] = @subscriptiontrack_text[:html]
151
- filters[:subscriptiontrack]['settings']['text/plain'] = @subscriptiontrack_text[:plain]
267
+ if @subscriptiontrack_text[:replace]
268
+ filters[:subscriptiontrack]['settings']['replace'] = @subscriptiontrack_text[:replace]
269
+ else
270
+ filters[:subscriptiontrack]['settings']['text/html'] = @subscriptiontrack_text[:html]
271
+ filters[:subscriptiontrack]['settings']['text/plain'] = @subscriptiontrack_text[:plain]
272
+ end
152
273
  elsif self.class.default_subscriptiontrack_text
153
- filters[:subscriptiontrack]['settings']['text/html'] = self.class.default_subscriptiontrack_text[:html]
154
- filters[:subscriptiontrack]['settings']['text/plain'] = self.class.default_subscriptiontrack_text[:plain]
274
+ if self.class.default_subscriptiontrack_text[:replace]
275
+ filters[:subscriptiontrack]['settings']['replace'] = self.class.default_subscriptiontrack_text[:replace]
276
+ else
277
+ filters[:subscriptiontrack]['settings']['text/html'] = self.class.default_subscriptiontrack_text[:html]
278
+ filters[:subscriptiontrack]['settings']['text/plain'] = self.class.default_subscriptiontrack_text[:plain]
279
+ end
155
280
  end
156
-
281
+
157
282
  when :footer
158
283
  if @footer_text
159
284
  filters[:footer]['settings']['text/html'] = @footer_text[:html]
@@ -162,14 +287,28 @@ module SendGrid
162
287
  filters[:footer]['settings']['text/html'] = self.class.default_footer_text[:html]
163
288
  filters[:footer]['settings']['text/plain'] = self.class.default_footer_text[:plain]
164
289
  end
165
-
290
+
166
291
  when :spamcheck
167
292
  if self.class.default_spamcheck_score || @spamcheck_score
168
293
  filters[:spamcheck]['settings']['maxscore'] = @spamcheck_score || self.class.default_spamcheck_score
169
294
  end
295
+
296
+ when :ganalytics
297
+ if @ganalytics_options
298
+ @ganalytics_options.each do |key, value|
299
+ filters[:ganalytics]['settings'][key.to_s] = value
300
+ end
301
+ end
302
+ end
303
+ end
304
+
305
+ if disabled_opts
306
+ disabled_opts.each do |opt|
307
+ filters[opt] = {'settings' => {'enable' => 0}}
170
308
  end
171
309
  end
310
+
172
311
  return filters
173
312
  end
174
-
313
+
175
314
  end
data/sendgrid.gemspec ADDED
@@ -0,0 +1,63 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "sendgrid"
8
+ s.version = "1.2.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Stephen Blankenship", "Marc Tremblay", "Bob Burbach"]
12
+ s.date = "2016-01-08"
13
+ s.description = "This gem allows simple integration between ActionMailer and SendGrid. \n SendGrid is an email deliverability API that is affordable and has lots of bells and whistles."
14
+ s.email = "stephenrb@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/sendgrid.rb",
28
+ "lib/sendgrid/railtie.rb",
29
+ "lib/sendgrid/version.rb",
30
+ "sendgrid.gemspec",
31
+ "test/sendgrid_test.rb",
32
+ "test/test_helper.rb"
33
+ ]
34
+ s.homepage = "http://github.com/stephenb/sendgrid"
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = "1.8.23"
37
+ s.summary = "A gem that allows simple integration of ActionMailer with SendGrid (http://sendgrid.com)"
38
+
39
+ if s.respond_to? :specification_version then
40
+ s.specification_version = 3
41
+
42
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
+ s.add_runtime_dependency(%q<json>, [">= 0"])
44
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
45
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
46
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
47
+ s.add_runtime_dependency(%q<json>, [">= 0"])
48
+ else
49
+ s.add_dependency(%q<json>, [">= 0"])
50
+ s.add_dependency(%q<shoulda>, [">= 0"])
51
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
52
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
53
+ s.add_dependency(%q<json>, [">= 0"])
54
+ end
55
+ else
56
+ s.add_dependency(%q<json>, [">= 0"])
57
+ s.add_dependency(%q<shoulda>, [">= 0"])
58
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
59
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
60
+ s.add_dependency(%q<json>, [">= 0"])
61
+ end
62
+ end
63
+
@@ -1,7 +1,42 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class SendgridTest < Test::Unit::TestCase
4
- should "probably rename this file and start testing for real" do
5
- flunk "hey buddy, you should probably rename this file and start testing for real"
4
+ def setup
5
+ ActionMailer::Base.delivery_method = :test
6
+ ActionMailer::Base.perform_deliveries = true
7
+ ActionMailer::Base.deliveries = []
8
+
9
+ @options = {
10
+ :to => ['test@example.com'],
11
+ :from => 'test@example.com',
12
+ :reply_to => 'reply-to@example.com',
13
+ :subject => 'The Subject',
14
+ :body => '<html>content</html>',
15
+ :category => 'MyCategory',
16
+ :substitutions => {
17
+ 'first_name' => ['Joe'],
18
+ 'last_name' => ['Schmoe', 'Cool']
19
+ }
20
+ }
21
+ end
22
+
23
+ should "require the same number of items in a substitution array as is in the recipient array" do
24
+ assert_raise ArgumentError do
25
+ test_email = SendgridCampaignTestMailer.create_test(@options).deliver
26
+ end
27
+ end
28
+
29
+ should "accept a hash of unique args at the class level" do
30
+ assert_equal ({ :test_arg => "test value" }), SendgridUniqueArgsMailer.default_sg_unique_args
31
+ end
32
+
33
+ should "pass unique args from both the mailer class and the mailer method through custom headers" do
34
+ @options.delete(:substitutions)
35
+ SendgridUniqueArgsMailer.unique_args_test_email(@options).deliver
36
+ mail = ActionMailer::Base.deliveries.last
37
+ # assert({ :unique_args => {:mailer_method_unique_arg => "some value", :test_arg => "test value"} }.to_json == mail.header['X-SMTPAPI'].value)
38
+ expected = { 'unique_args' => {'mailer_method_unique_arg' => "some value", 'test_arg' => "test value"} }
39
+ actual = JSON.parse(mail.header['X-SMTPAPI'].value)
40
+ assert_equal(expected, actual)
6
41
  end
7
42
  end
data/test/test_helper.rb CHANGED
@@ -4,7 +4,54 @@ require 'shoulda'
4
4
 
5
5
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
6
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'action_mailer'
7
8
  require 'sendgrid'
8
9
 
9
- class Test::Unit::TestCase
10
+ class SendgridCampaignTestMailer < ActionMailer::Base
11
+ include SendGrid
12
+
13
+ sendgrid_enable :opentrack, :clicktrack, :subscriptiontrack, :bypass_list_management
14
+
15
+ REQUIRED_OPTIONS = [:to, :from, :category, :html_content, :subject]
16
+
17
+ ##
18
+ # options are:
19
+ # :from the from address
20
+ # :to an array of recipients
21
+ # :substitutions a hash of substitutions of the form: 'text to be
22
+ # replaced' => [replacements]. The order and size of the replacement
23
+ # array must match the :to array
24
+ # :category the sendgrid category used for tracking
25
+ # :html_content, :text_content, :subject
26
+ def create_test(options)
27
+ handle_sendgrid_options(options)
28
+ mail(options)
29
+ end
30
+
31
+ protected
32
+ def handle_sendgrid_options(options)
33
+ REQUIRED_OPTIONS.each do |option|
34
+ raise ArgumentError.new("Required sendgrid option ':#{option}' missing") unless options[option]
35
+ end
36
+
37
+ sendgrid_recipients(options[:to])
38
+
39
+ if options[:substitutions]
40
+ options[:substitutions].each do |find, replace|
41
+ sendgrid_substitute(find, replace)
42
+ end
43
+ end
44
+
45
+ sendgrid_category(options[:category])
46
+ end
10
47
  end
48
+
49
+ class SendgridUniqueArgsMailer < ActionMailer::Base
50
+ include SendGrid
51
+ sendgrid_unique_args({ :test_arg => "test value" })
52
+
53
+ def unique_args_test_email(options)
54
+ sendgrid_unique_args({ :mailer_method_unique_arg => "some value" })
55
+ mail(options)
56
+ end
57
+ end
metadata CHANGED
@@ -1,67 +1,143 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: sendgrid
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.4
5
+ prerelease:
5
6
  platform: ruby
6
- authors:
7
+ authors:
7
8
  - Stephen Blankenship
9
+ - Marc Tremblay
10
+ - Bob Burbach
8
11
  autorequire:
9
12
  bindir: bin
10
13
  cert_chain: []
11
-
12
- date: 2009-11-08 00:00:00 -07:00
13
- default_executable:
14
- dependencies: []
15
-
16
- description: |-
17
- This gem allows simple integration between ActionMailer and SendGrid.
18
- SendGrid is an email deliverability API that is affordable and has lots of bells and whistles.
14
+ date: 2016-01-08 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: json
18
+ requirement: !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: shoulda
34
+ requirement: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: bundler
50
+ requirement: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: 1.0.0
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ version: 1.0.0
64
+ - !ruby/object:Gem::Dependency
65
+ name: jeweler
66
+ requirement: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ~>
70
+ - !ruby/object:Gem::Version
71
+ version: 1.5.1
72
+ type: :development
73
+ prerelease: false
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ version: 1.5.1
80
+ - !ruby/object:Gem::Dependency
81
+ name: json
82
+ requirement: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ description: ! "This gem allows simple integration between ActionMailer and SendGrid.
97
+ \n SendGrid is an email deliverability API that is affordable
98
+ and has lots of bells and whistles."
19
99
  email: stephenrb@gmail.com
20
100
  executables: []
21
-
22
101
  extensions: []
23
-
24
- extra_rdoc_files:
102
+ extra_rdoc_files:
25
103
  - LICENSE
26
- - README.textile
27
- files:
104
+ - README.md
105
+ files:
28
106
  - .document
29
- - .gitignore
107
+ - Gemfile
108
+ - Gemfile.lock
30
109
  - LICENSE
31
- - README.textile
110
+ - README.md
32
111
  - Rakefile
33
112
  - VERSION
34
113
  - lib/sendgrid.rb
114
+ - lib/sendgrid/railtie.rb
115
+ - lib/sendgrid/version.rb
116
+ - sendgrid.gemspec
35
117
  - test/sendgrid_test.rb
36
118
  - test/test_helper.rb
37
- has_rdoc: true
38
119
  homepage: http://github.com/stephenb/sendgrid
39
120
  licenses: []
40
-
41
121
  post_install_message:
42
- rdoc_options:
43
- - --charset=UTF-8
44
- require_paths:
122
+ rdoc_options: []
123
+ require_paths:
45
124
  - lib
46
- required_ruby_version: !ruby/object:Gem::Requirement
47
- requirements:
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: "0"
51
- version:
52
- required_rubygems_version: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: "0"
57
- version:
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
58
137
  requirements: []
59
-
60
138
  rubyforge_project:
61
- rubygems_version: 1.3.5
139
+ rubygems_version: 1.8.23
62
140
  signing_key:
63
141
  specification_version: 3
64
142
  summary: A gem that allows simple integration of ActionMailer with SendGrid (http://sendgrid.com)
65
- test_files:
66
- - test/sendgrid_test.rb
67
- - test/test_helper.rb
143
+ test_files: []
data/.gitignore DELETED
@@ -1,5 +0,0 @@
1
- *.sw?
2
- .DS_Store
3
- coverage
4
- rdoc
5
- pkg
data/README.textile DELETED
@@ -1,95 +0,0 @@
1
- h1. sendgrid
2
-
3
- h3. What is SendGrid?
4
-
5
- SendGrid is an awesome way to send large amounts of email (bells and whistles included) without spending large amounts of money. This gem allows for painless integration between ActionMailer and the SendGrid SMTP API. The current scope of this gem is focused around setting configuration options for outgoing email (essentially, setting categories, filters and the settings that can accompany those filters). SendGrid's service allows for some other cool stuff (such as postback notification of unsubscribes, bounces, etc.), but you'll have to integrate those features on your own.
6
-
7
- Visit "SendGrid":http://sendgrid.com to learn more.
8
-
9
- h3. Getting Started
10
-
11
- First of all, you'll need the gem. "Click here to get it from gemcutter":http://gemcutter.org/gems/sendgrid.
12
-
13
- Before you can do anything with the sendgrid gem, you'll need to create your very own SendGrid account. Go ahead and do so at "http://sendgrid.com":http://sendgrid.com (there's even a FREE account option).
14
-
15
- Next, update your application's SMTP settings to use SendGrid's servers (see "SendGrid's getting started guide":http://wiki.sendgrid.com/doku.php?id=get_started for instructions).
16
-
17
- Example:
18
- <pre>
19
- ActionMailer::Base.smtp_settings = {
20
- :address => "smtp.sendgrid.net",
21
- :port => 25,
22
- :domain => "mysite.com",
23
- :authentication => :plain,
24
- :user_name => "sendgrd_username@mysite.com",
25
- :password => "sendgrid_password"
26
- }
27
- </pre>
28
-
29
- h3. Using the sendgrid Gem
30
-
31
- If you do not already have an ActionMailer class up and running, then check out "this guide.":http://guides.rubyonrails.org/action_mailer_basics.html#walkthrough-to-generating-a-mailer
32
-
33
- 1) add the following line within your mailer class:
34
- <pre>
35
- include SendGrid
36
- </pre>
37
-
38
- 2) customize your sendgrid settings:
39
-
40
- There are 2 types of settings
41
- - Category settings
42
- - Enable/disable settings
43
-
44
- You can set both global and per-email settings - the same syntax is used in either case.
45
- Here is an example of what typical usage may look like:
46
-
47
- <pre>
48
- class MyMailer < ActionMailer::Base
49
- include SendGrid
50
- sendgrid_category :use_subject_lines
51
- sendgrid_enable :ganalytics, :opentracking
52
-
53
- def welcome_message(to_user)
54
- sendgrid_category "Welcome"
55
-
56
- recipients to_user.email
57
- subject "Welcome :-)"
58
- body :to_user => to_user
59
- end
60
-
61
- def goodbye_message(to_user)
62
- sendgrid_disable :ganalytics
63
-
64
- recipients to_user.email
65
- subject "Fare thee well :-("
66
- body :to_user => to_user
67
- end
68
- end
69
- </pre>
70
-
71
- Category settings can be any text you like and will allow you to view statistics per-category (very nice). There is also a custom global setting that will automatically use the subject-line of your email as the sendgrid_category:
72
- <pre>
73
- sendgrid_category :use_subject_lines
74
- </pre>
75
- Calling sendgrid_cateogry from within one of your mailer methods will override this global setting. Similarly, calling sendgrid_enable/sendgrid_disable from within a mailer method will add or remove from any defaults that may have been set globally.
76
-
77
- Here are a list of supported options for sendgrid_enable and sendgrid_disable:
78
- * :opentrack
79
- * :clicktrack
80
- * :ganalytics
81
- * :gravatar
82
- * :subscriptiontrack
83
- ** Call sendgrid_subscriptiontrack_text(:html => 'Unsubscribe <% Here %>', :plain => 'Unsubscribe Here: <% %>') to set a custom format for html/plain or both.
84
- * :footer
85
- ** Call sendgrid_footer_text(:html => 'My HTML footer rocks!', :plain => 'My plain text footer is so-so.') to set custom footer text for html/plain or both.
86
- * :spamcheck
87
- ** Call sendgrid_spamcheck_maxscore(4.5) to set a custom SpamAssassin threshold at which SendGrid drops emails (default value is 5.0).
88
-
89
- For further explanation see "SendGrid's wiki page on filters.":http://wiki.sendgrid.com/doku.php?id=filters
90
-
91
- h3. TODO
92
-
93
- * Test coverage (I would appreciate help writing tests).
94
- * Possibly integrate with SendGrid's Event API and some of the other goodies they provide.
95
-