# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. require 'aws/core' require 'aws/simple_email_service/config' module AWS # This class is the starting point for working with Amazon # SimpleEmailService (SES). # # To use Amazon SimpleEmailService you must first # [sign up here](http://aws.amazon.com/ses/) # # For more information about Amazon SimpleEmailService: # # * [Amazon SimpleEmailService](http://aws.amazon.com/ses/) # * [Amazon SimpleEmailService Documentation](http://aws.amazon.com/documentation/ses/) # # # Credentials # # You can setup default credentials for all AWS services via # AWS.config: # # AWS.config( # :access_key_id => 'YOUR_ACCESS_KEY_ID', # :secret_access_key => 'YOUR_SECRET_ACCESS_KEY') # # Or you can set them directly on the SimpleEmailService interface: # # ses = AWS::SimpleEmailService.new( # :access_key_id => 'YOUR_ACCESS_KEY_ID', # :secret_access_key => 'YOUR_SECRET_ACCESS_KEY') # # # Rails # # If you want to use Amazon SimpleEmailService to send email from your # Rails application you just need to do 2 things: # # 1. Configure your AWS credentials with {AWS.config} # 2. Set SES as the delivery method: # # config.action_mailer.delivery_method = :amazon_ses # # This has only been tested with Rails 2.3 and Rails 3.0. # # # # Identities # # Before you can send emails, you need to verify one or more identities. # Identities are email addresses or domain names that you have control over. # Until you have [requested production access](http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/InitialSetup.Customer.html) # you will only be able to send emails to and from verified email addresses # and domains. # # ## Verifying Email Addresses # # You can verify an email address for sending/receiving emails using # the identities collection. # # identity = ses.identities.verify('email@yourdomain.com') # identity.verified? #=> false # # You will be sent an email address with a link. Follow the link to # verify the email address. # # ## Verifying Domains # # You can also verify an entire domain for sending and receiving emails. # # identity = ses.identities.verify('yourdomain.com') # identity.verification_token # #=> "216D+lZbhUL0zOoAkC83/0TAl5lJSzLmzsOjtXM7AeM=" # # You will be expected to update the DNS records for your domain with # the given verification token. See the service documentation for # more details. # # ## Listing Identities # # You can enumerate all identities: # # ses.identities.map(&:identity) # #=> ['email@foo.com', 'somedomain.com'] # # You can filter the types of identities enumerated: # # domains = ses.identities.domains.map(&:identity) # email_addresses = ses.identities.email_addresses.map(&:identity) # # You can get the verification status and token from identities as well. # # # for an email address # identity = ses.identities['youremail@yourdomain.com'] # identity.verified? #=> true/false # # # for a domain # identity = ses.identities['yourdomain.com'] # identity.verified? #=> true/false # identity.verification_token #=> '...' # # # Sending Email # # To send a basic email you can use {#send_email}. # # ses.send_email( # :subject => 'A Sample Email', # :from => 'sender@domain.com', # :to => 'receipient@domain.com', # :body_text => 'Sample email text.', # :body_html => '

Sample Email

