aws-ses 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/CHANGELOG +6 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +28 -0
- data/LICENSE +20 -0
- data/README +47 -0
- data/README.erb +25 -0
- data/Rakefile +85 -0
- data/TODO +2 -0
- data/VERSION +1 -0
- data/lib/aws/ses.rb +22 -0
- data/lib/aws/ses/addresses.rb +61 -0
- data/lib/aws/ses/base.rb +213 -0
- data/lib/aws/ses/exceptions.rb +50 -0
- data/lib/aws/ses/extensions.rb +313 -0
- data/lib/aws/ses/response.rb +97 -0
- data/lib/aws/ses/version.rb +12 -0
- data/test/base_test.rb +9 -0
- data/test/extensions_test.rb +340 -0
- data/test/fixtures.rb +89 -0
- data/test/helper.rb +48 -0
- data/test/mocks/fake_response.rb +26 -0
- data/test/response_test.rb +33 -0
- metadata +257 -0
data/.document
ADDED
data/CHANGELOG
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "shoulda", ">= 0"
|
10
|
+
gem "bundler", "~> 1.0.0"
|
11
|
+
gem "jeweler", "~> 1.5.2"
|
12
|
+
gem "rcov", ">= 0"
|
13
|
+
gem 'flexmock', '~> 0.8.11'
|
14
|
+
end
|
15
|
+
|
16
|
+
gem 'xml-simple'
|
17
|
+
gem 'builder'
|
18
|
+
gem 'mime-types'
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
builder (3.0.0)
|
5
|
+
flexmock (0.8.11)
|
6
|
+
git (1.2.5)
|
7
|
+
jeweler (1.5.2)
|
8
|
+
bundler (~> 1.0.0)
|
9
|
+
git (>= 1.2.5)
|
10
|
+
rake
|
11
|
+
mime-types (1.16)
|
12
|
+
rake (0.8.7)
|
13
|
+
rcov (0.9.9)
|
14
|
+
shoulda (2.11.3)
|
15
|
+
xml-simple (1.0.13)
|
16
|
+
|
17
|
+
PLATFORMS
|
18
|
+
ruby
|
19
|
+
|
20
|
+
DEPENDENCIES
|
21
|
+
builder
|
22
|
+
bundler (~> 1.0.0)
|
23
|
+
flexmock (~> 0.8.11)
|
24
|
+
jeweler (~> 1.5.2)
|
25
|
+
mime-types
|
26
|
+
rcov
|
27
|
+
shoulda
|
28
|
+
xml-simple
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
Copyright (c) 2011 Drew V. Blas <drew.blas@gmail.com>
|
3
|
+
Copyright (c) 2006-2009 Marcel Molina Jr. <marcel@vernix.org>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in the
|
7
|
+
Software without restriction, including without limitation the rights to use,
|
8
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
9
|
+
Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
19
|
+
AN ACTION 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
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
= AWS::SES
|
2
|
+
|
3
|
+
AWS::SES is a Ruby library for Amazon's Simple Email Service's REST API (http://aws.amazon.com/ses).
|
4
|
+
|
5
|
+
== Getting started
|
6
|
+
|
7
|
+
To get started you need to require 'aws/ses':
|
8
|
+
|
9
|
+
% irb -rubygems
|
10
|
+
irb(main):001:0> require 'aws/ses'
|
11
|
+
# => true
|
12
|
+
|
13
|
+
Before you can do anything, you must establish a connection using Base.new. A basic connection would look something like this:
|
14
|
+
|
15
|
+
ses = AWS::SES::Base.new(
|
16
|
+
:access_key_id => 'abc',
|
17
|
+
:secret_access_key => '123'
|
18
|
+
)
|
19
|
+
|
20
|
+
The minimum connection options that you must specify are your access key id and your secret access key.
|
21
|
+
|
22
|
+
|
23
|
+
= Addresses
|
24
|
+
|
25
|
+
AWS::SES::Addresses provides for:
|
26
|
+
* Listing verified e-mail addresses
|
27
|
+
* Adding new e-mail addresses to verify
|
28
|
+
* Deleting verified e-mail addresses
|
29
|
+
|
30
|
+
|
31
|
+
== Contributing to aws-ses
|
32
|
+
|
33
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
34
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
35
|
+
* Fork the project
|
36
|
+
* Start a feature/bugfix branch
|
37
|
+
* Commit and push until you are happy with your contribution
|
38
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
39
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
40
|
+
|
41
|
+
== Copyright
|
42
|
+
|
43
|
+
Copyright (c) 2011 Drew Blas. See LICENSE for further details.
|
44
|
+
|
45
|
+
== Thanks
|
46
|
+
|
47
|
+
Special thanks to Marcel Molina Jr. for his creation of AWS::S3 which I used portions of to get things working.
|
data/README.erb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
= AWS::SES
|
2
|
+
|
3
|
+
<%= docs_for['AWS::SES'] %>
|
4
|
+
|
5
|
+
= Addresses
|
6
|
+
|
7
|
+
<%= docs_for['AWS::SES::Addresses'] %>
|
8
|
+
|
9
|
+
== Contributing to aws-ses
|
10
|
+
|
11
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
12
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
13
|
+
* Fork the project
|
14
|
+
* Start a feature/bugfix branch
|
15
|
+
* Commit and push until you are happy with your contribution
|
16
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
17
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
18
|
+
|
19
|
+
== Copyright
|
20
|
+
|
21
|
+
Copyright (c) 2011 Drew Blas. See LICENSE for further details.
|
22
|
+
|
23
|
+
== Thanks
|
24
|
+
|
25
|
+
Special thanks to Marcel Molina Jr. for his creation of AWS::S3 which I used portions of to get things working.
|
data/Rakefile
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'erb'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "aws-ses"
|
18
|
+
gem.homepage = "http://github.com/drewblas/aws-ses"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Client library for Amazon's Simple Email Service's REST API}
|
21
|
+
gem.description = gem.summary
|
22
|
+
gem.email = "drew.blas@gmail.com"
|
23
|
+
gem.authors = ["Drew Blas", 'Marcel Molina Jr.']
|
24
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
25
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
26
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
27
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
28
|
+
gem.add_dependency 'xml-simple'
|
29
|
+
gem.add_dependency 'builder'
|
30
|
+
gem.add_dependency 'mime-types'
|
31
|
+
end
|
32
|
+
Jeweler::RubygemsDotOrgTasks.new
|
33
|
+
|
34
|
+
require 'rake/testtask'
|
35
|
+
Rake::TestTask.new(:test) do |test|
|
36
|
+
test.libs << 'lib' << 'test'
|
37
|
+
test.pattern = 'test/**/*_test.rb'
|
38
|
+
test.verbose = true
|
39
|
+
end
|
40
|
+
|
41
|
+
require 'rcov/rcovtask'
|
42
|
+
Rcov::RcovTask.new do |test|
|
43
|
+
test.libs << 'test'
|
44
|
+
test.pattern = 'test/**/*_test.rb'
|
45
|
+
test.verbose = true
|
46
|
+
end
|
47
|
+
|
48
|
+
task :default => :test
|
49
|
+
|
50
|
+
require 'rake/rdoctask'
|
51
|
+
require File.dirname(__FILE__) + '/lib/aws/ses'
|
52
|
+
|
53
|
+
namespace :doc do
|
54
|
+
Rake::RDocTask.new do |rdoc|
|
55
|
+
rdoc.rdoc_dir = 'doc'
|
56
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
57
|
+
rdoc.title = "AWS::SES -- Support for Amazon SES's REST api #{version}"
|
58
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
59
|
+
rdoc.rdoc_files.include('README')
|
60
|
+
rdoc.rdoc_files.include('COPYING')
|
61
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
62
|
+
end
|
63
|
+
|
64
|
+
task :rdoc => 'doc:readme'
|
65
|
+
|
66
|
+
task :refresh => :rerdoc do
|
67
|
+
system 'open doc/index.html'
|
68
|
+
end
|
69
|
+
|
70
|
+
task :readme do
|
71
|
+
require 'support/rdoc/code_info'
|
72
|
+
RDoc::CodeInfo.parse('lib/**/*.rb')
|
73
|
+
|
74
|
+
strip_comments = lambda {|comment| comment.gsub(/^# ?/, '')}
|
75
|
+
docs_for = lambda do |location|
|
76
|
+
info = RDoc::CodeInfo.for(location)
|
77
|
+
raise RuntimeError, "Couldn't find documentation for `#{location}'" unless info
|
78
|
+
strip_comments[info.comment]
|
79
|
+
end
|
80
|
+
|
81
|
+
open('README', 'w') do |file|
|
82
|
+
file.write ERB.new(IO.read('README.erb')).result(binding)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/TODO
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/aws/ses.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
%w[ base64 cgi openssl digest/sha1 net/https net/http rexml/document time ostruct ].each { |f| require f }
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'URI' unless defined? URI
|
5
|
+
rescue Exception => e
|
6
|
+
# nothing
|
7
|
+
end
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'xmlsimple' unless defined? XmlSimple
|
11
|
+
rescue Exception => e
|
12
|
+
require 'xml-simple' unless defined? XmlSimple
|
13
|
+
end
|
14
|
+
|
15
|
+
$:.unshift(File.dirname(__FILE__))
|
16
|
+
require 'ses/extensions'
|
17
|
+
|
18
|
+
require 'ses/base'
|
19
|
+
require 'ses/response'
|
20
|
+
require 'ses/exceptions'
|
21
|
+
require 'ses/version'
|
22
|
+
require 'ses/addresses'
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module AWS
|
2
|
+
module SES
|
3
|
+
# AWS::SES::Addresses provides for:
|
4
|
+
# * Listing verified e-mail addresses
|
5
|
+
# * Adding new e-mail addresses to verify
|
6
|
+
# * Deleting verified e-mail addresses
|
7
|
+
class Addresses < Base
|
8
|
+
def initialize(ses)
|
9
|
+
@ses = ses
|
10
|
+
end
|
11
|
+
|
12
|
+
# List all verified e-mail addresses
|
13
|
+
#
|
14
|
+
# Usage:
|
15
|
+
# ses.addresses.list.result
|
16
|
+
# =>
|
17
|
+
# ['email1@example.com', email2@example.com']
|
18
|
+
def list
|
19
|
+
@ses.request('ListVerifiedEmailAddresses')
|
20
|
+
end
|
21
|
+
|
22
|
+
def verify(email)
|
23
|
+
@ses.request('VerifyEmailAddress',
|
24
|
+
'EmailAddress' => email
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def delete(email)
|
29
|
+
@ses.request('DeleteVerifiedEmailAddress',
|
30
|
+
'EmailAddress' => email
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class ListVerifiedEmailAddressesResponse < AWS::SES::Response
|
36
|
+
def result
|
37
|
+
if members = parsed['VerifiedEmailAddresses']
|
38
|
+
[members['member']].flatten
|
39
|
+
else
|
40
|
+
[]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class VerifyEmailAddressResponse < AWS::SES::Response
|
46
|
+
end
|
47
|
+
|
48
|
+
class DeleteVerifiedEmailAddressResponse < AWS::SES::Response
|
49
|
+
def result
|
50
|
+
success?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Base
|
55
|
+
def addresses
|
56
|
+
@addresses ||= Addresses.new(self)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
data/lib/aws/ses/base.rb
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
module AWS #:nodoc:
|
2
|
+
# AWS::SES is a Ruby library for Amazon's Simple Email Service's REST API (http://aws.amazon.com/ses).
|
3
|
+
#
|
4
|
+
# == Getting started
|
5
|
+
#
|
6
|
+
# To get started you need to require 'aws/ses':
|
7
|
+
#
|
8
|
+
# % irb -rubygems
|
9
|
+
# irb(main):001:0> require 'aws/ses'
|
10
|
+
# # => true
|
11
|
+
#
|
12
|
+
# Before you can do anything, you must establish a connection using Base.new. A basic connection would look something like this:
|
13
|
+
#
|
14
|
+
# ses = AWS::SES::Base.new(
|
15
|
+
# :access_key_id => 'abc',
|
16
|
+
# :secret_access_key => '123'
|
17
|
+
# )
|
18
|
+
#
|
19
|
+
# The minimum connection options that you must specify are your access key id and your secret access key.
|
20
|
+
module SES
|
21
|
+
|
22
|
+
API_VERSION = '2010-12-01'
|
23
|
+
|
24
|
+
DEFAULT_HOST = 'email.us-east-1.amazonaws.com'
|
25
|
+
|
26
|
+
# Encodes the given string with the secret_access_key by taking the
|
27
|
+
# hmac-sha1 sum, and then base64 encoding it. Optionally, it will also
|
28
|
+
# url encode the result of that to protect the string if it's going to
|
29
|
+
# be used as a query string parameter.
|
30
|
+
#
|
31
|
+
# @param [String] secret_access_key the user's secret access key for signing.
|
32
|
+
# @param [String] str the string to be hashed and encoded.
|
33
|
+
# @param [Boolean] urlencode whether or not to url encode the result., true or false
|
34
|
+
# @return [String] the signed and encoded string.
|
35
|
+
def SES.encode(secret_access_key, str, urlencode=true)
|
36
|
+
digest = OpenSSL::Digest::Digest.new('sha256')
|
37
|
+
b64_hmac =
|
38
|
+
Base64.encode64(
|
39
|
+
OpenSSL::HMAC.digest(digest, secret_access_key, str)).gsub("\n","")
|
40
|
+
|
41
|
+
if urlencode
|
42
|
+
return CGI::escape(b64_hmac)
|
43
|
+
else
|
44
|
+
return b64_hmac
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Generates the HTTP Header String that Amazon looks for
|
49
|
+
#
|
50
|
+
# @param [String] key the AWS Access Key ID
|
51
|
+
# @param [String] alg the algorithm used for the signature
|
52
|
+
# @param [String] sig the signature itself
|
53
|
+
def SES.authorization_header(key, alg, sig)
|
54
|
+
"AWS3-HTTPS AWSAccessKeyId=#{key}, Algorithm=#{alg}, Signature=#{sig}"
|
55
|
+
end
|
56
|
+
|
57
|
+
# AWS::SES::Base is the abstract super class of all classes who make requests against SES
|
58
|
+
class Base
|
59
|
+
|
60
|
+
attr_reader :use_ssl, :server, :proxy_server, :port
|
61
|
+
|
62
|
+
# @option options [String] :access_key_id ("") The user's AWS Access Key ID
|
63
|
+
# @option options [String] :secret_access_key ("") The user's AWS Secret Access Key
|
64
|
+
# @option options [Boolean] :use_ssl (true) Connect using SSL?
|
65
|
+
# @option options [String] :server ("email.us-east-1.amazonaws.com") The server API endpoint host
|
66
|
+
# @option options [String] :proxy_server (nil) An HTTP proxy server FQDN
|
67
|
+
# @return [Object] the object.
|
68
|
+
def initialize( options = {} )
|
69
|
+
|
70
|
+
options = { :access_key_id => "",
|
71
|
+
:secret_access_key => "",
|
72
|
+
:use_ssl => true,
|
73
|
+
:server => DEFAULT_HOST,
|
74
|
+
:path => "/",
|
75
|
+
:proxy_server => nil
|
76
|
+
}.merge(options)
|
77
|
+
|
78
|
+
@server = options[:server]
|
79
|
+
@proxy_server = options[:proxy_server]
|
80
|
+
@use_ssl = options[:use_ssl]
|
81
|
+
@path = options[:path]
|
82
|
+
|
83
|
+
raise ArgumentError, "No :access_key_id provided" if options[:access_key_id].nil? || options[:access_key_id].empty?
|
84
|
+
raise ArgumentError, "No :secret_access_key provided" if options[:secret_access_key].nil? || options[:secret_access_key].empty?
|
85
|
+
raise ArgumentError, "No :use_ssl value provided" if options[:use_ssl].nil?
|
86
|
+
raise ArgumentError, "Invalid :use_ssl value provided, only 'true' or 'false' allowed" unless options[:use_ssl] == true || options[:use_ssl] == false
|
87
|
+
raise ArgumentError, "No :server provided" if options[:server].nil? || options[:server].empty?
|
88
|
+
|
89
|
+
if options[:port]
|
90
|
+
# user-specified port
|
91
|
+
@port = options[:port]
|
92
|
+
elsif @use_ssl
|
93
|
+
# https
|
94
|
+
@port = 443
|
95
|
+
else
|
96
|
+
# http
|
97
|
+
@port = 80
|
98
|
+
end
|
99
|
+
|
100
|
+
@access_key_id = options[:access_key_id]
|
101
|
+
@secret_access_key = options[:secret_access_key]
|
102
|
+
|
103
|
+
# Use proxy server if defined
|
104
|
+
# Based on patch by Mathias Dalheimer. 20070217
|
105
|
+
proxy = @proxy_server ? URI.parse(@proxy_server) : OpenStruct.new
|
106
|
+
@http = Net::HTTP::Proxy( proxy.host,
|
107
|
+
proxy.port,
|
108
|
+
proxy.user,
|
109
|
+
proxy.password).new(options[:server], @port)
|
110
|
+
|
111
|
+
@http.use_ssl = @use_ssl
|
112
|
+
|
113
|
+
# Don't verify the SSL certificates. Avoids SSL Cert warning in log on every GET.
|
114
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
def connection
|
119
|
+
@http
|
120
|
+
end
|
121
|
+
|
122
|
+
# Make the connection to AWS EC2 passing in our request.
|
123
|
+
# allow us to have a one line call in each method which will do all of the work
|
124
|
+
# in making the actual request to AWS.
|
125
|
+
def request(action, params = {})
|
126
|
+
|
127
|
+
connection.start do
|
128
|
+
# remove any keys that have nil or empty values
|
129
|
+
params.reject! { |key, value| value.nil? or value.empty?}
|
130
|
+
|
131
|
+
timestamp = Time.now.getutc
|
132
|
+
|
133
|
+
params.merge!( {"Action" => action,
|
134
|
+
"SignatureVersion" => "2",
|
135
|
+
"SignatureMethod" => 'HmacSHA256',
|
136
|
+
"AWSAccessKeyId" => @access_key_id,
|
137
|
+
"Version" => API_VERSION,
|
138
|
+
"Timestamp" => timestamp.iso8601 } )
|
139
|
+
|
140
|
+
query = params.sort.collect do |param|
|
141
|
+
CGI::escape(param[0]) + "=" + CGI::escape(param[1])
|
142
|
+
end.join("&")
|
143
|
+
|
144
|
+
req = Net::HTTP::Post.new(@path)
|
145
|
+
req.content_type = 'application/x-www-form-urlencoded'
|
146
|
+
req['X-Amzn-Authorization'] = get_aws_auth_param(timestamp.httpdate, @secret_access_key)
|
147
|
+
req['Date'] = timestamp.httpdate
|
148
|
+
req['User-Agent'] = "github-aws-ses-ruby-gem"
|
149
|
+
|
150
|
+
response = connection.request(req, query)
|
151
|
+
|
152
|
+
# Make a call to see if we need to throw an error based on the response given by EC2
|
153
|
+
# All error classes are defined in EC2/exceptions.rb
|
154
|
+
aws_error?(response)
|
155
|
+
|
156
|
+
response_class = AWS::SES.const_get( "#{action}Response" )
|
157
|
+
return response_class.new(action, response)
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
# Set the Authorization header using AWS signed header authentication
|
163
|
+
def get_aws_auth_param(timestamp, secret_access_key)
|
164
|
+
encoded_canonical = SES.encode(secret_access_key, timestamp, false)
|
165
|
+
SES.authorization_header(@access_key_id, 'HmacSHA256', encoded_canonical)
|
166
|
+
end
|
167
|
+
|
168
|
+
# Raises the appropriate error if the specified Net::HTTPResponse object
|
169
|
+
# contains an AWS error; returns +false+ otherwise.
|
170
|
+
def aws_error?(response)
|
171
|
+
# return false if we got a HTTP 200 code,
|
172
|
+
# otherwise there is some type of error (40x,50x) and
|
173
|
+
# we should try to raise an appropriate exception
|
174
|
+
# from one of our exception classes defined in
|
175
|
+
# exceptions.rb
|
176
|
+
return false if response.is_a?(Net::HTTPSuccess)
|
177
|
+
|
178
|
+
raise AWS::Error, "Unexpected server error. response.body is: #{response.body}" if response.is_a?(Net::HTTPServerError)
|
179
|
+
|
180
|
+
# parse the XML document so we can walk through it
|
181
|
+
doc = REXML::Document.new(response.body)
|
182
|
+
|
183
|
+
# Check that the Error element is in the place we would expect.
|
184
|
+
# and if not raise a generic error exception
|
185
|
+
unless doc.root.elements['Error'].name == 'Error'
|
186
|
+
raise Error, "Unexpected error format. response.body is: #{response.body}"
|
187
|
+
end
|
188
|
+
|
189
|
+
# An valid error response looks like this:
|
190
|
+
# <?xml version="1.0"?><Response><Errors><Error><Code>InvalidParameterCombination</Code><Message>Unknown parameter: foo</Message></Error></Errors><RequestID>291cef62-3e86-414b-900e-17246eccfae8</RequestID></Response>
|
191
|
+
# AWS throws some exception codes that look like Error.SubError. Since we can't name classes this way
|
192
|
+
# we need to strip out the '.' in the error 'Code' and we name the error exceptions with this
|
193
|
+
# non '.' name as well.
|
194
|
+
error_code = doc.root.elements['Error'].elements['Code'].text.gsub('.', '')
|
195
|
+
error_message = doc.root.elements['Error'].elements['Message'].text
|
196
|
+
|
197
|
+
# Raise one of our specific error classes if it exists.
|
198
|
+
# otherwise, throw a generic EC2 Error with a few details.
|
199
|
+
if AWS.const_defined?(error_code)
|
200
|
+
raise AWS.const_get(error_code), error_message
|
201
|
+
else
|
202
|
+
raise AWS::Error, error_message
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
class << self
|
208
|
+
|
209
|
+
|
210
|
+
end # class methods
|
211
|
+
end # class Base
|
212
|
+
end # Module SES
|
213
|
+
end # Module AWS
|