sendgrid-ruby 0.0.3 → 1.0.0.alpha.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 +4 -4
- data/.gitignore +35 -17
- data/.rspec +2 -0
- data/.rubocop.yml +30 -0
- data/.travis.yml +20 -0
- data/Guardfile +7 -9
- data/README.md +11 -2
- data/Rakefile +5 -5
- data/lib/sendgrid/client.rb +63 -0
- data/lib/sendgrid/mail.rb +114 -34
- data/lib/sendgrid/response.rb +14 -0
- data/lib/sendgrid/version.rb +1 -1
- data/lib/sendgrid_ruby.rb +5 -0
- data/sendgrid-ruby.gemspec +7 -3
- data/spec/lib/sendgrid/client_spec.rb +83 -0
- data/spec/lib/sendgrid/mail_spec.rb +123 -0
- data/spec/lib/sendgrid_spec.rb +7 -0
- data/spec/spec_helper.rb +1 -0
- metadata +85 -16
- data/lib/sendgrid-ruby.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 151bbef80094a16705ac90105265586a3b297f72
|
4
|
+
data.tar.gz: 978bc5da9b1f788440e1e7e55cb821a0864571da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6445b8feda2318bb755c4a0a448f3456610d2de94982ae223acee641e1c5a1ea4ac6177e94fd89fd46323434f71512221528f904a967738f5aed176c0634e6c7
|
7
|
+
data.tar.gz: 379ae309fb47ad14331bc2747b226f016a865c8671d45567ab725eef5f2fdb8db4daf305ffba6143d3070b99302472863017484f860282b052b5d32116b18f6d
|
data/.gitignore
CHANGED
@@ -1,21 +1,39 @@
|
|
1
|
+
# Created by https://www.gitignore.io
|
2
|
+
|
3
|
+
### Ruby ###
|
1
4
|
*.gem
|
2
5
|
*.rbc
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
+
/.config
|
7
|
+
/coverage/
|
8
|
+
/InstalledFiles
|
9
|
+
/pkg/
|
10
|
+
/spec/reports/
|
11
|
+
/test/tmp/
|
12
|
+
/test/version_tmp/
|
13
|
+
/tmp/
|
14
|
+
|
15
|
+
## Specific to RubyMotion:
|
16
|
+
.dat*
|
17
|
+
.repl_history
|
18
|
+
build/
|
19
|
+
|
20
|
+
## Documentation cache and generated files:
|
21
|
+
/.yardoc/
|
22
|
+
/_yardoc/
|
23
|
+
/doc/
|
24
|
+
/rdoc/
|
25
|
+
|
26
|
+
## Environment normalisation:
|
27
|
+
/.bundle/
|
28
|
+
/vendor/bundle
|
29
|
+
/lib/bundler/man/
|
30
|
+
|
31
|
+
# for a library or gem, you might want to ignore these files since the code is
|
32
|
+
# intended to run in multiple environments; otherwise, check them in:
|
6
33
|
Gemfile.lock
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
pkg
|
13
|
-
rdoc
|
34
|
+
.ruby-version
|
35
|
+
.ruby-gemset
|
36
|
+
|
37
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
38
|
+
.rvmrc
|
14
39
|
|
15
|
-
tmp
|
16
|
-
*.bundle
|
17
|
-
*.so
|
18
|
-
*.o
|
19
|
-
*.a
|
20
|
-
mkmf.log
|
21
|
-
.DS_Store
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Metrics/AbcSize:
|
2
|
+
Max: 37
|
3
|
+
|
4
|
+
# Configuration parameters: CountComments.
|
5
|
+
Metrics/ClassLength:
|
6
|
+
Max: 109
|
7
|
+
|
8
|
+
Metrics/CyclomaticComplexity:
|
9
|
+
Max: 7
|
10
|
+
|
11
|
+
# Configuration parameters: AllowURI, URISchemes.
|
12
|
+
Metrics/LineLength:
|
13
|
+
Max: 132
|
14
|
+
|
15
|
+
# Configuration parameters: CountComments.
|
16
|
+
Metrics/MethodLength:
|
17
|
+
Max: 22
|
18
|
+
|
19
|
+
Style/Documentation:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
# Cop supports --auto-correct.
|
23
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
|
24
|
+
Style/SpaceInsideBlockBraces:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
# Cop supports --auto-correct.
|
28
|
+
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SupportedStyles.
|
29
|
+
Style/SpaceInsideHashLiteralBraces:
|
30
|
+
Enabled: false
|
data/.travis.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.2
|
4
|
+
- 2.0
|
5
|
+
- 1.9.3
|
6
|
+
notifications:
|
7
|
+
hipchat:
|
8
|
+
rooms:
|
9
|
+
secure: gYBEwOGBTxHE2nrxsHQqp2UdjRtCX04wVLYEimeT9RG/0LClS4nzJF7DaXLWlAwgLPmk+KV2+nXuLO5oausBr9ODmWhho8G0F90RPR47NupcvT1RM+I2ZbxSjHCUICL22mdnZd8ye/mrk/YtFWYmgmH7ILRK3BuYovXFoKoRnLg=
|
10
|
+
template:
|
11
|
+
- '<a href="https://travis-ci.org/%{repository}/builds/%{build_id}">%{repository}
|
12
|
+
Build %{build_number}</a> on branch <i>%{branch}</i> by %{author}: <strong>%{message}</strong>
|
13
|
+
<a href="https://github.com/sendgrid/docs/commits/%{commit}">View on GitHub</a>'
|
14
|
+
format: html
|
15
|
+
notify: true
|
16
|
+
before_script:
|
17
|
+
- bundle install
|
18
|
+
script:
|
19
|
+
- rubocop --fail-level=W
|
20
|
+
- rake
|
data/Guardfile
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
notification :gntp
|
2
|
-
guard 'rspec' do
|
3
|
-
|
4
|
-
watch(%r{^lib/(.+)
|
5
|
-
|
6
|
-
|
2
|
+
guard :rspec, cmd: 'rspec' do
|
3
|
+
watch(%r{^spec/.+_spec\.rb$})
|
4
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
5
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
6
|
+
end
|
7
7
|
|
8
|
-
|
9
|
-
watch(%r{^
|
10
|
-
"spec/#{m[1]}.rb"
|
11
|
-
end
|
8
|
+
guard :rubocop, all_on_start: false do
|
9
|
+
watch(%r{^lib/(.+)\.rb$})
|
12
10
|
end
|
data/README.md
CHANGED
@@ -4,6 +4,8 @@ This Gem allows you to quickly and easily send emails through SendGrid's Web API
|
|
4
4
|
|
5
5
|
You can read our official documentation on the Web API's Mail feature [here](https://sendgrid.com/docs/API_Reference/Web_API/mail.html).
|
6
6
|
|
7
|
+
[](https://travis-ci.org/sendgrid/sendgrid-ruby)
|
8
|
+
|
7
9
|
|
8
10
|
## Installation
|
9
11
|
|
@@ -49,11 +51,18 @@ puts client.send(mail)
|
|
49
51
|
# {"message":"success"}
|
50
52
|
```
|
51
53
|
|
52
|
-
You can also create a mail object with a hash
|
54
|
+
You can also create a mail object with a hash:
|
53
55
|
```ruby
|
54
56
|
client.send(SendGrid::Mail.new(to: 'example@example.com', from: 'taco@cat.limo', subject: 'Hello world!', text: 'Hi there!', html: '<b>Hi there!</b>'))
|
55
57
|
|
56
|
-
|
58
|
+
# {"message":"success"}
|
59
|
+
```
|
60
|
+
|
61
|
+
#### Attachments
|
62
|
+
|
63
|
+
Attachments can be added to a mail object with the `add_attachment` method. The first parameter is the path to the file, the second (optional) parameter is the desired name of the file. If a file name is not provided, it will use the original filename.
|
64
|
+
```ruby
|
65
|
+
mail.add_attachment('/tmp/report.pdf', 'july_report.pdf')
|
57
66
|
```
|
58
67
|
|
59
68
|
#### Available Params
|
data/Rakefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'rspec/core/rake_task'
|
2
1
|
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
3
5
|
|
4
|
-
|
5
|
-
task.rspec_opts = ['--color', '--format', 'nested']
|
6
|
-
end
|
6
|
+
task test: :spec
|
7
7
|
|
8
|
-
task default: :
|
8
|
+
task default: :test
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module SendGrid
|
4
|
+
class Client
|
5
|
+
attr_accessor :api_user, :api_key, :protocol, :host, :port, :url, :endpoint,
|
6
|
+
:user_agent
|
7
|
+
attr_writer :adapter, :conn, :raise_exceptions
|
8
|
+
|
9
|
+
def initialize(params = {})
|
10
|
+
self.api_user = params.fetch(:api_user, nil)
|
11
|
+
self.api_key = params.fetch(:api_key, nil)
|
12
|
+
self.protocol = params.fetch(:protocol, 'https')
|
13
|
+
self.host = params.fetch(:host, 'api.sendgrid.com')
|
14
|
+
self.port = params.fetch(:port, nil)
|
15
|
+
self.url = params.fetch(:url, protocol + '://' + host + (port ? ":#{port}" : ''))
|
16
|
+
self.endpoint = params.fetch(:endpoint, '/api/mail.send.json')
|
17
|
+
self.adapter = params.fetch(:adapter, adapter)
|
18
|
+
self.conn = params.fetch(:conn, conn)
|
19
|
+
self.user_agent = params.fetch(:user_agent, "sendgrid/#{SendGrid::VERSION};ruby")
|
20
|
+
self.raise_exceptions = params.fetch(:raise_exceptions, true)
|
21
|
+
yield self if block_given?
|
22
|
+
end
|
23
|
+
|
24
|
+
def send(mail)
|
25
|
+
res = conn.post do |req|
|
26
|
+
payload = mail.to_h
|
27
|
+
|
28
|
+
req.url(endpoint)
|
29
|
+
|
30
|
+
# Check if using username + password or API key
|
31
|
+
if api_user
|
32
|
+
# Username + password
|
33
|
+
payload = payload.merge(api_user: api_user, api_key: api_key)
|
34
|
+
else
|
35
|
+
# API key
|
36
|
+
req.headers['Authorization'] = "Bearer #{api_key}"
|
37
|
+
end
|
38
|
+
|
39
|
+
req.body = payload
|
40
|
+
end
|
41
|
+
|
42
|
+
fail SendGrid::Exception, res.body if raise_exceptions? && res.status != 200
|
43
|
+
|
44
|
+
SendGrid::Response.new(code: res.status, headers: res.headers, body: res.body)
|
45
|
+
end
|
46
|
+
|
47
|
+
def conn
|
48
|
+
@conn ||= Faraday.new(url: url) do |conn|
|
49
|
+
conn.request :multipart
|
50
|
+
conn.request :url_encoded
|
51
|
+
conn.adapter adapter
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def adapter
|
56
|
+
@adapter ||= Faraday.default_adapter
|
57
|
+
end
|
58
|
+
|
59
|
+
def raise_exceptions?
|
60
|
+
@raise_exceptions
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/sendgrid/mail.rb
CHANGED
@@ -3,58 +3,138 @@ require 'smtpapi'
|
|
3
3
|
|
4
4
|
module SendGrid
|
5
5
|
class Mail
|
6
|
-
attr_accessor :to, :to_name, :from, :from_name, :subject, :text, :html, :cc,
|
7
|
-
|
6
|
+
attr_accessor :to, :to_name, :from, :from_name, :subject, :text, :html, :cc,
|
7
|
+
:bcc, :reply_to, :date, :smtpapi, :attachments
|
8
8
|
|
9
9
|
def initialize(params = {})
|
10
10
|
params.each do |k, v|
|
11
|
-
|
11
|
+
send(:"#{k}=", v) unless v.nil?
|
12
12
|
end
|
13
|
-
@headers ||= {}
|
14
|
-
@attachments ||= []
|
15
|
-
@smtpapi ||= Smtpapi::Header.new
|
16
13
|
yield self if block_given?
|
17
14
|
end
|
18
15
|
|
19
|
-
def add_to(
|
20
|
-
|
16
|
+
def add_to(email, name = nil)
|
17
|
+
if email.is_a?(Array)
|
18
|
+
to.concat(email)
|
19
|
+
else
|
20
|
+
to << email
|
21
|
+
end
|
22
|
+
add_to_name(name) if name
|
23
|
+
end
|
24
|
+
|
25
|
+
def to
|
26
|
+
@to ||= []
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_name
|
30
|
+
@to_name ||= []
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_to_name(name)
|
34
|
+
if name.is_a?(Array)
|
35
|
+
to_name.concat(name)
|
36
|
+
else
|
37
|
+
to_name << name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def cc
|
42
|
+
@cc ||= []
|
43
|
+
end
|
44
|
+
|
45
|
+
def cc_name
|
46
|
+
@cc_name ||= []
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_cc(email, name = nil)
|
50
|
+
if email.is_a?(Array)
|
51
|
+
cc.concat(email)
|
52
|
+
else
|
53
|
+
cc << email
|
54
|
+
end
|
55
|
+
add_cc_name(name) if name
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_cc_name(name)
|
59
|
+
if name.is_a?(Array)
|
60
|
+
cc_name.concat(name)
|
61
|
+
else
|
62
|
+
cc_name << name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def bcc
|
67
|
+
@bcc ||= []
|
68
|
+
end
|
69
|
+
|
70
|
+
def bcc_name
|
71
|
+
@bcc_name ||= []
|
72
|
+
end
|
73
|
+
|
74
|
+
def add_bcc(email, name = nil)
|
75
|
+
if email.is_a?(Array)
|
76
|
+
bcc.concat(email)
|
77
|
+
else
|
78
|
+
bcc << email
|
79
|
+
end
|
80
|
+
add_bcc_name(name)
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_bcc_name(name)
|
84
|
+
if name.is_a?(Array)
|
85
|
+
bcc_name.concat(name)
|
86
|
+
else
|
87
|
+
bcc_name << name
|
88
|
+
end
|
21
89
|
end
|
22
90
|
|
23
91
|
def add_attachment(path, name = nil)
|
24
92
|
file = File.new(path)
|
25
93
|
name ||= File.basename(file)
|
26
|
-
|
94
|
+
attachments << {file: file, name: name}
|
95
|
+
end
|
96
|
+
|
97
|
+
def headers
|
98
|
+
@headers ||= {}
|
27
99
|
end
|
28
100
|
|
101
|
+
def attachments
|
102
|
+
@attachments ||= []
|
103
|
+
end
|
104
|
+
|
105
|
+
def smtpapi
|
106
|
+
@smtpapi ||= Smtpapi::Header.new
|
107
|
+
end
|
108
|
+
|
109
|
+
# rubocop:disable Style/HashSyntax
|
29
110
|
def to_h
|
30
111
|
payload = {
|
31
|
-
:from
|
32
|
-
:fromname
|
33
|
-
:subject
|
34
|
-
:to
|
35
|
-
:toname
|
36
|
-
:date
|
37
|
-
:replyto
|
38
|
-
:cc
|
39
|
-
:bcc
|
40
|
-
:text
|
41
|
-
:html
|
42
|
-
:'x-smtpapi' =>
|
43
|
-
:files
|
44
|
-
}.reject {|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
unless @attachments.empty?
|
52
|
-
@attachments.each do |file|
|
53
|
-
payload[:files][file[:name]] = file[:file]
|
54
|
-
end
|
55
|
-
end
|
112
|
+
:from => from,
|
113
|
+
:fromname => from_name,
|
114
|
+
:subject => subject,
|
115
|
+
:to => to,
|
116
|
+
:toname => to_name,
|
117
|
+
:date => date,
|
118
|
+
:replyto => reply_to,
|
119
|
+
:cc => cc,
|
120
|
+
:bcc => bcc,
|
121
|
+
:text => text,
|
122
|
+
:html => html,
|
123
|
+
:'x-smtpapi' => smtpapi.to_json,
|
124
|
+
:files => ({} unless attachments.empty?)
|
125
|
+
}.reject {|_, v| v.nil? || v.empty?}
|
126
|
+
|
127
|
+
payload.delete(:'x-smtpapi') if payload[:'x-smtpapi'] == '{}'
|
128
|
+
|
129
|
+
payload[:to] = payload[:from] unless payload[:to].nil? && smtpapi.to.empty?
|
56
130
|
|
131
|
+
return payload if attachments.empty?
|
132
|
+
|
133
|
+
attachments.each do |file|
|
134
|
+
payload[:files][file[:name]] = file[:file]
|
135
|
+
end
|
57
136
|
payload
|
58
137
|
end
|
138
|
+
# rubocop:enable Style/HashSyntax
|
59
139
|
end
|
60
140
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module SendGrid
|
4
|
+
class Response
|
5
|
+
attr_reader :code, :headers, :body, :raw_body
|
6
|
+
|
7
|
+
def initialize(params)
|
8
|
+
@code = params[:code]
|
9
|
+
@headers = params[:headers]
|
10
|
+
@body = JSON.parse(params[:body])
|
11
|
+
@raw_body = params[:body]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/sendgrid/version.rb
CHANGED
data/sendgrid-ruby.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ['Robin Johnson', 'Eddie Zaneski']
|
10
10
|
spec.email = 'community@sendgrid.com'
|
11
11
|
spec.summary = 'Official SendGrid Gem'
|
12
|
-
spec.description = 'Interact with SendGrids API in
|
12
|
+
spec.description = 'Interact with SendGrids API in native Ruby'
|
13
13
|
spec.homepage = 'http://github.com/sendgrid/sendgrid-ruby'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
@@ -18,12 +18,16 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(/^(test|spec|features)/)
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency 'smtpapi'
|
22
|
-
spec.add_dependency '
|
21
|
+
spec.add_dependency 'smtpapi', '~> 0.1'
|
22
|
+
spec.add_dependency 'faraday', '~> 0.9'
|
23
23
|
spec.add_development_dependency 'rake'
|
24
24
|
spec.add_development_dependency 'rspec'
|
25
25
|
spec.add_development_dependency 'rspec-nc'
|
26
|
+
spec.add_development_dependency 'webmock'
|
26
27
|
spec.add_development_dependency 'guard'
|
27
28
|
spec.add_development_dependency 'guard-rspec'
|
29
|
+
spec.add_development_dependency 'rubocop'
|
30
|
+
spec.add_development_dependency 'guard-rubocop'
|
31
|
+
spec.add_development_dependency 'ruby_gntp'
|
28
32
|
spec.add_development_dependency 'bundler', '~> 1.6'
|
29
33
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'webmock/rspec'
|
4
|
+
|
5
|
+
describe 'SendGrid::Client' do
|
6
|
+
it 'should accept a username and password' do
|
7
|
+
expect(SendGrid::Client.new(api_user: 'test', api_key: 'test')).to be_an_instance_of(SendGrid::Client)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should accept an api key' do
|
11
|
+
expect(SendGrid::Client.new(api_key: 'sendgrid_123')).to be_an_instance_of(SendGrid::Client)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should build the default url' do
|
15
|
+
expect(SendGrid::Client.new.url).to eq('https://api.sendgrid.com')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should build a custom url' do
|
19
|
+
expect(SendGrid::Client.new(port: 3000, host: 'foo.sendgrid.com', protocol: 'tacos').url).to eq('tacos://foo.sendgrid.com:3000')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should use the default endpoint' do
|
23
|
+
expect(SendGrid::Client.new.endpoint).to eq('/api/mail.send.json')
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ':send' do
|
27
|
+
it 'should make a request to sendgrid' do
|
28
|
+
stub_request(:any, 'https://api.sendgrid.com/api/mail.send.json')
|
29
|
+
.to_return(body: {message: 'success'}.to_json, status: 200, headers: {'X-TEST' => 'yes'})
|
30
|
+
|
31
|
+
client = SendGrid::Client.new(api_key: 'abc123')
|
32
|
+
mail = SendGrid::Mail.new
|
33
|
+
res = client.send(mail)
|
34
|
+
expect(res.code).to eq(200)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should have an auth header when using an api key' do
|
38
|
+
stub_request(:any, 'https://api.sendgrid.com/api/mail.send.json')
|
39
|
+
.to_return(body: {message: 'success'}.to_json, status: 200, headers: {'X-TEST' => 'yes'})
|
40
|
+
|
41
|
+
client = SendGrid::Client.new(api_key: 'abc123')
|
42
|
+
mail = SendGrid::Mail.new
|
43
|
+
|
44
|
+
client.send(mail)
|
45
|
+
|
46
|
+
expect(WebMock).to have_requested(:post, 'https://api.sendgrid.com/api/mail.send.json')
|
47
|
+
.with(headers: {'Authorization' => 'Bearer abc123'})
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should have a username + password when using them' do
|
51
|
+
stub_request(:any, 'https://api.sendgrid.com/api/mail.send.json')
|
52
|
+
.to_return(body: {message: 'success'}.to_json, status: 200, headers: {'X-TEST' => 'yes'})
|
53
|
+
|
54
|
+
client = SendGrid::Client.new(api_user: 'foobar', api_key: 'abc123')
|
55
|
+
mail = SendGrid::Mail.new
|
56
|
+
|
57
|
+
client.send(mail)
|
58
|
+
|
59
|
+
expect(WebMock).to have_requested(:post, 'https://api.sendgrid.com/api/mail.send.json')
|
60
|
+
.with(body: 'api_key=abc123&api_user=foobar')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should raise a SendGrid::Exception if status is not 200' do
|
64
|
+
stub_request(:any, 'https://api.sendgrid.com/api/mail.send.json')
|
65
|
+
.to_return(body: {message: 'error', errors: ['Bad username / password']}.to_json, status: 400, headers: {'X-TEST' => 'yes'})
|
66
|
+
|
67
|
+
client = SendGrid::Client.new(api_user: 'foobar', api_key: 'abc123')
|
68
|
+
mail = SendGrid::Mail.new
|
69
|
+
|
70
|
+
expect {client.send(mail)}.to raise_error(SendGrid::Exception)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should not raise a SendGrid::Exception if raise_exceptions is disabled' do
|
74
|
+
stub_request(:any, 'https://api.sendgrid.com/api/mail.send.json')
|
75
|
+
.to_return(body: {message: 'error', errors: ['Bad username / password']}.to_json, status: 400, headers: {'X-TEST' => 'yes'})
|
76
|
+
|
77
|
+
client = SendGrid::Client.new(api_user: 'foobar', api_key: 'abc123', raise_exceptions: false)
|
78
|
+
mail = SendGrid::Mail.new
|
79
|
+
|
80
|
+
expect {client.send(mail)}.not_to raise_error
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'SendGrid::Mail' do
|
4
|
+
before(:each) do
|
5
|
+
@mail = SendGrid::Mail.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should create an instance' do
|
9
|
+
expect(SendGrid::Mail.new).to be_an_instance_of(SendGrid::Mail)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'add_to_name' do
|
13
|
+
it 'should accept a name' do
|
14
|
+
@mail.add_to_name('Frank Foo')
|
15
|
+
expect(@mail.to_name).to eq(['Frank Foo'])
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should accept an array of names' do
|
19
|
+
@mail.add_to_name(['Frank Foo', 'Bob Bar'])
|
20
|
+
expect(@mail.to_name).to eq(['Frank Foo', 'Bob Bar'])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'add_to' do
|
25
|
+
it 'should accept an email' do
|
26
|
+
@mail.add_to('foo@example.com')
|
27
|
+
expect(@mail.to).to eq(['foo@example.com'])
|
28
|
+
|
29
|
+
@mail.add_to('bar@example.com')
|
30
|
+
expect(@mail.to).to eq(['foo@example.com', 'bar@example.com'])
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should accept an email and name' do
|
34
|
+
@mail.add_to('foo@example.com', 'Frank Foo')
|
35
|
+
expect(@mail.to).to eq(['foo@example.com'])
|
36
|
+
expect(@mail.to_name).to eq(['Frank Foo'])
|
37
|
+
|
38
|
+
@mail.add_to('bar@example.com', 'Bob Bar')
|
39
|
+
expect(@mail.to).to eq(['foo@example.com', 'bar@example.com'])
|
40
|
+
expect(@mail.to_name).to eq(['Frank Foo', 'Bob Bar'])
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should accept an array of emails' do
|
44
|
+
@mail.add_to(['foo@example.com', 'bar@example.com'])
|
45
|
+
expect(@mail.to).to eq(['foo@example.com', 'bar@example.com'])
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should accept an array of emails and names' do
|
49
|
+
@mail.add_to(['foo@example.com', 'bar@example.com'], ['Frank Foo', 'Bob Bar'])
|
50
|
+
expect(@mail.to).to eq(['foo@example.com', 'bar@example.com'])
|
51
|
+
expect(@mail.to_name).to eq(['Frank Foo', 'Bob Bar'])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'add_cc' do
|
56
|
+
it 'should accept an email' do
|
57
|
+
@mail.add_cc('foo@example.com')
|
58
|
+
expect(@mail.cc).to eq(['foo@example.com'])
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should accept an email and a name' do
|
62
|
+
@mail.add_cc('foo@example.com', 'Frank Foo')
|
63
|
+
expect(@mail.cc).to eq(['foo@example.com'])
|
64
|
+
expect(@mail.cc_name).to eq(['Frank Foo'])
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should accept an array of emails' do
|
68
|
+
@mail.add_cc(['foo@example.com', 'bar@example.com'])
|
69
|
+
expect(@mail.cc).to eq(['foo@example.com', 'bar@example.com'])
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should accept an array of emails and names' do
|
73
|
+
@mail.add_cc(['foo@example.com', 'bar@example.com'], ['Frank Foo', 'Bob Bar'])
|
74
|
+
expect(@mail.cc).to eq(['foo@example.com', 'bar@example.com'])
|
75
|
+
expect(@mail.cc_name).to eq(['Frank Foo', 'Bob Bar'])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'add_bcc' do
|
80
|
+
it 'should accept an email' do
|
81
|
+
@mail.add_bcc('foo@example.com')
|
82
|
+
expect(@mail.bcc).to eq(['foo@example.com'])
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should accept an email and a name' do
|
86
|
+
@mail.add_bcc('foo@example.com', 'Frank Foo')
|
87
|
+
expect(@mail.bcc).to eq(['foo@example.com'])
|
88
|
+
expect(@mail.bcc_name).to eq(['Frank Foo'])
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should accept an array of emails' do
|
92
|
+
@mail.add_bcc(['foo@example.com', 'bar@example.com'])
|
93
|
+
expect(@mail.bcc).to eq(['foo@example.com', 'bar@example.com'])
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should accept an array of emails and names' do
|
97
|
+
@mail.add_bcc(['foo@example.com', 'bar@example.com'], ['Frank Foo', 'Bob Bar'])
|
98
|
+
expect(@mail.bcc).to eq(['foo@example.com', 'bar@example.com'])
|
99
|
+
expect(@mail.bcc_name).to eq(['Frank Foo', 'Bob Bar'])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'to' do
|
104
|
+
it 'should be set' do
|
105
|
+
@mail.to = 'foo@example.com'
|
106
|
+
expect(@mail.to).to eq('foo@example.com')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'from_name' do
|
111
|
+
it 'should be set' do
|
112
|
+
@mail.from_name = 'Frank Foo'
|
113
|
+
expect(@mail.from_name).to eq('Frank Foo')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe 'reply_to' do
|
118
|
+
it 'should be set' do
|
119
|
+
@mail.reply_to = 'foo@example.com'
|
120
|
+
expect(@mail.reply_to).to eq('foo@example.com')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative '../lib/sendgrid_ruby'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sendgrid-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 1.0.0.alpha.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robin Johnson
|
@@ -9,16 +9,44 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-06-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: smtpapi
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0.1'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0.1'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: faraday
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0.9'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0.9'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake
|
16
44
|
requirement: !ruby/object:Gem::Requirement
|
17
45
|
requirements:
|
18
46
|
- - ">="
|
19
47
|
- !ruby/object:Gem::Version
|
20
48
|
version: '0'
|
21
|
-
type: :
|
49
|
+
type: :development
|
22
50
|
prerelease: false
|
23
51
|
version_requirements: !ruby/object:Gem::Requirement
|
24
52
|
requirements:
|
@@ -26,13 +54,13 @@ dependencies:
|
|
26
54
|
- !ruby/object:Gem::Version
|
27
55
|
version: '0'
|
28
56
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
57
|
+
name: rspec
|
30
58
|
requirement: !ruby/object:Gem::Requirement
|
31
59
|
requirements:
|
32
60
|
- - ">="
|
33
61
|
- !ruby/object:Gem::Version
|
34
62
|
version: '0'
|
35
|
-
type: :
|
63
|
+
type: :development
|
36
64
|
prerelease: false
|
37
65
|
version_requirements: !ruby/object:Gem::Requirement
|
38
66
|
requirements:
|
@@ -40,7 +68,7 @@ dependencies:
|
|
40
68
|
- !ruby/object:Gem::Version
|
41
69
|
version: '0'
|
42
70
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
71
|
+
name: rspec-nc
|
44
72
|
requirement: !ruby/object:Gem::Requirement
|
45
73
|
requirements:
|
46
74
|
- - ">="
|
@@ -54,7 +82,7 @@ dependencies:
|
|
54
82
|
- !ruby/object:Gem::Version
|
55
83
|
version: '0'
|
56
84
|
- !ruby/object:Gem::Dependency
|
57
|
-
name:
|
85
|
+
name: webmock
|
58
86
|
requirement: !ruby/object:Gem::Requirement
|
59
87
|
requirements:
|
60
88
|
- - ">="
|
@@ -68,7 +96,7 @@ dependencies:
|
|
68
96
|
- !ruby/object:Gem::Version
|
69
97
|
version: '0'
|
70
98
|
- !ruby/object:Gem::Dependency
|
71
|
-
name:
|
99
|
+
name: guard
|
72
100
|
requirement: !ruby/object:Gem::Requirement
|
73
101
|
requirements:
|
74
102
|
- - ">="
|
@@ -82,7 +110,7 @@ dependencies:
|
|
82
110
|
- !ruby/object:Gem::Version
|
83
111
|
version: '0'
|
84
112
|
- !ruby/object:Gem::Dependency
|
85
|
-
name: guard
|
113
|
+
name: guard-rspec
|
86
114
|
requirement: !ruby/object:Gem::Requirement
|
87
115
|
requirements:
|
88
116
|
- - ">="
|
@@ -96,7 +124,35 @@ dependencies:
|
|
96
124
|
- !ruby/object:Gem::Version
|
97
125
|
version: '0'
|
98
126
|
- !ruby/object:Gem::Dependency
|
99
|
-
name:
|
127
|
+
name: rubocop
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: guard-rubocop
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: ruby_gntp
|
100
156
|
requirement: !ruby/object:Gem::Requirement
|
101
157
|
requirements:
|
102
158
|
- - ">="
|
@@ -123,23 +179,32 @@ dependencies:
|
|
123
179
|
- - "~>"
|
124
180
|
- !ruby/object:Gem::Version
|
125
181
|
version: '1.6'
|
126
|
-
description: Interact with SendGrids API in
|
182
|
+
description: Interact with SendGrids API in native Ruby
|
127
183
|
email: community@sendgrid.com
|
128
184
|
executables: []
|
129
185
|
extensions: []
|
130
186
|
extra_rdoc_files: []
|
131
187
|
files:
|
132
188
|
- ".gitignore"
|
189
|
+
- ".rspec"
|
190
|
+
- ".rubocop.yml"
|
191
|
+
- ".travis.yml"
|
133
192
|
- Gemfile
|
134
193
|
- Guardfile
|
135
194
|
- LICENSE.txt
|
136
195
|
- README.md
|
137
196
|
- Rakefile
|
138
|
-
- lib/sendgrid
|
197
|
+
- lib/sendgrid/client.rb
|
139
198
|
- lib/sendgrid/exceptions.rb
|
140
199
|
- lib/sendgrid/mail.rb
|
200
|
+
- lib/sendgrid/response.rb
|
141
201
|
- lib/sendgrid/version.rb
|
202
|
+
- lib/sendgrid_ruby.rb
|
142
203
|
- sendgrid-ruby.gemspec
|
204
|
+
- spec/lib/sendgrid/client_spec.rb
|
205
|
+
- spec/lib/sendgrid/mail_spec.rb
|
206
|
+
- spec/lib/sendgrid_spec.rb
|
207
|
+
- spec/spec_helper.rb
|
143
208
|
homepage: http://github.com/sendgrid/sendgrid-ruby
|
144
209
|
licenses:
|
145
210
|
- MIT
|
@@ -155,13 +220,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
155
220
|
version: '0'
|
156
221
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
222
|
requirements:
|
158
|
-
- - "
|
223
|
+
- - ">"
|
159
224
|
- !ruby/object:Gem::Version
|
160
|
-
version:
|
225
|
+
version: 1.3.1
|
161
226
|
requirements: []
|
162
227
|
rubyforge_project:
|
163
|
-
rubygems_version: 2.4.
|
228
|
+
rubygems_version: 2.4.5
|
164
229
|
signing_key:
|
165
230
|
specification_version: 4
|
166
231
|
summary: Official SendGrid Gem
|
167
|
-
test_files:
|
232
|
+
test_files:
|
233
|
+
- spec/lib/sendgrid/client_spec.rb
|
234
|
+
- spec/lib/sendgrid/mail_spec.rb
|
235
|
+
- spec/lib/sendgrid_spec.rb
|
236
|
+
- spec/spec_helper.rb
|
data/lib/sendgrid-ruby.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require_relative 'sendgrid/exceptions'
|
2
|
-
require_relative 'sendgrid/mail'
|
3
|
-
require_relative 'sendgrid/version'
|
4
|
-
|
5
|
-
require 'rest-client'
|
6
|
-
|
7
|
-
module SendGrid
|
8
|
-
class Client
|
9
|
-
attr_accessor :api_user, :api_key, :host, :endpoint
|
10
|
-
|
11
|
-
def initialize(params = {})
|
12
|
-
@api_user = params.fetch(:api_user, nil)
|
13
|
-
@api_key = params.fetch(:api_key, nil)
|
14
|
-
@host = params.fetch(:host, 'https://api.sendgrid.com')
|
15
|
-
@endpoint = params.fetch(:endpoint, '/api/mail.send.json')
|
16
|
-
@conn = params.fetch(:conn, create_conn)
|
17
|
-
@user_agent = params.fetch(:user_agent, 'sendgrid/' + SendGrid::VERSION + ';ruby')
|
18
|
-
yield self if block_given?
|
19
|
-
raise SendGrid::Exception.new('api_user and api_key are required') unless @api_user && @api_key
|
20
|
-
end
|
21
|
-
|
22
|
-
def send(mail)
|
23
|
-
payload = mail.to_h.merge({api_user: @api_user, api_key: @api_key})
|
24
|
-
@conn[@endpoint].post(payload, {user_agent: @user_agent}) do |response, request, result|
|
25
|
-
case response.code.to_s
|
26
|
-
when /2\d\d/
|
27
|
-
response
|
28
|
-
when /4\d\d|5\d\d/
|
29
|
-
raise SendGrid::Exception.new(response)
|
30
|
-
else
|
31
|
-
# TODO: What will reach this?
|
32
|
-
"DEFAULT #{response.code} #{response}"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def create_conn
|
40
|
-
@conn = RestClient::Resource.new(@host)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|