') # # If you need to send email with attachments or have other special needs # that send_email does not support you can use {#send_raw_email}. # # ses.send_raw_email(< 'to@foo.com', :from => 'from@foo.com') # Subject: A Sample Email # # Sample email text. # EMAIL # # # Quotas # # Based on several factors, Amazon SES determines how much email you can # send and how quickly you can send it. These sending limits are defined # as follows: # # * `:max_send_rate` - Maximum number of emails you can send per second. # * `:max_24_hour_send` - Maximum number of emails you can send in a # 24-hour period. # # To get your current quotas (and how many emails you have sent in the last # 24 hours): # # ses.quotas # # => {:max_24_hour_send=>200, :max_send_rate=>1.0, :sent_last_24_hours=>22} # # # Statistics # # You can get statistics about individual emails: # # ses.statistics.each do |stats| # puts "Sent: #{stats[:sent]}" # puts "Delivery Attempts: #{stats[:delivery_attempts]}" # puts "Rejects: #{stats[:rejects]}" # puts "Bounces: #{stats[:bounces]}" # puts "Complaints: #{stats[:complaints]}" # end # # @!attribute [r] client # @return [Client] the low-level SimpleEmailService client object class SimpleEmailService autoload :Client, 'aws/simple_email_service/client' autoload :Errors, 'aws/simple_email_service/errors' autoload :EmailAddressCollection, 'aws/simple_email_service/email_address_collection' autoload :Identity, 'aws/simple_email_service/identity' autoload :IdentityCollection, 'aws/simple_email_service/identity_collection' autoload :Quotas, 'aws/simple_email_service/quotas' include Core::ServiceInterface endpoint_prefix 'email' # @note This method is deprecated. Use {#identities} instead. # @return [EmailAddressCollection] Returns a collection that represents # all of the verified email addresses for your account. def email_addresses EmailAddressCollection.new(:config => config) end # @return [IdentityCollection] def identities IdentityCollection.new(:config => config) end # Sends an email. # # ses.send_email( # :subject => 'A Sample Email', # :to => 'john@doe.com', # :from => 'no@reply.com', # :body_text => 'sample text ...', # :body_html => '

sample text ...

