brightbytes-sendgrid 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/MIT-LICENSE +20 -0
- data/README.md +90 -0
- data/Rakefile +6 -0
- data/brightbytes-sendgrid.gemspec +27 -0
- data/lib/brightbytes/sendgrid.rb +61 -0
- data/lib/brightbytes/sendgrid/config.rb +34 -0
- data/lib/brightbytes/sendgrid/smtp_api_header.rb +130 -0
- data/lib/brightbytes/sendgrid/unsubscribe.rb +78 -0
- data/lib/brightbytes/sendgrid/version.rb +5 -0
- data/spec/brightbytes/sendgrid/smtp_api_header_spec.rb +74 -0
- data/spec/brightbytes/sendgrid/version_spec.rb +7 -0
- data/spec/brightbytes/sendgrid_mailer_spec.rb +55 -0
- data/spec/brightbytes/sendgrid_spec.rb +15 -0
- data/spec/brightbytes/standard_mailer_spec.rb +39 -0
- data/spec/mailers/sendgrid_mailer.rb +33 -0
- data/spec/mailers/standard_mailer.rb +18 -0
- data/spec/spec_helper.rb +36 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OTI3NjE1NjIxNDJjNGEyZGUxZGUyMDJlOTMwNjQxMTEyOTk5MWFmMA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YTlhNDdiYjUyYjRkZTY3ZjBiMmE3ZjNkZTJkMjViMTVmODkwNDY5Ng==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZWNhZjJhMWYwY2U3NGFlNjIwM2FmZGVlMGQ1MjczZmYwYzVmODAwODZmZjc3
|
10
|
+
ZDk2M2IzMDUxYWE3Nzg2OTY3NzhlY2Y2ZDhmZjUwMGY2ZTZiYTMxOTEwMDdl
|
11
|
+
ZDhiMTkxYTQwZjA5OTgxZmIzN2U5NmI4NjVkMDQ2MzQ1NTM0ZjU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
M2VmOGI0MGFlZTI0Yzg0MzRiYTRhNWEzOTZiOTFiMGZjOWI4MjQ4M2MwNjY5
|
14
|
+
MGJhNmJmNDJkNDNkMGQyNGZiYjNhODZiOGM5YzBmZjQyNTE5NDZhMmZhMmIx
|
15
|
+
ZTAyZTdjNDM0MjE2MDE4ODM0NWYwNGVkOWZjMzBkYjc1MTcwZDU=
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
brightbytes-sendgrid
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p484
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Serhiy Rozum
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 BrightBytes Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# Brightbytes::Sendgrid
|
2
|
+
|
3
|
+
This gem allows for painless integration between ActionMailer and the SendGrid SMTP API.
|
4
|
+
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).
|
5
|
+
|
6
|
+
SendGrid's service allows to automatically include Unsubscribe link into your emails. Unfortunately, SendGrid doesn't manage multiple unsubscriptions lists based on your's emails categories.
|
7
|
+
|
8
|
+
Visit [SendGrid SMTP API](http://sendgrid.com/docs/API_Reference/SMTP_API/index.html) to learn more.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'brightbytes-sendgrid'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install brightbytes-sendgrid
|
23
|
+
|
24
|
+
In your config/initializers/sendgrid.rb:
|
25
|
+
|
26
|
+
ActionMailer::Base.send :include, Brightbytes::Sendgrid
|
27
|
+
|
28
|
+
Brightbytes::Sendgrid.configure do |config|
|
29
|
+
config.default_categories :system
|
30
|
+
config.unsubscribe_categories :system, :onboarding
|
31
|
+
config.unsubscribe_url 'http://brightbytes.net/unsubscribe'
|
32
|
+
end
|
33
|
+
|
34
|
+
Or use it with selected mailers:
|
35
|
+
|
36
|
+
Brightbytes::Sendgrid
|
37
|
+
|
38
|
+
## Usage
|
39
|
+
|
40
|
+
You can use following methods to set both global and per-email SendGrid SMTP API header options:
|
41
|
+
|
42
|
+
**sendgrid_substitute**
|
43
|
+
|
44
|
+
sendgrid_substitute :full_name, ['Jack', 'John']
|
45
|
+
sendgrid_substitute '{{some_text}}', 'another text'
|
46
|
+
|
47
|
+
**sendgrid_section**
|
48
|
+
|
49
|
+
sendgrid_section :greeting, I18n.translate('Hello')
|
50
|
+
|
51
|
+
**sendgrid_unique_args**
|
52
|
+
|
53
|
+
sendgrid_unique_args email_id: 12345
|
54
|
+
|
55
|
+
**sendgrid_categories**
|
56
|
+
|
57
|
+
sendgrid_categories :newsletter
|
58
|
+
|
59
|
+
**sendgrid_recipients**
|
60
|
+
|
61
|
+
sendgrid_recipients 'email1@email.com', 'email2@email.com'
|
62
|
+
|
63
|
+
**sendgrid_enable**
|
64
|
+
|
65
|
+
sendgrid_enable :opentrack
|
66
|
+
|
67
|
+
**sendgrid_disable**
|
68
|
+
|
69
|
+
sendgrid_disable :clicktrack
|
70
|
+
|
71
|
+
## Auto generated unsubscribe link
|
72
|
+
|
73
|
+
It is not a SendGrid **subscriptiontrack** filter!
|
74
|
+
|
75
|
+
What we diong here is just collecting recipients and generating unsubscribe links for every recipient.
|
76
|
+
Those links will be sent as a substitutions to SendGrid.
|
77
|
+
|
78
|
+
So, to make this feature work, you have to:
|
79
|
+
|
80
|
+
1. Configure unsubscribe categories. It will trigger link generator
|
81
|
+
2. Configure an unsubscribe_url. The resulting URL will be composed of unsubscribe_url and email and category parameters.
|
82
|
+
3. Put {{unsubscribe}} placeholder somewhere in your email body
|
83
|
+
|
84
|
+
##Contributors
|
85
|
+
|
86
|
+
This gem is written using code samples from:
|
87
|
+
|
88
|
+
* [http://github.com/stephenb/sendgrid](http://github.com/stephenb/sendgrid)
|
89
|
+
* [https://github.com/kylejginavan/sendgrid_smtpapi](https://github.com/kylejginavan/sendgrid_smtpapi)
|
90
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'brightbytes/sendgrid/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "brightbytes-sendgrid"
|
8
|
+
spec.version = Brightbytes::Sendgrid::VERSION
|
9
|
+
spec.authors = ["Serhiy Rozum"]
|
10
|
+
spec.email = ["serhiy@brightbytes.net"]
|
11
|
+
spec.summary = %q{BrightBytes and Sendgrid integration gem}
|
12
|
+
spec.description = %q{Gem to extend ActionMailer with SMTP API support}
|
13
|
+
spec.homepage = "https://github.com/brightbytes/brightbytes-sendgrid"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.1"
|
23
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
24
|
+
spec.add_development_dependency "actionmailer", "~> 3.2"
|
25
|
+
|
26
|
+
spec.add_dependency "activesupport", "~> 3.2"
|
27
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'brightbytes/sendgrid/smtp_api_header'
|
4
|
+
require 'brightbytes/sendgrid/config'
|
5
|
+
require 'brightbytes/sendgrid/unsubscribe'
|
6
|
+
require 'brightbytes/sendgrid/version'
|
7
|
+
|
8
|
+
module Brightbytes
|
9
|
+
module Sendgrid
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
autoload :SmtpApiHeader, 'sendgrid/smtp_api_header'
|
13
|
+
autoload :Config, 'sendgrid/config'
|
14
|
+
autoload :Unsubscribe, 'sendgrid/unsubscribe'
|
15
|
+
autoload :VERSION, 'sendgrid/version'
|
16
|
+
|
17
|
+
included do
|
18
|
+
delegate *Brightbytes::Sendgrid::SmtpApiHeader::DELEGATE_METHODS, to: :sendgrid, prefix: true
|
19
|
+
alias_method_chain :mail, :sendgrid
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def sendgrid
|
25
|
+
@sendgrid ||= Brightbytes::Sendgrid::SmtpApiHeader.new(self.class.sendgrid.data)
|
26
|
+
end
|
27
|
+
|
28
|
+
def mail_with_sendgrid(headers={}, &block)
|
29
|
+
mail_without_sendgrid(headers, &block).tap do |message|
|
30
|
+
# Add Unsubscribe links
|
31
|
+
Brightbytes::Sendgrid::Unsubscribe.add_links(sendgrid, message)
|
32
|
+
# Store Sendgrid in Message for future use
|
33
|
+
message.instance_variable_set :@sendgrid, sendgrid
|
34
|
+
# Add X-SMTPAPI Header
|
35
|
+
message.header['X-SMTPAPI'] = sendgrid.to_json if sendgrid.data.present?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module ClassMethods
|
40
|
+
|
41
|
+
delegate *Brightbytes::Sendgrid::SmtpApiHeader::DELEGATE_METHODS, to: :sendgrid, prefix: true
|
42
|
+
|
43
|
+
def sendgrid
|
44
|
+
@sendgrid ||= Brightbytes::Sendgrid::SmtpApiHeader.new(Brightbytes::Sendgrid.config.sendgrid.data)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class << self
|
50
|
+
|
51
|
+
def config
|
52
|
+
Brightbytes::Sendgrid::Config.instance
|
53
|
+
end
|
54
|
+
|
55
|
+
def configure
|
56
|
+
yield(self.config) if block_given?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Brightbytes
|
4
|
+
module Sendgrid
|
5
|
+
class Config
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
# Sendgrid default settings storage
|
9
|
+
|
10
|
+
delegate *Brightbytes::Sendgrid::SmtpApiHeader::DELEGATE_METHODS, to: :sendgrid, prefix: :default
|
11
|
+
|
12
|
+
def sendgrid
|
13
|
+
@sendgrid ||= Brightbytes::Sendgrid::SmtpApiHeader.new
|
14
|
+
end
|
15
|
+
|
16
|
+
# Unsubscribe default settings storage
|
17
|
+
|
18
|
+
class UnsubscribeConfig < Struct.new(:categories, :url); end
|
19
|
+
|
20
|
+
def unsubscribe
|
21
|
+
@unsubscribe ||= UnsubscribeConfig.new([],nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
def unsubscribe_categories(*categories)
|
25
|
+
unsubscribe.categories = categories.flatten.map(&:to_sym)
|
26
|
+
end
|
27
|
+
|
28
|
+
def unsubscribe_url(url)
|
29
|
+
unsubscribe.url = url
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Brightbytes
|
4
|
+
module Sendgrid
|
5
|
+
class SmtpApiHeader
|
6
|
+
|
7
|
+
DELEGATE_METHODS = [
|
8
|
+
:substitute,
|
9
|
+
:add_substitute,
|
10
|
+
:section,
|
11
|
+
:unique_args,
|
12
|
+
:categories,
|
13
|
+
:add_categories,
|
14
|
+
:recipients,
|
15
|
+
:add_recipients,
|
16
|
+
:filter_setting,
|
17
|
+
:enable,
|
18
|
+
:disable,
|
19
|
+
:ganalytics_options
|
20
|
+
]
|
21
|
+
|
22
|
+
VALID_FILTERS = [
|
23
|
+
:bcc,
|
24
|
+
:dkim,
|
25
|
+
:domainkeys,
|
26
|
+
:forwardspam,
|
27
|
+
:opentrack,
|
28
|
+
:clicktrack,
|
29
|
+
:ganalytics,
|
30
|
+
:gravatar,
|
31
|
+
:subscriptiontrack,
|
32
|
+
:template,
|
33
|
+
:footer,
|
34
|
+
:spamcheck,
|
35
|
+
:bypass_list_management
|
36
|
+
]
|
37
|
+
|
38
|
+
VALID_GANALYTICS_OPTIONS = [
|
39
|
+
:utm_source,
|
40
|
+
:utm_medium,
|
41
|
+
:utm_campaign,
|
42
|
+
:utm_term,
|
43
|
+
:utm_content
|
44
|
+
]
|
45
|
+
|
46
|
+
SUBST_PATTERN = '{{\1}}'
|
47
|
+
|
48
|
+
attr_reader :data
|
49
|
+
|
50
|
+
def initialize(default_data = nil)
|
51
|
+
@data = default_data.instance_of?(Hash) ? default_data.dup : Hash.new { |h,k| h[k] = Hash.new(&h.default_proc) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def substitute(key, values)
|
55
|
+
@data[:sub][key_to_tag(key)] = Array.wrap(values)
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_substitute(key, values)
|
59
|
+
@data[:sub][key_to_tag(key)] = [] unless @data[:sub][key_to_tag(key)].instance_of?(Array)
|
60
|
+
@data[:sub][key_to_tag(key)] += Array.wrap(values)
|
61
|
+
end
|
62
|
+
|
63
|
+
def section(key, value)
|
64
|
+
@data[:section][key_to_tag(key)] = value.to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
def unique_args(value)
|
68
|
+
@data[:unique_args] = value if value.instance_of?(Hash)
|
69
|
+
end
|
70
|
+
|
71
|
+
# getter/setter
|
72
|
+
def categories(*categories)
|
73
|
+
@data[:category] = categories.flatten.map(&:to_sym) if categories.flatten.present?
|
74
|
+
@data.fetch(:category, [])
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_categories(*categories)
|
78
|
+
init_array_key :category
|
79
|
+
@data[:category] |= categories.flatten.map(&:to_sym)
|
80
|
+
end
|
81
|
+
|
82
|
+
# getter/setter
|
83
|
+
def recipients(*recipients)
|
84
|
+
@data[:to] = recipients.flatten if recipients.flatten.present?
|
85
|
+
@data.fetch(:to, [])
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_recipients(*recipients)
|
89
|
+
init_array_key :to
|
90
|
+
@data[:to] += recipients.flatten
|
91
|
+
end
|
92
|
+
|
93
|
+
def filter_setting(filter, setting, value)
|
94
|
+
return unless VALID_FILTERS.include? filter
|
95
|
+
@data[:filters][filter][:settings][setting] = value
|
96
|
+
end
|
97
|
+
|
98
|
+
def enable(*filters)
|
99
|
+
filters.flatten.each { |filter| filter_setting filter, :enabled, 1 }
|
100
|
+
end
|
101
|
+
|
102
|
+
def disable(*filters)
|
103
|
+
filters.flatten.each { |filter| filter_setting filter, :enabled, 0 }
|
104
|
+
end
|
105
|
+
|
106
|
+
def ganalytics_options(options = {})
|
107
|
+
options.reject! { |k,v| !VALID_GANALYTICS_OPTIONS.include?(k) }
|
108
|
+
if options.present?
|
109
|
+
options.each { |setting, value| filter_setting :ganalytics, setting, value }
|
110
|
+
enable :ganalytics
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def to_json
|
115
|
+
JSON.generate(@data, {indent: '', space: ' ', space_before: '', object_nl: '', array_nl: ''})
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def key_to_tag(key)
|
121
|
+
key.is_a?(Symbol) ? key.to_s.sub(/(.*)/, SUBST_PATTERN) : key.to_s
|
122
|
+
end
|
123
|
+
|
124
|
+
def init_array_key(key)
|
125
|
+
@data[key] = [] unless @data[key].instance_of?(Array)
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Unsubscribe feature have some conventions:
|
2
|
+
# - {{unsubscribe}} substitution variable must be placed somewhere in email template or body
|
3
|
+
#
|
4
|
+
module Brightbytes
|
5
|
+
module Sendgrid
|
6
|
+
class Unsubscribe
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def add_links(sendgrid, message)
|
11
|
+
new(sendgrid, message).add_links
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :sendgrid
|
17
|
+
attr_reader :message
|
18
|
+
|
19
|
+
def initialize(sendgrid, message)
|
20
|
+
@sendgrid, @message = sendgrid, message
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_links
|
24
|
+
return unless feature_active?
|
25
|
+
if categories.present?
|
26
|
+
sendgrid.section :unsubscribe, "<a href=\"{{unsubscribe_link}}\">Unsubscribe</a>"
|
27
|
+
emails.each do |email|
|
28
|
+
sendgrid.add_substitute :unsubscribe_link, unsubscribe_link(email)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
sendgrid.section :unsubscribe, ''
|
32
|
+
sendgrid.add_substitute :unsubscribe_link, Array.new(emails.size, '')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def config
|
39
|
+
Brightbytes::Sendgrid.config.unsubscribe
|
40
|
+
end
|
41
|
+
|
42
|
+
delegate :categories, :url, to: :config, prefix: :unsubscribe
|
43
|
+
|
44
|
+
def feature_active?
|
45
|
+
unsubscribe_categories.present? || unsubscribe_url.present?
|
46
|
+
end
|
47
|
+
|
48
|
+
def categories
|
49
|
+
@categories ||= unsubscribe_categories & sendgrid.categories
|
50
|
+
end
|
51
|
+
|
52
|
+
def emails
|
53
|
+
@emails ||= recipients.map{ |e| e =~ /([^<]+)\s<(.*)>|(.*)/; $2 || $3 }
|
54
|
+
end
|
55
|
+
|
56
|
+
def recipients
|
57
|
+
sendgrid.recipients + message_recipients
|
58
|
+
end
|
59
|
+
|
60
|
+
def message_recipients
|
61
|
+
Array.wrap(message.to) + Array.wrap(message.cc) + Array.wrap(message.bcc)
|
62
|
+
end
|
63
|
+
|
64
|
+
def unsubscribe_link(email)
|
65
|
+
if unsubscribe_url.instance_of? Proc
|
66
|
+
unsubscribe_url.call(email: email, category: categories)
|
67
|
+
else
|
68
|
+
"#{unsubscribe_url}#{unsubscribe_url[-1] == '?' ? '' : '?'}#{url_parameters(email)}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def url_parameters(email)
|
73
|
+
URI.encode_www_form(email: email, category: categories)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Brightbytes::Sendgrid::SmtpApiHeader do
|
4
|
+
|
5
|
+
let(:header) { described_class.new }
|
6
|
+
|
7
|
+
subject { header.to_json }
|
8
|
+
|
9
|
+
it { should eql '{}' }
|
10
|
+
|
11
|
+
it "contains substitution" do
|
12
|
+
header.substitute :key, 'Hello'
|
13
|
+
should eql '{"sub": {"{{key}}": ["Hello"]}}'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "adds substitution" do
|
17
|
+
header.substitute :key, 'Hello'
|
18
|
+
header.add_substitute :key, ['Again', 'And Again']
|
19
|
+
should eql '{"sub": {"{{key}}": ["Hello","Again","And Again"]}}'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "contains section" do
|
23
|
+
header.section :key, 'Hello'
|
24
|
+
should eql '{"section": {"{{key}}": "Hello"}}'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "contains category" do
|
28
|
+
header.categories :category_name
|
29
|
+
should eql '{"category": ["category_name"]}'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "adds category" do
|
33
|
+
header.categories :category_name
|
34
|
+
header.add_categories :new_category, :category_name
|
35
|
+
should eql '{"category": ["category_name","new_category"]}'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "contains 1 recipient (as array)" do
|
39
|
+
header.recipients 'email1@email.com'
|
40
|
+
should eql '{"to": ["email1@email.com"]}'
|
41
|
+
end
|
42
|
+
|
43
|
+
it "adds recipients" do
|
44
|
+
header.recipients 'email1@email.com'
|
45
|
+
header.add_recipients 'email2@email.com'
|
46
|
+
should eql '{"to": ["email1@email.com","email2@email.com"]}'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "contains unique args" do
|
50
|
+
header.unique_args arg1: 'val1'
|
51
|
+
should eql '{"unique_args": {"arg1": "val1"}}'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "contains valid filter settings" do
|
55
|
+
header.filter_setting :opentrack, :setting, 'value'
|
56
|
+
should eql '{"filters": {"opentrack": {"settings": {"setting": "value"}}}}'
|
57
|
+
end
|
58
|
+
|
59
|
+
it "skips invalid filter settings" do
|
60
|
+
header.filter_setting :somefilter, :setting, 'value'
|
61
|
+
should eql '{}'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "enables filters" do
|
65
|
+
header.enable :opentrack, :bcc
|
66
|
+
should eql '{"filters": {"opentrack": {"settings": {"enabled": 1}},"bcc": {"settings": {"enabled": 1}}}}'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "disables filters" do
|
70
|
+
header.disable :opentrack, :bcc
|
71
|
+
should eql '{"filters": {"opentrack": {"settings": {"enabled": 0}},"bcc": {"settings": {"enabled": 0}}}}'
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SendgridMailer do
|
4
|
+
|
5
|
+
let(:header) { subject.header.to_s.gsub(/\r|\n/, "") }
|
6
|
+
|
7
|
+
describe "when sendgrid default category is set" do
|
8
|
+
subject(:message) { described_class.default_category }
|
9
|
+
|
10
|
+
it 'header should have category' do
|
11
|
+
header.should include('"category": ["system"]')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "when sendgrid category is set" do
|
16
|
+
subject(:message) { described_class.new_category }
|
17
|
+
|
18
|
+
it 'header should have new category' do
|
19
|
+
header.should include('"category": ["new_category"]')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "when sendgrid recipients are set" do
|
24
|
+
subject(:message) { described_class.with_recipients }
|
25
|
+
|
26
|
+
it 'header should have recipients' do
|
27
|
+
header.should include('"to": ["email1@email.com","email2@email.com"]')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "when unsubscribe not required" do
|
32
|
+
subject(:message) { described_class.unsubscribe_not_required }
|
33
|
+
|
34
|
+
before(:each) { sendgrid_config_setup }
|
35
|
+
|
36
|
+
it 'unsubscribe section should be empty' do
|
37
|
+
header.should include('"{{unsubscribe}}": ""')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "when unsubscribe required" do
|
42
|
+
subject(:message) { described_class.unsubscribe_required }
|
43
|
+
|
44
|
+
before(:each) { sendgrid_config_setup }
|
45
|
+
|
46
|
+
it 'unsubscribe section should be set' do
|
47
|
+
header.should include('"{{unsubscribe}}": "<a href=\"{{unsubscribe_link}}\">Unsubscribe</a>"')
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'unsubscribe link should be set' do
|
51
|
+
header.should include('"{{unsubscribe_link}}": ["http://example.com/u?email=email1%40email.com&category=unsubscribe","http://example.com/u?email=email2%40email.com&category=unsubscribe","http://example.com/u?email=email%40email.com&category=unsubscribe"]')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe StandardMailer do
|
4
|
+
|
5
|
+
let(:header) { subject.header.to_s.gsub(/\r|\n/, "") }
|
6
|
+
|
7
|
+
describe "when sendgrid not engaged" do
|
8
|
+
subject(:message) { described_class.sendgrid_not_engaged }
|
9
|
+
|
10
|
+
it 'header should not be set' do
|
11
|
+
header.should_not include('X-SMTPAPI:')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "when unsubscribe not required" do
|
16
|
+
subject(:message) { described_class.unsubscribe_not_required }
|
17
|
+
|
18
|
+
before(:each) { sendgrid_config_setup }
|
19
|
+
|
20
|
+
it 'unsubscribe section should be empty' do
|
21
|
+
header.should include('"{{unsubscribe}}": ""')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "when unsubscribe required" do
|
26
|
+
subject(:message) { described_class.unsubscribe_required }
|
27
|
+
|
28
|
+
before(:each) { sendgrid_config_setup }
|
29
|
+
|
30
|
+
it 'unsubscribe section should be set' do
|
31
|
+
header.should include('"{{unsubscribe}}": "<a href=\"{{unsubscribe_link}}\">Unsubscribe</a>"')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'unsubscribe link should be set' do
|
35
|
+
header.should include('"{{unsubscribe_link}}": ["http://example.com/u?email=email%40email.com&category=unsubscribe"]')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class SendgridMailer < ActionMailer::Base
|
2
|
+
default from: 'noreply@brightbytes.net',
|
3
|
+
subject: 'Clarity'
|
4
|
+
|
5
|
+
sendgrid_categories :system
|
6
|
+
|
7
|
+
def default_category
|
8
|
+
mail to: 'email@email.com', body: 'Hello!'
|
9
|
+
end
|
10
|
+
|
11
|
+
def new_category
|
12
|
+
sendgrid_categories :new_category
|
13
|
+
mail to: 'email@email.com', body: 'Hello!'
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_recipients
|
17
|
+
sendgrid_recipients 'email1@email.com', 'email2@email.com'
|
18
|
+
mail to: 'email@email.com', body: 'Hello!'
|
19
|
+
end
|
20
|
+
|
21
|
+
def unsubscribe_not_required
|
22
|
+
sendgrid_recipients 'email1@email.com', 'email2@email.com'
|
23
|
+
mail to: 'email@email.com', body: 'Hello!'
|
24
|
+
end
|
25
|
+
|
26
|
+
def unsubscribe_required
|
27
|
+
sendgrid_recipients 'email1@email.com', 'email2@email.com'
|
28
|
+
sendgrid_categories :unsubscribe
|
29
|
+
mail to: 'email@email.com', body: 'Hello!'
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class StandardMailer < ActionMailer::Base
|
2
|
+
default from: 'noreply@brightbytes.net',
|
3
|
+
subject: 'Clarity'
|
4
|
+
|
5
|
+
def sendgrid_not_engaged
|
6
|
+
mail to: 'email@email.com', body: 'Hello!'
|
7
|
+
end
|
8
|
+
|
9
|
+
def unsubscribe_not_required
|
10
|
+
mail to: 'email@email.com', body: 'Hello!'
|
11
|
+
end
|
12
|
+
|
13
|
+
def unsubscribe_required
|
14
|
+
sendgrid_categories :unsubscribe
|
15
|
+
mail to: 'email@email.com', body: 'Hello!'
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'action_mailer'
|
3
|
+
require 'brightbytes/sendgrid'
|
4
|
+
|
5
|
+
ActionMailer::Base.delivery_method = :test
|
6
|
+
ActionMailer::Base.perform_deliveries = true
|
7
|
+
ActionMailer::Base.deliveries = []
|
8
|
+
|
9
|
+
ActionMailer::Base.send :include, Brightbytes::Sendgrid
|
10
|
+
|
11
|
+
Dir["#{File.dirname(__FILE__)}/mailers/*.rb"].each { |f| require f }
|
12
|
+
|
13
|
+
def sendgrid_config_setup
|
14
|
+
Brightbytes::Sendgrid.configure do |config|
|
15
|
+
config.unsubscribe_categories :unsubscribe
|
16
|
+
config.unsubscribe_url 'http://example.com/u'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def sendgrid_config_reset
|
21
|
+
Brightbytes::Sendgrid.configure do |config|
|
22
|
+
config.unsubscribe_categories []
|
23
|
+
config.unsubscribe_url nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
RSpec.configure do |config|
|
28
|
+
|
29
|
+
config.after(:each) do
|
30
|
+
Brightbytes::Sendgrid.configure do |config|
|
31
|
+
config.unsubscribe_categories []
|
32
|
+
config.unsubscribe_url nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: brightbytes-sendgrid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Serhiy Rozum
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.14'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.14'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: actionmailer
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.2'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activesupport
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.2'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.2'
|
83
|
+
description: Gem to extend ActionMailer with SMTP API support
|
84
|
+
email:
|
85
|
+
- serhiy@brightbytes.net
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- .rspec
|
92
|
+
- .ruby-gemset
|
93
|
+
- .ruby-version
|
94
|
+
- .travis.yml
|
95
|
+
- Gemfile
|
96
|
+
- LICENSE.txt
|
97
|
+
- MIT-LICENSE
|
98
|
+
- README.md
|
99
|
+
- Rakefile
|
100
|
+
- brightbytes-sendgrid.gemspec
|
101
|
+
- lib/brightbytes/sendgrid.rb
|
102
|
+
- lib/brightbytes/sendgrid/config.rb
|
103
|
+
- lib/brightbytes/sendgrid/smtp_api_header.rb
|
104
|
+
- lib/brightbytes/sendgrid/unsubscribe.rb
|
105
|
+
- lib/brightbytes/sendgrid/version.rb
|
106
|
+
- spec/brightbytes/sendgrid/smtp_api_header_spec.rb
|
107
|
+
- spec/brightbytes/sendgrid/version_spec.rb
|
108
|
+
- spec/brightbytes/sendgrid_mailer_spec.rb
|
109
|
+
- spec/brightbytes/sendgrid_spec.rb
|
110
|
+
- spec/brightbytes/standard_mailer_spec.rb
|
111
|
+
- spec/mailers/sendgrid_mailer.rb
|
112
|
+
- spec/mailers/standard_mailer.rb
|
113
|
+
- spec/spec_helper.rb
|
114
|
+
homepage: https://github.com/brightbytes/brightbytes-sendgrid
|
115
|
+
licenses:
|
116
|
+
- MIT
|
117
|
+
metadata: {}
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 2.2.1
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: BrightBytes and Sendgrid integration gem
|
138
|
+
test_files:
|
139
|
+
- spec/brightbytes/sendgrid/smtp_api_header_spec.rb
|
140
|
+
- spec/brightbytes/sendgrid/version_spec.rb
|
141
|
+
- spec/brightbytes/sendgrid_mailer_spec.rb
|
142
|
+
- spec/brightbytes/sendgrid_spec.rb
|
143
|
+
- spec/brightbytes/standard_mailer_spec.rb
|
144
|
+
- spec/mailers/sendgrid_mailer.rb
|
145
|
+
- spec/mailers/standard_mailer.rb
|
146
|
+
- spec/spec_helper.rb
|