class AWS::SES::Base
AWS::SES::Base
is the abstract super class of all classes who make requests against SES
Attributes
Public Class Methods
@option options [String] :access_key_id (“”) The user's AWS
Access Key ID @option options [String] :secret_access_key (“”) The user's AWS
Secret Access Key @option options [Boolean] :use_ssl (true) Connect using SSL? @option options [String] :server (“email.us-east-1.amazonaws.com”) The server API endpoint host @option options [String] :proxy_server (nil) An HTTP proxy server FQDN @option options [String] :user_agent (“github-aws-ses-ruby-gem”) The HTTP User-Agent header value @option options [String] :region (“us-east-1”) The server API endpoint host @option options [String] :message_id_domain (“us-east-1.amazonses.com”) Domain used to build message_id header @return [Object] the object.
# File lib/aws/ses/base.rb, line 103 def initialize( options = {} ) options = { :access_key_id => "", :secret_access_key => "", :use_ssl => true, :server => DEFAULT_HOST, :message_id_domain => DEFAULT_MESSAGE_ID_DOMAIN, :path => "/", :user_agent => USER_AGENT, :proxy_server => nil, :region => DEFAULT_REGION, :signature_version => DEFAULT_SIGNATURE_VERSION }.merge(options) @signature_version = options[:signature_version] @server = options[:server] @message_id_domain = options[:message_id_domain] @proxy_server = options[:proxy_server] @use_ssl = options[:use_ssl] @path = options[:path] @user_agent = options[:user_agent] @region = options[:region] @settings = {} raise ArgumentError, "No :access_key_id provided" if options[:access_key_id].nil? || options[:access_key_id].empty? raise ArgumentError, "No :secret_access_key provided" if options[:secret_access_key].nil? || options[:secret_access_key].empty? raise ArgumentError, "No :use_ssl value provided" if options[:use_ssl].nil? raise ArgumentError, "Invalid :use_ssl value provided, only 'true' or 'false' allowed" unless options[:use_ssl] == true || options[:use_ssl] == false raise ArgumentError, "No :server provided" if options[:server].nil? || options[:server].empty? raise ArgumentError, ":signature_version must be 2 or 4" unless [2, 4].include?(options[:signature_version]) if options[:port] # user-specified port @port = options[:port] elsif @use_ssl # https @port = 443 else # http @port = 80 end @access_key_id = options[:access_key_id] @secret_access_key = options[:secret_access_key] # Use proxy server if defined # Based on patch by Mathias Dalheimer. 20070217 proxy = @proxy_server ? URI.parse(@proxy_server) : OpenStruct.new @http = Net::HTTP::Proxy( proxy.host, proxy.port, proxy.user, proxy.password).new(options[:server], @port) @http.use_ssl = @use_ssl end
Public Instance Methods
# File lib/aws/ses/addresses.rb, line 69 def addresses @addresses ||= Addresses.new(self) end
# File lib/aws/ses/base.rb, line 159 def connection @http end
Set the Authorization header using AWS
signed header authentication
# File lib/aws/ses/base.rb, line 211 def get_aws_auth_header_v2 encoded_canonical = SES.encode(@secret_access_key, httpdate, false) SES.authorization_header(@access_key_id, 'HmacSHA256', encoded_canonical) end
# File lib/aws/ses/base.rb, line 216 def get_aws_auth_header_v4 SES.authorization_header_v4(sig_v4_auth_credential, sig_v4_auth_signed_headers, sig_v4_auth_signature) end
# File lib/aws/ses/base.rb, line 195 def get_req_headers headers = {} if signature_version == 4 headers['host'] = @server headers['authorization'] = get_aws_auth_header_v4 headers['x-amz-date'] = amzdate headers['user-agent'] = @user_agent else headers['x-amzn-authorization'] = get_aws_auth_header_v2 headers['date'] = action_time.httpdate headers['user-agent'] = @user_agent end headers end
Make the connection to AWS
passing in our request. allow us to have a one line call in each method which will do all of the work in making the actual request to AWS
.
# File lib/aws/ses/base.rb, line 166 def request(action, params = {}) @action = action # Use a copy so that we don't modify the caller's Hash, remove any keys that have nil or empty values params = params.reject { |_, value| value.nil? or value.empty?} @action_time = Time.now.getutc params.merge!( {"Action" => action, "SignatureVersion" => signature_version.to_s, "SignatureMethod" => 'HmacSHA256', "AWSAccessKeyId" => @access_key_id, "Version" => API_VERSION, "Timestamp" => action_time.iso8601 } ) @query = params.sort.collect do |param| CGI::escape(param[0]) + "=" + CGI::escape(param[1]) end.join("&") response = connection.post(@path, query, get_req_headers) response_class = AWS::SES.const_get( "#{action}Response" ) result = response_class.new(action, response) if result.error? raise ResponseError.new(result) end result end
Private Instance Methods
# File lib/aws/ses/base.rb, line 238 def amzdate @action_time ||= Time.now.getutc action_time.strftime('%Y%m%dT%H%M%SZ') end
# File lib/aws/ses/base.rb, line 260 def canonical_headers 'host:' + server + "\n" + 'x-amz-date:' + amzdate + "\n" end
# File lib/aws/ses/base.rb, line 256 def canonical_querystring signature_version == 2 ? "Action=#{action}&Version=2013-10-15" : '' end
# File lib/aws/ses/base.rb, line 252 def canonical_request "POST" + "\n" + "/" + "\n" + canonical_querystring + "\n" + canonical_headers + "\n" + sig_v4_auth_signed_headers + "\n" + payload_hash end
# File lib/aws/ses/base.rb, line 230 def credential_scope datestamp + '/' + region + '/' + SERVICE + '/' + 'aws4_request' end
# File lib/aws/ses/base.rb, line 243 def datestamp @action_time ||= Time.now.getutc action_time.strftime('%Y%m%d') end
# File lib/aws/ses/base.rb, line 272 def getSignatureKey kDate = sign(('AWS4' + @secret_access_key).encode('utf-8'), datestamp) kRegion = sign(kDate, region) kService = sign(kRegion, SERVICE) kSigning = sign(kService, 'aws4_request') kSigning end
# File lib/aws/ses/base.rb, line 248 def httpdate @action_time ||= Time.now.getutc.httpdate end
# File lib/aws/ses/base.rb, line 264 def payload_hash Digest::SHA256.hexdigest(query.to_s.encode('utf-8')) end
# File lib/aws/ses/base.rb, line 222 def sig_v4_auth_credential @access_key_id + '/' + credential_scope end
# File lib/aws/ses/base.rb, line 268 def sig_v4_auth_signature OpenSSL::HMAC.hexdigest("SHA256", getSignatureKey, string_to_sign.encode('utf-8')) end
# File lib/aws/ses/base.rb, line 226 def sig_v4_auth_signed_headers 'host;x-amz-date' end
# File lib/aws/ses/base.rb, line 281 def sign(key, msg) OpenSSL::HMAC.digest("SHA256", key, msg.encode('utf-8')) end
# File lib/aws/ses/base.rb, line 234 def string_to_sign "AWS4-HMAC-SHA256\n" + amzdate + "\n" + credential_scope + "\n" + Digest::SHA256.hexdigest(canonical_request.encode('utf-8').b) end