aws-ses-rails31 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -0,0 +1,39 @@
1
+ #:stopdoc:
2
+ module Kernel
3
+ def __method__(depth = 0)
4
+ caller[depth][/`([^']+)'/, 1]
5
+ end if RUBY_VERSION <= '1.8.7'
6
+
7
+ def __called_from__
8
+ caller[1][/`([^']+)'/, 1]
9
+ end if RUBY_VERSION > '1.8.7'
10
+
11
+ def expirable_memoize(reload = false, storage = nil)
12
+ current_method = RUBY_VERSION > '1.8.7' ? __called_from__ : __method__(1)
13
+ storage = "@#{storage || current_method}"
14
+ if reload
15
+ instance_variable_set(storage, nil)
16
+ else
17
+ if cache = instance_variable_get(storage)
18
+ return cache
19
+ end
20
+ end
21
+ instance_variable_set(storage, yield)
22
+ end
23
+ end
24
+
25
+ class Module
26
+ def memoized(method_name)
27
+ original_method = "unmemoized_#{method_name}_#{Time.now.to_i}"
28
+ alias_method original_method, method_name
29
+ module_eval(<<-EVAL, __FILE__, __LINE__)
30
+ def #{method_name}(reload = false, *args, &block)
31
+ expirable_memoize(reload) do
32
+ send(:#{original_method}, *args, &block)
33
+ end
34
+ end
35
+ EVAL
36
+ end
37
+ end
38
+
39
+ #:startdoc:
@@ -0,0 +1,100 @@
1
+ module AWS
2
+ module SES
3
+ # Adds functionality for the statistics and info send quota data that Amazon SES makes available
4
+ #
5
+ # You can access these methods as follows:
6
+ #
7
+ # ses = AWS::SES::Base.new( ... connection info ... )
8
+ #
9
+ # == Get the quota information
10
+ # response = ses.quota
11
+ # # How many e-mails you've sent in the last 24 hours
12
+ # response.sent_last_24_hours
13
+ # # How many e-mails you're allowed to send in 24 hours
14
+ # response.max_24_hour_send
15
+ # # How many e-mails you can send per second
16
+ # response.max_send_rate
17
+ #
18
+ # == Get detailed send statistics
19
+ # The result is a list of data points, representing the last two weeks of sending activity.
20
+ # Each data point in the list contains statistics for a 15-minute interval.
21
+ # GetSendStatisticsResponse#data_points is an array where each element is a hash with give string keys:
22
+ #
23
+ # * +Bounces+
24
+ # * +DeliveryAttempts+
25
+ # * +Rejects+
26
+ # * +Complaints+
27
+ # * +Timestamp+
28
+ #
29
+ # response = ses.statistics
30
+ # response.data_points # =>
31
+ # [{"Bounces"=>"0",
32
+ # "Timestamp"=>"2011-01-26T16:30:00Z",
33
+ # "DeliveryAttempts"=>"1",
34
+ # "Rejects"=>"0",
35
+ # "Complaints"=>"0"},
36
+ # {"Bounces"=>"0",
37
+ # "Timestamp"=>"2011-02-09T14:45:00Z",
38
+ # "DeliveryAttempts"=>"3",
39
+ # "Rejects"=>"0",
40
+ # "Complaints"=>"0"},
41
+ # {"Bounces"=>"0",
42
+ # "Timestamp"=>"2011-01-31T15:30:00Z",
43
+ # "DeliveryAttempts"=>"3",
44
+ # "Rejects"=>"0",
45
+ # "Complaints"=>"0"},
46
+ # {"Bounces"=>"0",
47
+ # "Timestamp"=>"2011-01-31T16:00:00Z",
48
+ # "DeliveryAttempts"=>"3",
49
+ # "Rejects"=>"0",
50
+ # "Complaints"=>"0"}]
51
+
52
+ module Info
53
+ # Returns quota information provided by SES
54
+ #
55
+ # The return format inside the response result will look like:
56
+ # {"SentLast24Hours"=>"0.0", "MaxSendRate"=>"1.0", "Max24HourSend"=>"200.0"}
57
+ def quota
58
+ request('GetSendQuota')
59
+ end
60
+
61
+ def statistics
62
+ request('GetSendStatistics')
63
+ end
64
+ end
65
+
66
+ class GetSendQuotaResponse < AWS::SES::Response
67
+ def result
68
+ parsed['GetSendQuotaResult']
69
+ end
70
+
71
+ def sent_last_24_hours
72
+ result['SentLast24Hours']
73
+ end
74
+
75
+ def max_24_hour_send
76
+ result['Max24HourSend']
77
+ end
78
+
79
+ def max_send_rate
80
+ result['MaxSendRate']
81
+ end
82
+ end
83
+
84
+ class GetSendStatisticsResponse < AWS::SES::Response
85
+ def result
86
+ if members = parsed['GetSendStatisticsResult']['SendDataPoints']
87
+ [members['member']].flatten
88
+ else
89
+ []
90
+ end
91
+ end
92
+
93
+ memoized :result
94
+
95
+ def data_points
96
+ result
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,110 @@
1
+ module AWS
2
+ module SES
3
+ class Response < String
4
+ attr_reader :response, :body, :parsed, :action
5
+
6
+ def initialize(action, response)
7
+ @action = action
8
+ @response = response
9
+ @body = response.body.to_s
10
+ super(body)
11
+ end
12
+
13
+ def headers
14
+ headers = {}
15
+ response.each do |header, value|
16
+ headers[header] = value
17
+ end
18
+ headers
19
+ end
20
+ memoized :headers
21
+
22
+ def [](header)
23
+ headers[header]
24
+ end
25
+
26
+ def each(&block)
27
+ headers.each(&block)
28
+ end
29
+
30
+ def code
31
+ response.code.to_i
32
+ end
33
+
34
+ {:success => 200..299, :redirect => 300..399,
35
+ :client_error => 400..499, :server_error => 500..599}.each do |result, code_range|
36
+ class_eval(<<-EVAL, __FILE__, __LINE__)
37
+ def #{result}?
38
+ return false unless response
39
+ (#{code_range}).include? code
40
+ end
41
+ EVAL
42
+ end
43
+
44
+ def error?
45
+ !success? && (response['content-type'] == 'application/xml' || response['content-type'] == 'text/xml')
46
+ end
47
+
48
+ def error
49
+ parsed['Error']
50
+ end
51
+ memoized :error
52
+
53
+ def parsed
54
+ parse_options = { 'forcearray' => ['item', 'member'], 'suppressempty' => nil, 'keeproot' => false }
55
+ # parse_options = { 'suppressempty' => nil, 'keeproot' => false }
56
+
57
+ XmlSimple.xml_in(body, parse_options)
58
+ end
59
+ memoized :parsed
60
+
61
+ # It's expected that each subclass of Response will override this method with what part of response is relevant
62
+ def result
63
+ parsed
64
+ end
65
+
66
+ def request_id
67
+ error? ? parsed['RequestId'] : parsed['ResponseMetadata']['RequestId']
68
+ end
69
+
70
+ def inspect
71
+ "#<%s:0x%s %s %s %s>" % [self.class, object_id, request_id, response.code, response.message]
72
+ end
73
+ end # class Response
74
+
75
+ # Requests whose response code is between 300 and 599 and contain an <Error></Error> in their body
76
+ # are wrapped in an Error::Response. This Error::Response contains an Error object which raises an exception
77
+ # that corresponds to the error in the response body. The exception object contains the ErrorResponse, so
78
+ # in all cases where a request happens, you can rescue ResponseError and have access to the ErrorResponse and
79
+ # its Error object which contains information about the ResponseError.
80
+ #
81
+ # begin
82
+ # Bucket.create(..)
83
+ # rescue ResponseError => exception
84
+ # exception.response
85
+ # # => <Error::Response>
86
+ # exception.response.error
87
+ # # => <Error>
88
+ # end
89
+ class ResponseError < StandardError
90
+ attr_reader :response
91
+ def initialize(response)
92
+ @response = response
93
+ super("AWS::SES Response Error: #{message}")
94
+ end
95
+
96
+ def code
97
+ @response.code
98
+ end
99
+
100
+ def message
101
+ @response.error['Code'] + @response.error['Message']
102
+ end
103
+
104
+ def inspect
105
+ "#<%s:0x%s %s %s '%s'>" % [self.class.name, object_id, @response.request_id, code, message]
106
+ end
107
+ end
108
+ end # module SES
109
+ end # module AWS
110
+
@@ -0,0 +1,144 @@
1
+ module AWS
2
+ module SES
3
+ # Adds functionality for send_email and send_raw_email
4
+ # Use the following to send an e-mail:
5
+ #
6
+ # ses = AWS::SES::Base.new( ... connection info ... )
7
+ # ses.send_email :to => ['jon@example.com', 'dave@example.com'],
8
+ # :source => '"Steve Smith" <steve@example.com>',
9
+ # :subject => 'Subject Line'
10
+ # :text_body => 'Internal text body'
11
+ #
12
+ # By default, the email "from" display address is whatever is before the @.
13
+ # To change the display from, use the format:
14
+ #
15
+ # "Steve Smith" <steve@example.com>
16
+ #
17
+ # You can also send Mail objects using send_raw_email:
18
+ #
19
+ # m = Mail.new( :to => ..., :from => ... )
20
+ # ses.send_raw_email(m)
21
+ #
22
+ # send_raw_email will also take a hash and pass it through Mail.new automatically as well.
23
+ #
24
+ module SendEmail
25
+
26
+ # Sends an email through SES
27
+ #
28
+ # the destination parameters can be:
29
+ #
30
+ # [A single e-mail string] "jon@example.com"
31
+ # [A array of e-mail addresses] ['jon@example.com', 'dave@example.com']
32
+ #
33
+ # ---
34
+ # = "Email address is not verified.MessageRejected (AWS::Error)"
35
+ # If you are receiving this message and you HAVE verified the [source] please <b>check to be sure you are not in sandbox mode!</b>
36
+ # If you have not been granted production access, you will have to <b>verify all recipients</b> as well.
37
+ # http://docs.amazonwebservices.com/ses/2010-12-01/DeveloperGuide/index.html?InitialSetup.Customer.html
38
+ # ---
39
+ #
40
+ # @option options [String] :source Source e-mail (from)
41
+ # @option options [String] :from alias for :source
42
+ # @option options [String] :to Destination e-mails
43
+ # @option options [String] :cc Destination e-mails
44
+ # @option options [String] :bcc Destination e-mails
45
+ # @option options [String] :subject
46
+ # @option options [String] :html_body
47
+ # @option options [String] :text_body
48
+ # @option options [String] :return_path The email address to which bounce notifications are to be forwarded. If the message cannot be delivered to the recipient, then an error message will be returned from the recipient's ISP; this message will then be forwarded to the email address specified by the ReturnPath parameter.
49
+ # @option options [String] :reply_to The reploy-to email address(es) for the message. If the recipient replies to the message, each reply-to address will receive the reply.
50
+ # @option options
51
+ # @return [Response] the response to sending this e-mail
52
+ def send_email(options = {})
53
+ package = {}
54
+
55
+ package['Source'] = options[:source] || options[:from]
56
+
57
+ add_array_to_hash!(package, 'Destination.ToAddresses', options[:to]) if options[:to]
58
+ add_array_to_hash!(package, 'Destination.CcAddresses', options[:cc]) if options[:cc]
59
+ add_array_to_hash!(package, 'Destination.BccAddresses', options[:bcc]) if options[:bcc]
60
+
61
+ package['Message.Subject.Data'] = options[:subject]
62
+
63
+ package['Message.Body.Html.Data'] = options[:html_body] if options[:html_body]
64
+ package['Message.Body.Text.Data'] = options[:text_body] || options[:body] if options[:text_body] || options[:body]
65
+
66
+ package['ReturnPath'] = options[:return_path] if options[:return_path]
67
+
68
+ add_array_to_hash!(package, 'ReplyToAddresses', options[:reply_to]) if options[:reply_to]
69
+
70
+ request('SendEmail', package)
71
+ end
72
+
73
+ # Sends using the SendRawEmail method
74
+ # This gives the most control and flexibility
75
+ #
76
+ # This uses the underlying Mail object from the mail gem
77
+ # You can pass in a Mail object, a Hash of params that will be parsed by Mail.new, or just a string
78
+ #
79
+ # Note that the params are different from send_email
80
+ # Specifically, the following fields from send_email will NOT work:
81
+ #
82
+ # * :source
83
+ # * :html_body
84
+ # * :text_body
85
+ #
86
+ # send_email accepts the aliases of :from & :body in order to be more compatible with the Mail gem
87
+ #
88
+ # This method is aliased as deliver and deliver! for compatibility (especially with Rails)
89
+ #
90
+ # @option mail [String] A raw string that is a properly formatted e-mail message
91
+ # @option mail [Hash] A hash that will be parsed by Mail.new
92
+ # @option mail [Mail] A mail object, ready to be encoded
93
+ # @option args [String] :source The sender's email address
94
+ # @option args [String] :destinations A list of destinations for the message.
95
+ # @option args [String] :from alias for :source
96
+ # @option args [String] :to alias for :destinations
97
+ # @return [Response]
98
+ def send_raw_email(mail, args = {})
99
+ message = mail.is_a?(Hash) ? Mail.new(mail).to_s : mail.to_s
100
+ package = { 'RawMessage.Data' => Base64::encode64(message) }
101
+ package['Source'] = args[:from] if args[:from]
102
+ package['Source'] = args[:source] if args[:source]
103
+ if args[:destinations]
104
+ add_array_to_hash!(package, 'Destinations', args[:destinations])
105
+ else
106
+ add_array_to_hash!(package, 'Destinations', args[:to]) if args[:to]
107
+ end
108
+ request('SendRawEmail', package)
109
+ end
110
+
111
+ alias :deliver! :send_raw_email
112
+ alias :deliver :send_raw_email
113
+
114
+ private
115
+
116
+ # Adds all elements of the ary with the appropriate member elements
117
+ def add_array_to_hash!(hash, key, ary)
118
+ cnt = 1
119
+ [*ary].each do |o|
120
+ hash["#{key}.member.#{cnt}"] = o
121
+ cnt += 1
122
+ end
123
+ end
124
+ end
125
+
126
+ class EmailResponse < AWS::SES::Response
127
+ def result
128
+ super["#{action}Result"]
129
+ end
130
+
131
+ def message_id
132
+ result['MessageId']
133
+ end
134
+ end
135
+
136
+ class SendEmailResponse < EmailResponse
137
+
138
+ end
139
+
140
+ class SendRawEmailResponse < EmailResponse
141
+
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,12 @@
1
+ module AWS
2
+ module SES
3
+ module VERSION #:nodoc:
4
+ MAJOR = '0'
5
+ MINOR = '4'
6
+ TINY = '2'
7
+ BETA = Time.now.to_i.to_s
8
+ end
9
+
10
+ Version = [VERSION::MAJOR, VERSION::MINOR, VERSION::TINY, VERSION::BETA].compact * '.'
11
+ end
12
+ end
data/lib/aws/ses.rb ADDED
@@ -0,0 +1,28 @@
1
+ %w[ base64 cgi openssl digest/sha1 net/https net/http rexml/document time ostruct mail].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/response'
19
+ require 'ses/send_email'
20
+ require 'ses/info'
21
+ require 'ses/base'
22
+ require 'ses/version'
23
+ require 'ses/addresses'
24
+
25
+ if defined?(Rails)
26
+ major, minor = Rails.version.split('.')
27
+ require 'actionmailer/ses_extension' if major == '2' && minor == '3'
28
+ end