axtro-aws-ses 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/CHANGELOG +42 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +28 -0
- data/LICENSE +20 -0
- data/README.erb +92 -0
- data/README.rdoc +196 -0
- data/Rakefile +82 -0
- data/TODO +3 -0
- data/VERSION +1 -0
- data/aws-ses.gemspec +102 -0
- data/axtro-aws-ses.gemspec +104 -0
- data/lib/aws/actionmailer/ses_extension.rb +19 -0
- data/lib/aws/ses.rb +29 -0
- data/lib/aws/ses/addresses.rb +75 -0
- data/lib/aws/ses/base.rb +176 -0
- data/lib/aws/ses/expirable_memoize.rb +45 -0
- data/lib/aws/ses/info.rb +103 -0
- data/lib/aws/ses/response.rb +113 -0
- data/lib/aws/ses/send_email.rb +156 -0
- data/lib/aws/ses/version.rb +12 -0
- data/test/address_test.rb +72 -0
- data/test/base_test.rb +40 -0
- data/test/expirable_memoize_test.rb +120 -0
- data/test/fixtures.rb +89 -0
- data/test/helper.rb +56 -0
- data/test/info_test.rb +108 -0
- data/test/mocks/fake_response.rb +26 -0
- data/test/response_test.rb +26 -0
- data/test/send_email_test.rb +94 -0
- metadata +215 -0
data/TODO
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
* Use a better XML parser (and be consistent)
|
2
|
+
* Rename Base to something else (probably Mailer): Nothing else actually inherits from Base, so that is a very poor naming convention. I intend to change it in the future
|
3
|
+
* Integer responses should probably be cast to ints instead of left as strings
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.4
|
data/aws-ses.gemspec
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{aws-ses}
|
8
|
+
s.version = "0.4.3"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Drew Blas", "Marcel Molina Jr."]
|
12
|
+
s.date = %q{2011-06-23}
|
13
|
+
s.description = %q{Client library for Amazon's Simple Email Service's REST API}
|
14
|
+
s.email = %q{drew.blas@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.erb",
|
18
|
+
"README.rdoc",
|
19
|
+
"TODO"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".document",
|
23
|
+
"CHANGELOG",
|
24
|
+
"Gemfile",
|
25
|
+
"Gemfile.lock",
|
26
|
+
"LICENSE",
|
27
|
+
"README.erb",
|
28
|
+
"README.rdoc",
|
29
|
+
"Rakefile",
|
30
|
+
"TODO",
|
31
|
+
"VERSION",
|
32
|
+
"aws-ses.gemspec",
|
33
|
+
"lib/aws/actionmailer/ses_extension.rb",
|
34
|
+
"lib/aws/ses.rb",
|
35
|
+
"lib/aws/ses/addresses.rb",
|
36
|
+
"lib/aws/ses/base.rb",
|
37
|
+
"lib/aws/ses/extensions.rb",
|
38
|
+
"lib/aws/ses/info.rb",
|
39
|
+
"lib/aws/ses/response.rb",
|
40
|
+
"lib/aws/ses/send_email.rb",
|
41
|
+
"lib/aws/ses/version.rb",
|
42
|
+
"test/address_test.rb",
|
43
|
+
"test/base_test.rb",
|
44
|
+
"test/extensions_test.rb",
|
45
|
+
"test/fixtures.rb",
|
46
|
+
"test/helper.rb",
|
47
|
+
"test/info_test.rb",
|
48
|
+
"test/mocks/fake_response.rb",
|
49
|
+
"test/response_test.rb",
|
50
|
+
"test/send_email_test.rb"
|
51
|
+
]
|
52
|
+
s.homepage = %q{http://github.com/drewblas/aws-ses}
|
53
|
+
s.licenses = ["MIT"]
|
54
|
+
s.require_paths = ["lib"]
|
55
|
+
s.rubygems_version = %q{1.5.2}
|
56
|
+
s.summary = %q{Client library for Amazon's Simple Email Service's REST API}
|
57
|
+
s.test_files = [
|
58
|
+
"test/address_test.rb",
|
59
|
+
"test/base_test.rb",
|
60
|
+
"test/extensions_test.rb",
|
61
|
+
"test/fixtures.rb",
|
62
|
+
"test/helper.rb",
|
63
|
+
"test/info_test.rb",
|
64
|
+
"test/mocks/fake_response.rb",
|
65
|
+
"test/response_test.rb",
|
66
|
+
"test/send_email_test.rb"
|
67
|
+
]
|
68
|
+
|
69
|
+
if s.respond_to? :specification_version then
|
70
|
+
s.specification_version = 3
|
71
|
+
|
72
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
73
|
+
s.add_runtime_dependency(%q<xml-simple>, [">= 0"])
|
74
|
+
s.add_runtime_dependency(%q<builder>, [">= 0"])
|
75
|
+
s.add_runtime_dependency(%q<mime-types>, [">= 0"])
|
76
|
+
s.add_development_dependency(%q<shoulda-context>, [">= 0"])
|
77
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
78
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
79
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
80
|
+
s.add_development_dependency(%q<flexmock>, ["~> 0.8.11"])
|
81
|
+
else
|
82
|
+
s.add_dependency(%q<xml-simple>, [">= 0"])
|
83
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
84
|
+
s.add_dependency(%q<mime-types>, [">= 0"])
|
85
|
+
s.add_dependency(%q<shoulda-context>, [">= 0"])
|
86
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
87
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
88
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
89
|
+
s.add_dependency(%q<flexmock>, ["~> 0.8.11"])
|
90
|
+
end
|
91
|
+
else
|
92
|
+
s.add_dependency(%q<xml-simple>, [">= 0"])
|
93
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
94
|
+
s.add_dependency(%q<mime-types>, [">= 0"])
|
95
|
+
s.add_dependency(%q<shoulda-context>, [">= 0"])
|
96
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
97
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
98
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
99
|
+
s.add_dependency(%q<flexmock>, ["~> 0.8.11"])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{axtro-aws-ses}
|
8
|
+
s.version = "0.4.4"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Drew Blas", "Marcel Molina Jr."]
|
12
|
+
s.date = %q{2011-10-31}
|
13
|
+
s.description = %q{Client library for Amazon's Simple Email Service's REST API}
|
14
|
+
s.email = %q{drew.blas@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.erb",
|
18
|
+
"README.rdoc",
|
19
|
+
"TODO"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".document",
|
23
|
+
"CHANGELOG",
|
24
|
+
"Gemfile",
|
25
|
+
"Gemfile.lock",
|
26
|
+
"LICENSE",
|
27
|
+
"README.erb",
|
28
|
+
"README.rdoc",
|
29
|
+
"Rakefile",
|
30
|
+
"TODO",
|
31
|
+
"VERSION",
|
32
|
+
"aws-ses.gemspec",
|
33
|
+
"axtro-aws-ses.gemspec",
|
34
|
+
"lib/aws/actionmailer/ses_extension.rb",
|
35
|
+
"lib/aws/ses.rb",
|
36
|
+
"lib/aws/ses/addresses.rb",
|
37
|
+
"lib/aws/ses/base.rb",
|
38
|
+
"lib/aws/ses/expirable_memoize.rb",
|
39
|
+
"lib/aws/ses/info.rb",
|
40
|
+
"lib/aws/ses/response.rb",
|
41
|
+
"lib/aws/ses/send_email.rb",
|
42
|
+
"lib/aws/ses/version.rb",
|
43
|
+
"test/address_test.rb",
|
44
|
+
"test/base_test.rb",
|
45
|
+
"test/expirable_memoize_test.rb",
|
46
|
+
"test/fixtures.rb",
|
47
|
+
"test/helper.rb",
|
48
|
+
"test/info_test.rb",
|
49
|
+
"test/mocks/fake_response.rb",
|
50
|
+
"test/response_test.rb",
|
51
|
+
"test/send_email_test.rb"
|
52
|
+
]
|
53
|
+
s.homepage = %q{http://github.com/axtro/aws-ses}
|
54
|
+
s.licenses = ["MIT"]
|
55
|
+
s.require_paths = ["lib"]
|
56
|
+
s.rubygems_version = %q{1.3.7}
|
57
|
+
s.summary = %q{Client library for Amazon's Simple Email Service's REST API}
|
58
|
+
s.test_files = [
|
59
|
+
"test/address_test.rb",
|
60
|
+
"test/base_test.rb",
|
61
|
+
"test/expirable_memoize_test.rb",
|
62
|
+
"test/fixtures.rb",
|
63
|
+
"test/helper.rb",
|
64
|
+
"test/info_test.rb",
|
65
|
+
"test/mocks/fake_response.rb",
|
66
|
+
"test/response_test.rb",
|
67
|
+
"test/send_email_test.rb"
|
68
|
+
]
|
69
|
+
|
70
|
+
if s.respond_to? :specification_version then
|
71
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
72
|
+
s.specification_version = 3
|
73
|
+
|
74
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
75
|
+
s.add_runtime_dependency(%q<xml-simple>, [">= 0"])
|
76
|
+
s.add_runtime_dependency(%q<builder>, [">= 0"])
|
77
|
+
s.add_runtime_dependency(%q<mime-types>, [">= 0"])
|
78
|
+
s.add_development_dependency(%q<shoulda-context>, [">= 0"])
|
79
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
80
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
81
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
82
|
+
s.add_development_dependency(%q<flexmock>, ["~> 0.8.11"])
|
83
|
+
else
|
84
|
+
s.add_dependency(%q<xml-simple>, [">= 0"])
|
85
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
86
|
+
s.add_dependency(%q<mime-types>, [">= 0"])
|
87
|
+
s.add_dependency(%q<shoulda-context>, [">= 0"])
|
88
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
89
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
90
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
91
|
+
s.add_dependency(%q<flexmock>, ["~> 0.8.11"])
|
92
|
+
end
|
93
|
+
else
|
94
|
+
s.add_dependency(%q<xml-simple>, [">= 0"])
|
95
|
+
s.add_dependency(%q<builder>, [">= 0"])
|
96
|
+
s.add_dependency(%q<mime-types>, [">= 0"])
|
97
|
+
s.add_dependency(%q<shoulda-context>, [">= 0"])
|
98
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
99
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
100
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
101
|
+
s.add_dependency(%q<flexmock>, ["~> 0.8.11"])
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# A quick little extension to use this lib with with rails 2.3.X
|
2
|
+
# To use it, in your environment.rb or some_environment.rb you simply set
|
3
|
+
#
|
4
|
+
# config.after_initialize do
|
5
|
+
# ActionMailer::Base.delivery_method = :amazon_ses
|
6
|
+
# ActionMailer::Base.custom_amazon_ses_mailer = AWS::SES::Base.new(:secret_access_key => S3_CONFIG[:secret_access_key], :access_key_id => S3_CONFIG[:access_key_id])
|
7
|
+
# end
|
8
|
+
|
9
|
+
module ActionMailer
|
10
|
+
class Base
|
11
|
+
cattr_accessor :custom_amazon_ses_mailer
|
12
|
+
|
13
|
+
def perform_delivery_amazon_ses(mail)
|
14
|
+
raise 'AWS::SES::Base has not been intitialized.' unless @@custom_amazon_ses_mailer
|
15
|
+
@@custom_amazon_ses_mailer.deliver!(mail)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/lib/aws/ses.rb
ADDED
@@ -0,0 +1,29 @@
|
|
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
|
+
|
17
|
+
require 'ses/expirable_memoize'
|
18
|
+
|
19
|
+
require 'ses/response'
|
20
|
+
require 'ses/send_email'
|
21
|
+
require 'ses/info'
|
22
|
+
require 'ses/base'
|
23
|
+
require 'ses/version'
|
24
|
+
require 'ses/addresses'
|
25
|
+
|
26
|
+
if defined?(Rails)
|
27
|
+
major, minor = Rails.version.split('.')
|
28
|
+
require 'actionmailer/ses_extension' if major == '2' && minor == '3'
|
29
|
+
end
|
@@ -0,0 +1,75 @@
|
|
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
|
+
#
|
8
|
+
# You can access these methods as follows:
|
9
|
+
#
|
10
|
+
# ses = AWS::SES::Base.new( ... connection info ... )
|
11
|
+
#
|
12
|
+
# # Get a list of verified addresses
|
13
|
+
# ses.addresses.list.result
|
14
|
+
#
|
15
|
+
# # Add a new e-mail address to verify
|
16
|
+
# ses.addresses.verify('jon@example.com')
|
17
|
+
#
|
18
|
+
# # Delete an e-mail address
|
19
|
+
# ses.addresses.delete('jon@example.com')
|
20
|
+
class Addresses < Base
|
21
|
+
def initialize(ses)
|
22
|
+
@ses = ses
|
23
|
+
end
|
24
|
+
|
25
|
+
# List all verified e-mail addresses
|
26
|
+
#
|
27
|
+
# Usage:
|
28
|
+
# ses.addresses.list.result
|
29
|
+
# =>
|
30
|
+
# ['email1@example.com', email2@example.com']
|
31
|
+
def list
|
32
|
+
@ses.request('ListVerifiedEmailAddresses')
|
33
|
+
end
|
34
|
+
|
35
|
+
def verify(email)
|
36
|
+
@ses.request('VerifyEmailAddress',
|
37
|
+
'EmailAddress' => email
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete(email)
|
42
|
+
@ses.request('DeleteVerifiedEmailAddress',
|
43
|
+
'EmailAddress' => email
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class ListVerifiedEmailAddressesResponse < AWS::SES::Response
|
49
|
+
def result
|
50
|
+
if members = parsed['ListVerifiedEmailAddressesResult']['VerifiedEmailAddresses']
|
51
|
+
[members['member']].flatten
|
52
|
+
else
|
53
|
+
[]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
memoized :result
|
57
|
+
end
|
58
|
+
|
59
|
+
class VerifyEmailAddressResponse < AWS::SES::Response
|
60
|
+
end
|
61
|
+
|
62
|
+
class DeleteVerifiedEmailAddressResponse < AWS::SES::Response
|
63
|
+
def result
|
64
|
+
success?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Base
|
69
|
+
def addresses
|
70
|
+
@addresses ||= Addresses.new(self)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
data/lib/aws/ses/base.rb
ADDED
@@ -0,0 +1,176 @@
|
|
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
|
+
USER_AGENT = 'github-aws-ses-ruby-gem'
|
27
|
+
|
28
|
+
# Encodes the given string with the secret_access_key by taking the
|
29
|
+
# hmac-sha1 sum, and then base64 encoding it. Optionally, it will also
|
30
|
+
# url encode the result of that to protect the string if it's going to
|
31
|
+
# be used as a query string parameter.
|
32
|
+
#
|
33
|
+
# @param [String] secret_access_key the user's secret access key for signing.
|
34
|
+
# @param [String] str the string to be hashed and encoded.
|
35
|
+
# @param [Boolean] urlencode whether or not to url encode the result., true or false
|
36
|
+
# @return [String] the signed and encoded string.
|
37
|
+
def SES.encode(secret_access_key, str, urlencode=true)
|
38
|
+
digest = OpenSSL::Digest::Digest.new('sha256')
|
39
|
+
b64_hmac =
|
40
|
+
Base64.encode64(
|
41
|
+
OpenSSL::HMAC.digest(digest, secret_access_key, str)).gsub("\n","")
|
42
|
+
|
43
|
+
if urlencode
|
44
|
+
return CGI::escape(b64_hmac)
|
45
|
+
else
|
46
|
+
return b64_hmac
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Generates the HTTP Header String that Amazon looks for
|
51
|
+
#
|
52
|
+
# @param [String] key the AWS Access Key ID
|
53
|
+
# @param [String] alg the algorithm used for the signature
|
54
|
+
# @param [String] sig the signature itself
|
55
|
+
def SES.authorization_header(key, alg, sig)
|
56
|
+
"AWS3-HTTPS AWSAccessKeyId=#{key}, Algorithm=#{alg}, Signature=#{sig}"
|
57
|
+
end
|
58
|
+
|
59
|
+
# AWS::SES::Base is the abstract super class of all classes who make requests against SES
|
60
|
+
class Base
|
61
|
+
include SendEmail
|
62
|
+
include Info
|
63
|
+
|
64
|
+
attr_reader :use_ssl, :server, :proxy_server, :port
|
65
|
+
|
66
|
+
# @option options [String] :access_key_id ("") The user's AWS Access Key ID
|
67
|
+
# @option options [String] :secret_access_key ("") The user's AWS Secret Access Key
|
68
|
+
# @option options [Boolean] :use_ssl (true) Connect using SSL?
|
69
|
+
# @option options [String] :server ("email.us-east-1.amazonaws.com") The server API endpoint host
|
70
|
+
# @option options [String] :proxy_server (nil) An HTTP proxy server FQDN
|
71
|
+
# @option options [String] :user_agent ("github-aws-ses-ruby-gem") The HTTP User-Agent header value
|
72
|
+
# @return [Object] the object.
|
73
|
+
def initialize( options = {} )
|
74
|
+
|
75
|
+
options = { :access_key_id => "",
|
76
|
+
:secret_access_key => "",
|
77
|
+
:use_ssl => true,
|
78
|
+
:server => DEFAULT_HOST,
|
79
|
+
:path => "/",
|
80
|
+
:user_agent => USER_AGENT,
|
81
|
+
:proxy_server => nil
|
82
|
+
}.merge(options)
|
83
|
+
|
84
|
+
@server = options[:server]
|
85
|
+
@proxy_server = options[:proxy_server]
|
86
|
+
@use_ssl = options[:use_ssl]
|
87
|
+
@path = options[:path]
|
88
|
+
@user_agent = options[:user_agent]
|
89
|
+
|
90
|
+
raise ArgumentError, "No :access_key_id provided" if options[:access_key_id].nil? || options[:access_key_id].empty?
|
91
|
+
raise ArgumentError, "No :secret_access_key provided" if options[:secret_access_key].nil? || options[:secret_access_key].empty?
|
92
|
+
raise ArgumentError, "No :use_ssl value provided" if options[:use_ssl].nil?
|
93
|
+
raise ArgumentError, "Invalid :use_ssl value provided, only 'true' or 'false' allowed" unless options[:use_ssl] == true || options[:use_ssl] == false
|
94
|
+
raise ArgumentError, "No :server provided" if options[:server].nil? || options[:server].empty?
|
95
|
+
|
96
|
+
if options[:port]
|
97
|
+
# user-specified port
|
98
|
+
@port = options[:port]
|
99
|
+
elsif @use_ssl
|
100
|
+
# https
|
101
|
+
@port = 443
|
102
|
+
else
|
103
|
+
# http
|
104
|
+
@port = 80
|
105
|
+
end
|
106
|
+
|
107
|
+
@access_key_id = options[:access_key_id]
|
108
|
+
@secret_access_key = options[:secret_access_key]
|
109
|
+
|
110
|
+
# Use proxy server if defined
|
111
|
+
# Based on patch by Mathias Dalheimer. 20070217
|
112
|
+
proxy = @proxy_server ? URI.parse(@proxy_server) : OpenStruct.new
|
113
|
+
@http = Net::HTTP::Proxy( proxy.host,
|
114
|
+
proxy.port,
|
115
|
+
proxy.user,
|
116
|
+
proxy.password).new(options[:server], @port)
|
117
|
+
|
118
|
+
@http.use_ssl = @use_ssl
|
119
|
+
|
120
|
+
# Don't verify the SSL certificates. Avoids SSL Cert warning in log on every GET.
|
121
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
attr_accessor :settings
|
126
|
+
|
127
|
+
def connection
|
128
|
+
@http
|
129
|
+
end
|
130
|
+
|
131
|
+
# Make the connection to AWS passing in our request.
|
132
|
+
# allow us to have a one line call in each method which will do all of the work
|
133
|
+
# in making the actual request to AWS.
|
134
|
+
def request(action, params = {})
|
135
|
+
# Use a copy so that we don't modify the caller's Hash, remove any keys that have nil or empty values
|
136
|
+
params = params.reject { |key, value| value.nil? or value.empty?}
|
137
|
+
|
138
|
+
timestamp = Time.now.getutc
|
139
|
+
|
140
|
+
params.merge!( {"Action" => action,
|
141
|
+
"SignatureVersion" => "2",
|
142
|
+
"SignatureMethod" => 'HmacSHA256',
|
143
|
+
"AWSAccessKeyId" => @access_key_id,
|
144
|
+
"Version" => API_VERSION,
|
145
|
+
"Timestamp" => timestamp.iso8601 } )
|
146
|
+
|
147
|
+
query = params.sort.collect do |param|
|
148
|
+
CGI::escape(param[0]) + "=" + CGI::escape(param[1])
|
149
|
+
end.join("&")
|
150
|
+
|
151
|
+
req = {}
|
152
|
+
|
153
|
+
req['X-Amzn-Authorization'] = get_aws_auth_param(timestamp.httpdate, @secret_access_key)
|
154
|
+
req['Date'] = timestamp.httpdate
|
155
|
+
req['User-Agent'] = @user_agent
|
156
|
+
|
157
|
+
response = connection.post(@path, query, req)
|
158
|
+
|
159
|
+
response_class = AWS::SES.const_get( "#{action}Response" )
|
160
|
+
result = response_class.new(action, response)
|
161
|
+
|
162
|
+
if result.error?
|
163
|
+
raise ResponseError.new(result)
|
164
|
+
end
|
165
|
+
|
166
|
+
result
|
167
|
+
end
|
168
|
+
|
169
|
+
# Set the Authorization header using AWS signed header authentication
|
170
|
+
def get_aws_auth_param(timestamp, secret_access_key)
|
171
|
+
encoded_canonical = SES.encode(secret_access_key, timestamp, false)
|
172
|
+
SES.authorization_header(@access_key_id, 'HmacSHA256', encoded_canonical)
|
173
|
+
end
|
174
|
+
end # class Base
|
175
|
+
end # Module SES
|
176
|
+
end # Module AWS
|