ses 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.
- data/.gems +5 -0
- data/.gitignore +5 -0
- data/.rvmrc +1 -0
- data/.travis.yml +15 -0
- data/.yardopts +9 -0
- data/LICENSE +19 -0
- data/README.md +49 -0
- data/Rakefile +3 -0
- data/lib/.gitkeep +0 -0
- data/lib/ses.rb +4 -0
- data/lib/ses/.gitkeep +0 -0
- data/lib/ses/client.rb +122 -0
- data/lib/ses/email.rb +214 -0
- data/lib/ses/errors.rb +15 -0
- data/lib/ses/version.rb +3 -0
- data/pkg/.gitkeep +0 -0
- data/ses.gemspec +21 -0
- data/spec/.gitkeep +0 -0
- data/spec/helper.rb +8 -0
- data/spec/ses/client.rb +44 -0
- data/spec/ses/email.rb +128 -0
- data/task/build.rake +18 -0
- metadata +122 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create 1.9.3@ses
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2012, Yorick Peterse
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# SES
|
2
|
+
|
3
|
+
SES is a very simple and easy to use Gem for sending Emails using the Amazon SES
|
4
|
+
API. While there are already quite a few Gems out there for using this API most
|
5
|
+
of them had a dependency on the rather bloated "Mail" library.
|
6
|
+
|
7
|
+
This particular Gem aims to be as small as possible, comes with only HTTParty as
|
8
|
+
a dependency and doesn't do anything else besides sending Emails. This means
|
9
|
+
that if you're looking for a way to verify Emails or to get your send quota you
|
10
|
+
should probably look somewhere else.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
$ gem install ses
|
15
|
+
|
16
|
+
## Sending Emails
|
17
|
+
|
18
|
+
Load the gem:
|
19
|
+
|
20
|
+
require 'ses'
|
21
|
+
|
22
|
+
Configure your access and secret keys:
|
23
|
+
|
24
|
+
SES::Client::OPTIONS[:access_key] = 'example'
|
25
|
+
SES::Client::OPTIONS[:secret_key] = 'example'
|
26
|
+
|
27
|
+
Create a new instance of ``SES::Email``:
|
28
|
+
|
29
|
+
email = SES::Email.new(
|
30
|
+
:from => 'user@example.com',
|
31
|
+
:to => 'somebody@example.com',
|
32
|
+
:subject => 'Testing',
|
33
|
+
:body => 'This is an example Email'
|
34
|
+
)
|
35
|
+
|
36
|
+
And send it:
|
37
|
+
|
38
|
+
email.deliver
|
39
|
+
|
40
|
+
## Running Tests
|
41
|
+
|
42
|
+
The tests are written using Bacon and can be executed as following:
|
43
|
+
|
44
|
+
$ bacon spec/ses/*.rb
|
45
|
+
|
46
|
+
## License
|
47
|
+
|
48
|
+
The code in this repository is licensed under the MIT license. A copy of this
|
49
|
+
license can be found in the file "LICENSE".
|
data/Rakefile
ADDED
data/lib/.gitkeep
ADDED
File without changes
|
data/lib/ses.rb
ADDED
data/lib/ses/.gitkeep
ADDED
File without changes
|
data/lib/ses/client.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'openssl'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module SES
|
6
|
+
##
|
7
|
+
# Client for sending HTTP requests to the Amazon SES API using HTTParty.
|
8
|
+
#
|
9
|
+
# In order to be able to send Emails you'll have to specify an access key and
|
10
|
+
# a secret key. These keys can be set as following:
|
11
|
+
#
|
12
|
+
# SES::Client::OPTIONS[:access_key] = '...'
|
13
|
+
# SES::Client::OPTIONS[:secret_key] = '...'
|
14
|
+
#
|
15
|
+
# Once set you can start sending Emails using {SES::Email}.
|
16
|
+
#
|
17
|
+
# @since 24-01-2012
|
18
|
+
#
|
19
|
+
module Client
|
20
|
+
include HTTParty
|
21
|
+
|
22
|
+
format :xml
|
23
|
+
base_uri 'https://email.us-east-1.amazonaws.com'
|
24
|
+
|
25
|
+
# Hash containing the configuration options required for each HTTP
|
26
|
+
# request.
|
27
|
+
OPTIONS = {
|
28
|
+
# Your AWS access key.
|
29
|
+
:access_key => nil,
|
30
|
+
|
31
|
+
# Your AWS secret key.
|
32
|
+
:secret_key => nil,
|
33
|
+
|
34
|
+
# The version of the SES API.
|
35
|
+
:version => '2010-12-01'
|
36
|
+
}
|
37
|
+
|
38
|
+
class << self
|
39
|
+
##
|
40
|
+
# Executes a signed POST request.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# response = SES::Client.signed_post(
|
44
|
+
# :Action => 'SendEmail',
|
45
|
+
# :source => 'foo@bar.com',
|
46
|
+
# ...
|
47
|
+
# )
|
48
|
+
#
|
49
|
+
# puts response.parsed_response
|
50
|
+
#
|
51
|
+
# @since 24-01-2012
|
52
|
+
# @param [String] uri The URI relative to the base URL to send the request
|
53
|
+
# to.
|
54
|
+
# @param [Hash] body A hash containing the various keys and values that
|
55
|
+
# have to used as POST fields.
|
56
|
+
# @return [Mixed]
|
57
|
+
#
|
58
|
+
def signed_post(uri = '/', body = {})
|
59
|
+
verify_keys
|
60
|
+
|
61
|
+
time = Time.now
|
62
|
+
url_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z')
|
63
|
+
sig_time = time.gmtime.strftime('%a, %d %b %Y %H:%M:%S GMT')
|
64
|
+
|
65
|
+
body[:Timestamp] = url_time
|
66
|
+
body[:Version] = OPTIONS[:version]
|
67
|
+
body[:AWSAccessKeyId] = OPTIONS[:access_key]
|
68
|
+
|
69
|
+
data = {
|
70
|
+
:headers => {
|
71
|
+
'X-Amzn-Authorization' => signature(sig_time),
|
72
|
+
'Date' => sig_time
|
73
|
+
},
|
74
|
+
:body => body
|
75
|
+
}
|
76
|
+
|
77
|
+
return post(uri, data)
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Checks if the AWS access and secret key are set and raises an error if
|
82
|
+
# this isn't the case.
|
83
|
+
#
|
84
|
+
# @since 24-01-2012
|
85
|
+
# @raise [SES::Error] raised whenever one of the keys was
|
86
|
+
# missing.
|
87
|
+
#
|
88
|
+
def verify_keys
|
89
|
+
[:access_key, :secret_key].each do |k|
|
90
|
+
if OPTIONS[k].nil? or OPTIONS[k].empty?
|
91
|
+
raise(
|
92
|
+
SES::Error,
|
93
|
+
"You have to specify a non empty value for the #{k} option" \
|
94
|
+
" in SES::Client::OPTIONS"
|
95
|
+
)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Generates a signature to use for a single HTTP request.
|
102
|
+
#
|
103
|
+
# @since 24-01-2012
|
104
|
+
# @param [String] time The signature time as a string in the format
|
105
|
+
# ``%a, %d %b %Y %H:%M:%S GMT``.
|
106
|
+
# @return [String]
|
107
|
+
#
|
108
|
+
def signature(time)
|
109
|
+
hash = OpenSSL::HMAC.digest(
|
110
|
+
OpenSSL::Digest::Digest.new('sha256'),
|
111
|
+
OPTIONS[:secret_key],
|
112
|
+
time
|
113
|
+
)
|
114
|
+
|
115
|
+
hash = Base64.encode64(hash).chomp
|
116
|
+
|
117
|
+
return "AWS3-HTTPS AWSAccessKey=#{OPTIONS[:access_key]}, " \
|
118
|
+
"Signature=#{hash}, Algorithm=HmacSHA256"
|
119
|
+
end
|
120
|
+
end # class << self
|
121
|
+
end # Client
|
122
|
+
end # SES
|
data/lib/ses/email.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
module SES
|
2
|
+
##
|
3
|
+
# Class used for creating and sending Emails.
|
4
|
+
#
|
5
|
+
# In order to create a new Email you call {SES::Email.new} and provide a hash
|
6
|
+
# containing parameters such as the sender's Email, subject, etc:
|
7
|
+
#
|
8
|
+
# mail = SES::Email.new(
|
9
|
+
# :from => 'user@example.com',
|
10
|
+
# :to => 'anotheruser@example.com',
|
11
|
+
# :subject => 'Testing',
|
12
|
+
# :body => 'This is the Email body.'
|
13
|
+
# )
|
14
|
+
#
|
15
|
+
# Once the mail object has been created you can send it by calling
|
16
|
+
# {SES::Email#deliver}:
|
17
|
+
#
|
18
|
+
# mail.deliver
|
19
|
+
#
|
20
|
+
# Upon success the return value is set to the message ID of the newly created
|
21
|
+
# Email, upon any failure an instance of {SES::Error} is raised so be sure to
|
22
|
+
# properly wrap calls to {SES::Email#deliver} in a begin/rescue block:
|
23
|
+
#
|
24
|
+
# begin
|
25
|
+
# mail.deliver
|
26
|
+
# rescue SES::Error => e
|
27
|
+
# # Do something with the error.
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# ## Default Sender Details
|
31
|
+
#
|
32
|
+
# To make it easier to send Emails you can set the default sender Email and
|
33
|
+
# name in the hash {SES::Email::OPTIONS}. These options can be set as
|
34
|
+
# following:
|
35
|
+
#
|
36
|
+
# SES::Email::OPTIONS[:sender] = 'user@example.com'
|
37
|
+
# SES::Email::OPTIONS[:sender_name] = 'User'
|
38
|
+
#
|
39
|
+
# Once set these values will be used whenever there are no custom values
|
40
|
+
# specified for the sender Email/name.
|
41
|
+
#
|
42
|
+
# @since 24-01-2012
|
43
|
+
#
|
44
|
+
class Email
|
45
|
+
# Hash containing various configuration options.
|
46
|
+
OPTIONS = {
|
47
|
+
# The default sender Email to use.
|
48
|
+
:sender => '',
|
49
|
+
|
50
|
+
# The default name of the sender.
|
51
|
+
:sender_name => ''
|
52
|
+
}
|
53
|
+
|
54
|
+
# The Email address of the sender.
|
55
|
+
attr_accessor :from
|
56
|
+
|
57
|
+
# The full name of the sender.
|
58
|
+
attr_accessor :name
|
59
|
+
|
60
|
+
# A list of addresses to send the Email to. If a string is given the Email
|
61
|
+
# is only sent to that particular address, if an array is given the Email
|
62
|
+
# will be sent to all the specified addresses.
|
63
|
+
attr_accessor :to
|
64
|
+
|
65
|
+
# String containing the subject of the Email.
|
66
|
+
attr_accessor :subject
|
67
|
+
|
68
|
+
# String containing the body of the Email.
|
69
|
+
attr_accessor :body
|
70
|
+
|
71
|
+
# When set to true the Email will be sent as an HTML email. Set to
|
72
|
+
# ``false`` by default.
|
73
|
+
attr_accessor :html
|
74
|
+
|
75
|
+
# The character set to use for the subject and body. The character set is
|
76
|
+
# set to UTF-8 by default.
|
77
|
+
attr_accessor :charset
|
78
|
+
|
79
|
+
##
|
80
|
+
# Creates a new instance of the class and sets the specified attributes
|
81
|
+
# such as the sender's Email and subject.
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
# email = SES::Email.new(
|
85
|
+
# :from => 'user@example.com',
|
86
|
+
# :name => 'Example User',
|
87
|
+
# :to => 'another_user@example.com',
|
88
|
+
# :subject => 'Testing',
|
89
|
+
# :body => 'This is a test Email.'
|
90
|
+
# )
|
91
|
+
#
|
92
|
+
# @since 24-01-2012
|
93
|
+
# @param [Hash] options A hash containing the attributes to set. See the
|
94
|
+
# corresponding getters/setters for their descriptions.
|
95
|
+
# @option options [String] :from The Email of the sender.
|
96
|
+
# @option options [String] :name The name of the sender.
|
97
|
+
# @option options [String|Array] :to A string containing a single Email
|
98
|
+
# address to send the Email to or an array of multiple Email addresses.
|
99
|
+
# @option options [String] :subject The subject of the Email.
|
100
|
+
# @option options [String] :body The body of the Email.
|
101
|
+
# @option options [String] :html When set to ``true`` the Email will be
|
102
|
+
# sent as an HTML Email.
|
103
|
+
# @option options [String] :charset The character set to use for the Email,
|
104
|
+
# set to UTF-8 by default.
|
105
|
+
#
|
106
|
+
def initialize(options = {})
|
107
|
+
@from = options[:from] || OPTIONS[:sender]
|
108
|
+
@name = options[:name] || OPTIONS[:sender_name]
|
109
|
+
@to = options[:to]
|
110
|
+
@subject = options[:subject]
|
111
|
+
@body = options[:body]
|
112
|
+
@html = options[:html] || false
|
113
|
+
@charset = options[:charset] || 'UTF-8'
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Sends the Email and returns the message ID.
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
# email = SES::Email.new(...)
|
121
|
+
# id = email.deliver
|
122
|
+
#
|
123
|
+
# puts id # => "0000013511a87590-......."
|
124
|
+
#
|
125
|
+
# @since 24-01-2012
|
126
|
+
# @return [String]
|
127
|
+
# @raise [SES::Error] Raised whenever the Email could not be
|
128
|
+
# sent.
|
129
|
+
#
|
130
|
+
def deliver
|
131
|
+
validate
|
132
|
+
|
133
|
+
if @name.nil?
|
134
|
+
from = @from
|
135
|
+
else
|
136
|
+
from = "#{@name} <#{@from}>"
|
137
|
+
end
|
138
|
+
|
139
|
+
options = {
|
140
|
+
:Action => 'SendEmail',
|
141
|
+
:Source => from,
|
142
|
+
:'Message.Subject.Data' => @subject,
|
143
|
+
:'Message.Subject.Charset' => @charset
|
144
|
+
}
|
145
|
+
|
146
|
+
if @html == true
|
147
|
+
options[:'Message.Body.Html.Data'] = @body
|
148
|
+
options[:'Message.Body.Html.Charset'] = @charset
|
149
|
+
else
|
150
|
+
options[:'Message.Body.Text.Data'] = @body
|
151
|
+
options[:'Message.Body.Text.Charset'] = @charset
|
152
|
+
end
|
153
|
+
|
154
|
+
if @to.is_a?(Array)
|
155
|
+
num = 1
|
156
|
+
|
157
|
+
@to.each do |value, index|
|
158
|
+
if !value.nil? and !value.empty?
|
159
|
+
options[:"Destination.toAddresses.member.#{num}"] = value
|
160
|
+
|
161
|
+
num += 1
|
162
|
+
end
|
163
|
+
end
|
164
|
+
else
|
165
|
+
options[:'Destination.ToAddresses.member.1'] = @to
|
166
|
+
end
|
167
|
+
|
168
|
+
response = SES::Client.signed_post('/', options)
|
169
|
+
parsed = response.parsed_response
|
170
|
+
|
171
|
+
# Bummer, something went wrong.
|
172
|
+
if response.code != 200 and parsed.key?('ErrorResponse')
|
173
|
+
message = parsed['ErrorResponse']['Error']['Message']
|
174
|
+
|
175
|
+
raise(SES::Error, "Failed to send the Email: #{message}")
|
176
|
+
|
177
|
+
# Everything is fine, get the mail ID.
|
178
|
+
elsif response.code == 200 and parsed.key?('SendEmailResponse')
|
179
|
+
return parsed['SendEmailResponse']['SendEmailResult']['MessageId']
|
180
|
+
|
181
|
+
else
|
182
|
+
raise(
|
183
|
+
SES::Error,
|
184
|
+
"Failed to extract the message ID, raw response: #{response.body}"
|
185
|
+
)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
##
|
190
|
+
# Validates the attributes (such as the name and subject) and raises an
|
191
|
+
# error if they're invalid.
|
192
|
+
#
|
193
|
+
# @since 24-01-2012
|
194
|
+
# @raise [SES::ValidationError] raised whenever one of the set
|
195
|
+
# attributes is invalid.
|
196
|
+
#
|
197
|
+
def validate
|
198
|
+
if @from.nil? or @from.empty?
|
199
|
+
raise(
|
200
|
+
SES::ValidationError,
|
201
|
+
'You have to specify the from address'
|
202
|
+
)
|
203
|
+
end
|
204
|
+
|
205
|
+
if !@to.is_a?(Array) and !@to.is_a?(String)
|
206
|
+
raise(
|
207
|
+
SES::ValidationError,
|
208
|
+
"Expected an instance of Array or String for the to address but " \
|
209
|
+
"got #{@to.class} instead"
|
210
|
+
)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end # Email
|
214
|
+
end # SES
|
data/lib/ses/errors.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module SES
|
2
|
+
##
|
3
|
+
# Generic error class for the Amazon SES package.
|
4
|
+
#
|
5
|
+
# @since 24-01-2012
|
6
|
+
#
|
7
|
+
class Error < ::StandardError; end
|
8
|
+
|
9
|
+
##
|
10
|
+
# Error class used by {SES::Email#validate}.
|
11
|
+
#
|
12
|
+
# @since 24-01-2012
|
13
|
+
#
|
14
|
+
class ValidationError < ::StandardError; end
|
15
|
+
end # SES
|
data/lib/ses/version.rb
ADDED
data/pkg/.gitkeep
ADDED
File without changes
|
data/ses.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path('../lib/ses/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'ses'
|
5
|
+
s.version = SES::VERSION
|
6
|
+
s.date = '2012-03-09'
|
7
|
+
s.authors = ['Yorick Peterse']
|
8
|
+
s.email = 'yorickpeterse@gmail.com'
|
9
|
+
s.summary = 'A small and easy to use Gem for Amazon SES.'
|
10
|
+
s.homepage = 'https://github.com/yorickpeterse/ses'
|
11
|
+
s.description = s.summary
|
12
|
+
s.files = `git ls-files`.split("\n").sort
|
13
|
+
s.has_rdoc = 'yard'
|
14
|
+
|
15
|
+
s.add_dependency 'httparty', ['>= 0.8.1']
|
16
|
+
|
17
|
+
s.add_development_dependency 'rake' , ['>= 0.9.2']
|
18
|
+
s.add_development_dependency 'yard' , ['>= 0.7.2']
|
19
|
+
s.add_development_dependency 'bacon', ['>= 1.1.0']
|
20
|
+
s.add_development_dependency 'rdiscount', ['>= 1.6.8']
|
21
|
+
end
|
data/spec/.gitkeep
ADDED
File without changes
|
data/spec/helper.rb
ADDED
data/spec/ses/client.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path('../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'SES::Client' do
|
4
|
+
after do
|
5
|
+
SES::Client::OPTIONS[:access_key] = nil
|
6
|
+
SES::Client::OPTIONS[:secret_key] = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'Verify the access and secret keys' do
|
10
|
+
should.raise SES::Error do
|
11
|
+
SES::Client.verify_keys
|
12
|
+
end
|
13
|
+
|
14
|
+
SES::Client::OPTIONS[:access_key] = 'access'
|
15
|
+
|
16
|
+
should.raise SES::Error do
|
17
|
+
SES::Client.verify_keys
|
18
|
+
end
|
19
|
+
|
20
|
+
SES::Client::OPTIONS[:secret_key] = 'secret'
|
21
|
+
|
22
|
+
should.not.raise SES::Error do
|
23
|
+
SES::Client.verify_keys
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'Generate a signature for a given time' do
|
28
|
+
SES::Client::OPTIONS[:access_key] = 'access'
|
29
|
+
SES::Client::OPTIONS[:secret_key] = 'secret'
|
30
|
+
|
31
|
+
time = Time.new.strftime('%a, %d %b %Y %H:%M:%S GMT')
|
32
|
+
hash = OpenSSL::HMAC.digest(
|
33
|
+
OpenSSL::Digest::Digest.new('sha256'),
|
34
|
+
'secret',
|
35
|
+
time
|
36
|
+
)
|
37
|
+
|
38
|
+
hash = Base64.encode64(hash).chomp
|
39
|
+
got = SES::Client.signature(time)
|
40
|
+
|
41
|
+
got.should == "AWS3-HTTPS AWSAccessKey=access, Signature=#{hash}, " \
|
42
|
+
"Algorithm=HmacSHA256"
|
43
|
+
end
|
44
|
+
end
|
data/spec/ses/email.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
require File.expand_path('../../helper', __FILE__)
|
2
|
+
|
3
|
+
describe 'SES::Email' do
|
4
|
+
extend WebMock::API
|
5
|
+
|
6
|
+
after do
|
7
|
+
SES::Email::OPTIONS[:sender] = nil
|
8
|
+
SES::Email::OPTIONS[:sender_name] = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'Create a new instance of SES::Email and set the various parameters' do
|
12
|
+
email = SES::Email.new(
|
13
|
+
:from => 'user@example.com',
|
14
|
+
:name => 'User',
|
15
|
+
:to => 'user1@example.com',
|
16
|
+
:subject => 'Example',
|
17
|
+
:body => 'This is the body',
|
18
|
+
:html => true
|
19
|
+
)
|
20
|
+
|
21
|
+
email.from.should == 'user@example.com'
|
22
|
+
email.name.should == 'User'
|
23
|
+
email.to.should == 'user1@example.com'
|
24
|
+
email.subject.should == 'Example'
|
25
|
+
email.body.should == 'This is the body'
|
26
|
+
email.html.should == true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'Use the default sender and sender name if these are not manually given' do
|
30
|
+
SES::Email::OPTIONS[:sender] = 'user@example.com'
|
31
|
+
SES::Email::OPTIONS[:sender_name] = 'User'
|
32
|
+
|
33
|
+
email = SES::Email.new(
|
34
|
+
:to => 'user1@example.com',
|
35
|
+
:subject => 'Example',
|
36
|
+
:body => 'This is the body',
|
37
|
+
:html => true
|
38
|
+
)
|
39
|
+
|
40
|
+
email.from.should == 'user@example.com'
|
41
|
+
email.name.should == 'User'
|
42
|
+
email.to.should == 'user1@example.com'
|
43
|
+
email.subject.should == 'Example'
|
44
|
+
email.body.should == 'This is the body'
|
45
|
+
email.html.should == true
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'Raise when no sender Email is specified' do
|
49
|
+
should.raise SES::ValidationError do
|
50
|
+
SES::Email.new.deliver
|
51
|
+
end
|
52
|
+
|
53
|
+
should.raise SES::ValidationError do
|
54
|
+
SES::Email.new(:from => 'foo@bar.com').deliver
|
55
|
+
end
|
56
|
+
|
57
|
+
# :to can only be an array or a string.
|
58
|
+
should.raise SES::ValidationError do
|
59
|
+
SES::Email.new(:from => 'foo@bar.com', :to => 10).deliver
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'Send a valid Email' do
|
64
|
+
SES::Client::OPTIONS[:access_key] = 'access'
|
65
|
+
SES::Client::OPTIONS[:secret_key] = 'secret'
|
66
|
+
|
67
|
+
email = SES::Email.new(
|
68
|
+
:from => 'user@example.com',
|
69
|
+
:name => 'User',
|
70
|
+
:to => 'user1@example.com',
|
71
|
+
:subject => 'Example',
|
72
|
+
:body => 'This is the body',
|
73
|
+
:html => true
|
74
|
+
)
|
75
|
+
|
76
|
+
message_id = '00000131d51d2292-159ad6eb-077c-46e6-ad09-ae7c05925ed4-000000'
|
77
|
+
response_body = <<-XML.strip
|
78
|
+
<SendEmailResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
|
79
|
+
<SendEmailResult>
|
80
|
+
<MessageId>#{message_id}</MessageId>
|
81
|
+
</SendEmailResult>
|
82
|
+
<ResponseMetadata>
|
83
|
+
<RequestId>d5964849-c866-11e0-9beb-01a62d68c57f</RequestId>
|
84
|
+
</ResponseMetadata>
|
85
|
+
</SendEmailResponse>
|
86
|
+
XML
|
87
|
+
|
88
|
+
stub_request(:post, 'https://email.us-east-1.amazonaws.com') \
|
89
|
+
.to_return(:status => 200, :body => response_body)
|
90
|
+
|
91
|
+
email.deliver.should == message_id
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'Send an invalid Email' do
|
95
|
+
SES::Client::OPTIONS[:access_key] = 'access'
|
96
|
+
SES::Client::OPTIONS[:secret_key] = 'secret'
|
97
|
+
|
98
|
+
email = SES::Email.new(
|
99
|
+
:from => 'user@example.com',
|
100
|
+
:name => 'User',
|
101
|
+
:to => 'user1@example.com',
|
102
|
+
:subject => 'Example',
|
103
|
+
:body => 'This is the body',
|
104
|
+
:html => true
|
105
|
+
)
|
106
|
+
|
107
|
+
response_body = <<-XML.strip
|
108
|
+
<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
|
109
|
+
<Error>
|
110
|
+
<Message>Something went wrong</Message>
|
111
|
+
</Error>
|
112
|
+
</ErrorResponse>
|
113
|
+
XML
|
114
|
+
|
115
|
+
stub_request(:post, 'https://email.us-east-1.amazonaws.com') \
|
116
|
+
.to_return(:status => 400, :body => response_body)
|
117
|
+
|
118
|
+
should.raise SES::Error do
|
119
|
+
email.deliver
|
120
|
+
end
|
121
|
+
|
122
|
+
begin
|
123
|
+
email.deliver
|
124
|
+
rescue => e
|
125
|
+
e.message.should == 'Failed to send the Email: Something went wrong'
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/task/build.rake
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
namespace :build do
|
2
|
+
desc 'Builds a new Gem'
|
3
|
+
task :gem do
|
4
|
+
gemspec = Gem::Specification.load(
|
5
|
+
File.expand_path('../../ses.gemspec', __FILE__)
|
6
|
+
)
|
7
|
+
|
8
|
+
root = File.expand_path('../../', __FILE__)
|
9
|
+
name = "#{gemspec.name}-#{gemspec.version.version}.gem"
|
10
|
+
path = File.join(root, name)
|
11
|
+
pkg = File.join(root, 'pkg', name)
|
12
|
+
|
13
|
+
# Build and install the gem
|
14
|
+
sh('gem', 'build', File.join(root, 'ses.gemspec'))
|
15
|
+
sh('mv' , path, pkg)
|
16
|
+
sh('gem', 'install', pkg)
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ses
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Yorick Peterse
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: httparty
|
16
|
+
requirement: &2152150100 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.8.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2152150100
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &2152148320 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.9.2
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2152148320
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: yard
|
38
|
+
requirement: &2152145140 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.7.2
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2152145140
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: bacon
|
49
|
+
requirement: &2152156200 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.0
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2152156200
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rdiscount
|
60
|
+
requirement: &2152155140 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.6.8
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2152155140
|
69
|
+
description: A small and easy to use Gem for Amazon SES.
|
70
|
+
email: yorickpeterse@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- .gems
|
76
|
+
- .gitignore
|
77
|
+
- .rvmrc
|
78
|
+
- .travis.yml
|
79
|
+
- .yardopts
|
80
|
+
- LICENSE
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- lib/.gitkeep
|
84
|
+
- lib/ses.rb
|
85
|
+
- lib/ses/.gitkeep
|
86
|
+
- lib/ses/client.rb
|
87
|
+
- lib/ses/email.rb
|
88
|
+
- lib/ses/errors.rb
|
89
|
+
- lib/ses/version.rb
|
90
|
+
- pkg/.gitkeep
|
91
|
+
- ses.gemspec
|
92
|
+
- spec/.gitkeep
|
93
|
+
- spec/helper.rb
|
94
|
+
- spec/ses/client.rb
|
95
|
+
- spec/ses/email.rb
|
96
|
+
- task/build.rake
|
97
|
+
homepage: https://github.com/yorickpeterse/ses
|
98
|
+
licenses: []
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ! '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 1.8.16
|
118
|
+
signing_key:
|
119
|
+
specification_version: 3
|
120
|
+
summary: A small and easy to use Gem for Amazon SES.
|
121
|
+
test_files: []
|
122
|
+
has_rdoc: yard
|