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 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
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
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
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in brightbytes-sendgrid.gemspec
4
+ gemspec
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,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -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,5 @@
1
+ module Brightbytes
2
+ module Sendgrid
3
+ VERSION = "0.0.1"
4
+ end
5
+ 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,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brightbytes::Sendgrid::VERSION do
4
+ it "should be a version number" do
5
+ should_not be_nil
6
+ end
7
+ 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,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brightbytes::Sendgrid do
4
+
5
+ describe "config" do
6
+
7
+ subject { described_class.config }
8
+
9
+ it "should be an instance of Config " do
10
+ should be_instance_of Brightbytes::Sendgrid::Config
11
+ end
12
+
13
+ end
14
+
15
+ 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
@@ -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