') # # You can also pass multiple email addresses for the `:to`, `:cc`, # `:bcc` and `:reply_to` options. Email addresses can also be # formatted with names. # # ses.send_email( # :subject => 'A Sample Email', # :to => ['"John Doe" ', '"Jane Doe" '], # :from => 'no@reply.com', # :body_text => 'sample text ...') # # @param [Hash] options # @option options [required,String] :subject The subject of the message. # A short summary of the content, which will appear in the # # recipient's inbox. # @option options [required,String] :from The sender's email address. # @option options [String,Array] :to The address(es) to send the email to. # @option options [String,Array] :cc The address(es) to cc (carbon copy) # the email to. # @option options [String,Array] :bcc The address(es) to bcc (blind # carbon copy) the email to. # @option options [String,Array] :reply_to The reply-to email address(es) # for the message. If the recipient replies to the message, each # reply-to address will receive the reply. # @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 `:return_path` option. # @option options [String] :body_text The email text contents. # You must provide `:body_text`, `:body_html` or both. # @option options [String] :body_html The email html contents. # You must provide `:body_text`, `:body_html` or both. # @option options [String] :subject_charset The character set of the # `:subject` string. If the text must contain any other characters, # then you must also specify the character set. Examples include # UTF-8, ISO-8859-1, and Shift_JIS. Defaults to 7-bit ASCII. # @option options [String] :body_text_charset The character set of the # `:body_text` string. If the text must contain any other characters, # then you must also specify the character set. Examples include # UTF-8, ISO-8859-1, and Shift_JIS. Defaults to 7-bit ASCII. # @option options [String] :body_html_charset The character set of the # `:body_html` string. If the text must contain any other characters, # then you must also specify the character set. Examples include # UTF-8, ISO-8859-1, and Shift_JIS. Defaults to 7-bit ASCII. # @option options [String] :body_html # @return [Core::Response] the SendEmail response def send_email options = {} require_each(options, :subject, :from) require_one_of(options, :to, :cc, :bcc) require_one_of(options, :body_text, :body_html) # these three options can be passed strings or arrays of strings, # but the service requires them in a list (array) [:to, :cc, :bcc, :reply_to].each do |key| if options[key] options[key] = [options[key]].flatten end end accepted_options = { :subject => %w(message subject data), :subject_charset => %w(message subject charset), :to => %w(destination to_addresses), :cc => %w(destination cc_addresses), :bcc => %w(destination bcc_addresses), :from => %w(source), :reply_to => %w(reply_to_addresses), :return_path => %w(return_path), :body_text => %w(message body text data), :body_text_charset => %w(message body text charset), :body_html => %w(message body html data), :body_html_charset => %w(message body html charset), } client.send_email(nest_options(options, accepted_options)) end # Sends a raw email (email message, with header and content specified). # Useful for sending multipart MIME emails. The raw text of the message # must comply with Internet email standards; otherwise, the message # cannot be sent. # # raw = <<-EMAIL # Date: Wed, 1 Jun 2011 09:13:07 -0700 # Subject: A Sample Email # From: "John Doe" # To: "Jane Doe" # Accept-Language: en-US # Content-Language: en-US # Content-Type: text/plain; charset="utf-8" # Content-Transfer-Encoding: base64 # MIME-Version: 1.0 # # c2FtcGxlIHRleHQNCg== # EMAIL # # ses.send_raw_email(raw) # # Amazon SES has a limit on the total number of recipients per # message: The combined number of To:, CC: and BCC: email addresses # cannot exceed 50. If you need to send an email message to a larger # audience, you can divide your recipient list into groups of 50 or # fewer, and then call Amazon SES repeatedly to send the message to # each group. # # @param [required, String] raw_message The raw text of the message. # You can pass in any object whos #to_s returns a valid formatted # email (e.g. ruby Mail gem). The raw message should: # * Contain a header and a body, separated by a blank line # * Contain all required internet email headers # * Each part of a multipart MIME message must be formatted properly # * MIME content types must be among those supported by Amazon SES. # Refer to the Amazon SES Developer Guide for more details. # * Use content that is base64-encoded, if MIME requires it # @option options [String,Array] :to One or more email addresses to # send the email to. # @option options [String] :from The sender's email address. # If you specify the :from option, then bounce notifications and # complaints will be sent to this email address. This takes # precedence over any Return-Path header that you might include in # the `raw_message`. # @return [Core::Response] the SendRawEmail response def send_raw_email raw_message, options = {} send_opts = {} send_opts[:raw_message] = {} send_opts[:raw_message][:data] = raw_message.to_s send_opts[:source] = options[:from] if options[:from] if raw_message.respond_to?(:destinations) send_opts[:destinations] = raw_message.destinations end send_opts[:destinations] = [options[:to]].flatten if options[:to] response = client.send_raw_email(send_opts) if raw_message.respond_to?(:message_id=) raw_message.message_id = "#{response.data[:message_id]}@email.amazonses.com" end response end # for compatability with ActionMailer alias_method :deliver, :send_raw_email alias_method :deliver!, :send_raw_email def settings; {}; end # @example # # ses.quotas # # {:max_24_hour_send=>200, :max_send_rate=>1.0, :sent_last_24_hours=>22} # # @return [Hash] Returns a hash of SES quotas and limits. def quotas Quotas.new(:config => config).to_h end # Returns an array of email statistics. Each object in this array is a # hash with the following keys: # # * `:delivery_attempts` # * `:rejects` # * `:bounces` # * `:complaints` # * `:timestamp` # # @return [Array of Hashes] An array of email statistic hashes. def statistics response = client.get_send_statistics response.data[:send_data_points].collect do |data| { :sent => data[:timestamp], :delivery_attempts => data[:delivery_attempts], :rejects => data[:rejects], :bounces => data[:bounces], :complaints => data[:complaints], } end end # @api private protected def require_one_of options, *keys unless keys.any?{|key| options[key] } parts = keys.collect{|key| ":#{key}" }.join(', ') raise ArgumentError, "you must provide at least one of #{parts}" end end # @api private protected def require_each options, *keys keys.each do |key| unless options[key] raise ArgumentError, "missing required option :#{key}" end end end # @api private protected def nest_options options, accepted_options send_opts = {} accepted_options.each_pair do |option, keys| next unless options[option] hash = send_opts keys.collect{|k| k.to_sym }.each do |key| hash[key] = {} unless hash[key] if keys.last == key.to_s hash[key] = options[option] else hash = hash[key] end end end send_opts end end end