ahoy_email 0.5.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/CONTRIBUTING.md +47 -0
- data/LICENSE.txt +1 -1
- data/README.md +174 -96
- data/app/controllers/ahoy/messages_controller.rb +20 -22
- data/app/models/ahoy/message.rb +1 -1
- data/config/routes.rb +1 -3
- data/lib/ahoy_email/engine.rb +3 -3
- data/lib/ahoy_email/mailer.rb +31 -21
- data/lib/ahoy_email/observer.rb +7 -0
- data/lib/ahoy_email/processor.rb +52 -67
- data/lib/ahoy_email/tracker.rb +19 -0
- data/lib/ahoy_email/version.rb +1 -1
- data/lib/ahoy_email.rb +50 -22
- data/lib/generators/ahoy_email/install_generator.rb +3 -20
- data/lib/generators/ahoy_email/templates/install.rb.tt +11 -0
- metadata +15 -64
- data/.gitignore +0 -24
- data/.travis.yml +0 -16
- data/Gemfile +0 -6
- data/Rakefile +0 -9
- data/ahoy_email.gemspec +0 -35
- data/lib/ahoy_email/interceptor.rb +0 -9
- data/lib/generators/ahoy_email/templates/install.rb +0 -30
- data/test/gemfiles/actionmailer42.gemfile +0 -6
- data/test/gemfiles/actionmailer50.gemfile +0 -6
- data/test/gemfiles/actionmailer51.gemfile +0 -6
- data/test/internal/config/database.yml +0 -3
- data/test/internal/config/routes.rb +0 -3
- data/test/internal/db/schema.rb +0 -30
- data/test/mailer_test.rb +0 -153
- data/test/test_helper.rb +0 -16
    
        data/lib/ahoy_email/processor.rb
    CHANGED
    
    | @@ -1,103 +1,90 @@ | |
| 1 1 | 
             
            module AhoyEmail
         | 
| 2 2 | 
             
              class Processor
         | 
| 3 | 
            -
                attr_reader : | 
| 3 | 
            +
                attr_reader :mailer, :options
         | 
| 4 4 |  | 
| 5 5 | 
             
                UTM_PARAMETERS = %w(utm_source utm_medium utm_term utm_content utm_campaign)
         | 
| 6 6 |  | 
| 7 | 
            -
                def initialize( | 
| 8 | 
            -
                  @message = message
         | 
| 7 | 
            +
                def initialize(mailer, options)
         | 
| 9 8 | 
             
                  @mailer = mailer
         | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
                def process
         | 
| 13 | 
            -
                  Safely.safely do
         | 
| 14 | 
            -
                    action_name = mailer.action_name.to_sym
         | 
| 15 | 
            -
                    if options[:message] && (!options[:only] || options[:only].include?(action_name)) && !options[:except].to_a.include?(action_name)
         | 
| 16 | 
            -
                      @ahoy_message = AhoyEmail.message_model.new
         | 
| 17 | 
            -
                      ahoy_message.token = generate_token
         | 
| 18 | 
            -
                      ahoy_message.to = Array(message.to).join(", ") if ahoy_message.respond_to?(:to=)
         | 
| 19 | 
            -
                      ahoy_message.user = options[:user]
         | 
| 9 | 
            +
                  @options = options
         | 
| 20 10 |  | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 11 | 
            +
                  unknown_keywords = options.keys - AhoyEmail.default_options.keys
         | 
| 12 | 
            +
                  raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any?
         | 
| 13 | 
            +
                end
         | 
| 23 14 |  | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 15 | 
            +
                def perform
         | 
| 16 | 
            +
                  track_open if options[:open]
         | 
| 17 | 
            +
                  track_links if options[:utm_params] || options[:click]
         | 
| 18 | 
            +
                  track_message
         | 
| 19 | 
            +
                end
         | 
| 27 20 |  | 
| 28 | 
            -
             | 
| 29 | 
            -
                        ahoy_message.send("#{k}=", options[k.to_sym]) if ahoy_message.respond_to?("#{k}=")
         | 
| 30 | 
            -
                      end
         | 
| 21 | 
            +
                protected
         | 
| 31 22 |  | 
| 32 | 
            -
             | 
| 23 | 
            +
                def message
         | 
| 24 | 
            +
                  mailer.message
         | 
| 25 | 
            +
                end
         | 
| 33 26 |  | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
                    end
         | 
| 37 | 
            -
                  end
         | 
| 27 | 
            +
                def token
         | 
| 28 | 
            +
                  @token ||= SecureRandom.urlsafe_base64(32).gsub(/[\-_]/, "").first(32)
         | 
| 38 29 | 
             
                end
         | 
| 39 30 |  | 
| 40 | 
            -
                def  | 
| 41 | 
            -
                   | 
| 42 | 
            -
                     | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 31 | 
            +
                def track_message
         | 
| 32 | 
            +
                  data = {
         | 
| 33 | 
            +
                    mailer: options[:mailer],
         | 
| 34 | 
            +
                    extra: options[:extra],
         | 
| 35 | 
            +
                    user: options[:user]
         | 
| 36 | 
            +
                  }
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  # legacy, remove in next major version
         | 
| 39 | 
            +
                  user = options[:user]
         | 
| 40 | 
            +
                  if user
         | 
| 41 | 
            +
                    data[:user_type] = user.model_name.name
         | 
| 42 | 
            +
                    id = user.id
         | 
| 43 | 
            +
                    data[:user_id] = id.is_a?(Integer) ? id : id.to_s
         | 
| 50 44 | 
             
                  end
         | 
| 51 | 
            -
                end
         | 
| 52 45 |  | 
| 53 | 
            -
             | 
| 46 | 
            +
                  if options[:open] || options[:click]
         | 
| 47 | 
            +
                    data[:token] = token
         | 
| 48 | 
            +
                  end
         | 
| 54 49 |  | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
                    if mailer.ahoy_options
         | 
| 59 | 
            -
                      options = options.except(:only, :except).merge(mailer.ahoy_options)
         | 
| 60 | 
            -
                    end
         | 
| 61 | 
            -
                    options.each do |k, v|
         | 
| 62 | 
            -
                      if v.respond_to?(:call)
         | 
| 63 | 
            -
                        options[k] = v.call(message, mailer)
         | 
| 64 | 
            -
                      end
         | 
| 50 | 
            +
                  if options[:utm_params]
         | 
| 51 | 
            +
                    UTM_PARAMETERS.map(&:to_sym).each do |k|
         | 
| 52 | 
            +
                      data[k] = options[k] if options[k]
         | 
| 65 53 | 
             
                    end
         | 
| 66 | 
            -
                    options
         | 
| 67 54 | 
             
                  end
         | 
| 68 | 
            -
                end
         | 
| 69 55 |  | 
| 70 | 
            -
             | 
| 71 | 
            -
                  SecureRandom.urlsafe_base64(32).gsub(/[\-_]/, "").first(32)
         | 
| 56 | 
            +
                  mailer.message.ahoy_data = data
         | 
| 72 57 | 
             
                end
         | 
| 73 58 |  | 
| 74 59 | 
             
                def track_open
         | 
| 75 60 | 
             
                  if html_part?
         | 
| 76 | 
            -
                     | 
| 61 | 
            +
                    part = message.html_part || message
         | 
| 62 | 
            +
                    raw_source = part.body.raw_source
         | 
| 63 | 
            +
             | 
| 77 64 | 
             
                    regex = /<\/body>/i
         | 
| 78 65 | 
             
                    url =
         | 
| 79 66 | 
             
                      url_for(
         | 
| 80 67 | 
             
                        controller: "ahoy/messages",
         | 
| 81 68 | 
             
                        action: "open",
         | 
| 82 | 
            -
                        id:  | 
| 69 | 
            +
                        id: token,
         | 
| 83 70 | 
             
                        format: "gif"
         | 
| 84 71 | 
             
                      )
         | 
| 85 72 | 
             
                    pixel = ActionController::Base.helpers.image_tag(url, size: "1x1", alt: "")
         | 
| 86 73 |  | 
| 87 74 | 
             
                    # try to add before body tag
         | 
| 88 75 | 
             
                    if raw_source.match(regex)
         | 
| 89 | 
            -
                      raw_source.gsub | 
| 76 | 
            +
                      part.body = raw_source.gsub(regex, "#{pixel}\\0")
         | 
| 90 77 | 
             
                    else
         | 
| 91 | 
            -
                      raw_source  | 
| 78 | 
            +
                      part.body = raw_source + pixel
         | 
| 92 79 | 
             
                    end
         | 
| 93 80 | 
             
                  end
         | 
| 94 81 | 
             
                end
         | 
| 95 82 |  | 
| 96 83 | 
             
                def track_links
         | 
| 97 84 | 
             
                  if html_part?
         | 
| 98 | 
            -
                     | 
| 85 | 
            +
                    part = message.html_part || message
         | 
| 99 86 |  | 
| 100 | 
            -
                    doc = Nokogiri::HTML(body.raw_source)
         | 
| 87 | 
            +
                    doc = Nokogiri::HTML(part.body.raw_source)
         | 
| 101 88 | 
             
                    doc.css("a[href]").each do |link|
         | 
| 102 89 | 
             
                      uri = parse_uri(link["href"])
         | 
| 103 90 | 
             
                      next unless trackable?(uri)
         | 
| @@ -113,20 +100,22 @@ module AhoyEmail | |
| 113 100 | 
             
                      end
         | 
| 114 101 |  | 
| 115 102 | 
             
                      if options[:click] && !skip_attribute?(link, "click")
         | 
| 116 | 
            -
                         | 
| 103 | 
            +
                        raise "Secret token is empty" unless AhoyEmail.secret_token
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                        # TODO sign more than just url and transition to HMAC-SHA256
         | 
| 106 | 
            +
                        signature = OpenSSL::HMAC.hexdigest("SHA1", AhoyEmail.secret_token, link["href"])
         | 
| 117 107 | 
             
                        link["href"] =
         | 
| 118 108 | 
             
                          url_for(
         | 
| 119 109 | 
             
                            controller: "ahoy/messages",
         | 
| 120 110 | 
             
                            action: "click",
         | 
| 121 | 
            -
                            id:  | 
| 111 | 
            +
                            id: token,
         | 
| 122 112 | 
             
                            url: link["href"],
         | 
| 123 113 | 
             
                            signature: signature
         | 
| 124 114 | 
             
                          )
         | 
| 125 115 | 
             
                      end
         | 
| 126 116 | 
             
                    end
         | 
| 127 117 |  | 
| 128 | 
            -
                     | 
| 129 | 
            -
                    body.raw_source.sub!(body.raw_source, doc.to_s)
         | 
| 118 | 
            +
                    part.body = doc.to_s
         | 
| 130 119 | 
             
                  end
         | 
| 131 120 | 
             
                end
         | 
| 132 121 |  | 
| @@ -157,11 +146,7 @@ module AhoyEmail | |
| 157 146 | 
             
                # Return uri if valid, nil otherwise
         | 
| 158 147 | 
             
                def parse_uri(href)
         | 
| 159 148 | 
             
                  # to_s prevent to return nil from this method
         | 
| 160 | 
            -
                   | 
| 161 | 
            -
                    Addressable::URI.heuristic_parse(href.to_s) rescue nil
         | 
| 162 | 
            -
                  else
         | 
| 163 | 
            -
                    Addressable::URI.parse(href.to_s) rescue nil
         | 
| 164 | 
            -
                  end
         | 
| 149 | 
            +
                  Addressable::URI.heuristic_parse(href.to_s) rescue nil
         | 
| 165 150 | 
             
                end
         | 
| 166 151 |  | 
| 167 152 | 
             
                def url_for(opt)
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            module AhoyEmail
         | 
| 2 | 
            +
              class Tracker
         | 
| 3 | 
            +
                attr_reader :message
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def initialize(message)
         | 
| 6 | 
            +
                  @message = message
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def perform
         | 
| 10 | 
            +
                  Safely.safely do
         | 
| 11 | 
            +
                    # perform_deliveries check still needed in observer
         | 
| 12 | 
            +
                    if message.perform_deliveries && message.ahoy_data
         | 
| 13 | 
            +
                      data = message.ahoy_data.merge(message: message)
         | 
| 14 | 
            +
                      message.ahoy_message = AhoyEmail.track_method.call(data)
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
    
        data/lib/ahoy_email/version.rb
    CHANGED
    
    
    
        data/lib/ahoy_email.rb
    CHANGED
    
    | @@ -1,47 +1,74 @@ | |
| 1 | 
            +
            # dependencies
         | 
| 1 2 | 
             
            require "active_support"
         | 
| 2 | 
            -
            require "nokogiri"
         | 
| 3 3 | 
             
            require "addressable/uri"
         | 
| 4 | 
            +
            require "nokogiri"
         | 
| 4 5 | 
             
            require "openssl"
         | 
| 5 6 | 
             
            require "safely/core"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            # modules
         | 
| 6 9 | 
             
            require "ahoy_email/processor"
         | 
| 7 | 
            -
            require "ahoy_email/ | 
| 10 | 
            +
            require "ahoy_email/tracker"
         | 
| 11 | 
            +
            require "ahoy_email/observer"
         | 
| 8 12 | 
             
            require "ahoy_email/mailer"
         | 
| 9 | 
            -
            require "ahoy_email/engine"
         | 
| 10 13 | 
             
            require "ahoy_email/version"
         | 
| 14 | 
            +
            require "ahoy_email/engine" if defined?(Rails)
         | 
| 11 15 |  | 
| 12 16 | 
             
            module AhoyEmail
         | 
| 13 | 
            -
              mattr_accessor :secret_token, : | 
| 17 | 
            +
              mattr_accessor :secret_token, :default_options, :subscribers, :invalid_redirect_url, :track_method, :api, :preserve_callbacks
         | 
| 18 | 
            +
              mattr_writer :message_model
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              self.api = false
         | 
| 14 21 |  | 
| 15 | 
            -
              self. | 
| 22 | 
            +
              self.default_options = {
         | 
| 16 23 | 
             
                message: true,
         | 
| 17 | 
            -
                open:  | 
| 18 | 
            -
                click:  | 
| 19 | 
            -
                utm_params:  | 
| 20 | 
            -
                utm_source: -> | 
| 24 | 
            +
                open: false,
         | 
| 25 | 
            +
                click: false,
         | 
| 26 | 
            +
                utm_params: false,
         | 
| 27 | 
            +
                utm_source: -> { mailer_name },
         | 
| 21 28 | 
             
                utm_medium: "email",
         | 
| 22 29 | 
             
                utm_term: nil,
         | 
| 23 30 | 
             
                utm_content: nil,
         | 
| 24 | 
            -
                utm_campaign: -> | 
| 25 | 
            -
                user: ->( | 
| 26 | 
            -
                mailer: -> | 
| 31 | 
            +
                utm_campaign: -> { action_name },
         | 
| 32 | 
            +
                user: -> { @user || (respond_to?(:params) && params && params[:user]) || (message.to.try(:size) == 1 ? (User.find_by(email: message.to.first) rescue nil) : nil) },
         | 
| 33 | 
            +
                mailer: -> { "#{self.class.name}##{action_name}" },
         | 
| 27 34 | 
             
                url_options: {},
         | 
| 28 | 
            -
                 | 
| 35 | 
            +
                extra: {},
         | 
| 36 | 
            +
                unsubscribe_links: false
         | 
| 29 37 | 
             
              }
         | 
| 30 38 |  | 
| 31 | 
            -
              self. | 
| 39 | 
            +
              self.track_method = lambda do |data|
         | 
| 40 | 
            +
                message = data[:message]
         | 
| 32 41 |  | 
| 33 | 
            -
             | 
| 42 | 
            +
                ahoy_message = AhoyEmail.message_model.new
         | 
| 43 | 
            +
                ahoy_message.to = Array(message.to).join(", ") if ahoy_message.respond_to?(:to=)
         | 
| 44 | 
            +
                ahoy_message.user = data[:user] if ahoy_message.respond_to?(:user=)
         | 
| 34 45 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
                 | 
| 37 | 
            -
             | 
| 46 | 
            +
                ahoy_message.mailer = data[:mailer] if ahoy_message.respond_to?(:mailer=)
         | 
| 47 | 
            +
                ahoy_message.subject = message.subject if ahoy_message.respond_to?(:subject=)
         | 
| 48 | 
            +
                ahoy_message.content = message.encoded if ahoy_message.respond_to?(:content=)
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                AhoyEmail::Processor::UTM_PARAMETERS.each do |k|
         | 
| 51 | 
            +
                  ahoy_message.send("#{k}=", data[k.to_sym]) if ahoy_message.respond_to?("#{k}=")
         | 
| 52 | 
            +
                end
         | 
| 38 53 |  | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 54 | 
            +
                ahoy_message.token = data[:token] if ahoy_message.respond_to?(:token=)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                ahoy_message.assign_attributes(data[:extra] || {})
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                ahoy_message.sent_at = Time.now
         | 
| 59 | 
            +
                ahoy_message.save!
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                ahoy_message
         | 
| 41 62 | 
             
              end
         | 
| 42 63 |  | 
| 64 | 
            +
              self.subscribers = []
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              self.preserve_callbacks = []
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              self.message_model = -> { ::Ahoy::Message }
         | 
| 69 | 
            +
             | 
| 43 70 | 
             
              def self.message_model
         | 
| 44 | 
            -
                model =  | 
| 71 | 
            +
                model = defined?(@@message_model) && @@message_model
         | 
| 45 72 | 
             
                model = model.call if model.respond_to?(:call)
         | 
| 46 73 | 
             
                model
         | 
| 47 74 | 
             
              end
         | 
| @@ -49,5 +76,6 @@ end | |
| 49 76 |  | 
| 50 77 | 
             
            ActiveSupport.on_load(:action_mailer) do
         | 
| 51 78 | 
             
              include AhoyEmail::Mailer
         | 
| 52 | 
            -
               | 
| 79 | 
            +
              register_observer AhoyEmail::Observer
         | 
| 80 | 
            +
              Mail::Message.send(:attr_accessor, :ahoy_data, :ahoy_message)
         | 
| 53 81 | 
             
            end
         | 
| @@ -1,34 +1,17 @@ | |
| 1 | 
            -
            # taken from https://github.com/collectiveidea/audited/blob/master/lib/generators/audited/install_generator.rb
         | 
| 2 | 
            -
            require "rails/generators"
         | 
| 3 | 
            -
            require "rails/generators/migration"
         | 
| 4 | 
            -
            require "active_record"
         | 
| 5 1 | 
             
            require "rails/generators/active_record"
         | 
| 6 2 |  | 
| 7 3 | 
             
            module AhoyEmail
         | 
| 8 4 | 
             
              module Generators
         | 
| 9 5 | 
             
                class InstallGenerator < Rails::Generators::Base
         | 
| 10 | 
            -
                  include  | 
| 11 | 
            -
             | 
| 12 | 
            -
                  source_root File.expand_path("../templates", __FILE__)
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  # Implement the required interface for Rails::Generators::Migration.
         | 
| 15 | 
            -
                  def self.next_migration_number(dirname) #:nodoc:
         | 
| 16 | 
            -
                    next_migration_number = current_migration_number(dirname) + 1
         | 
| 17 | 
            -
                    if ActiveRecord::Base.timestamped_migrations
         | 
| 18 | 
            -
                      [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
         | 
| 19 | 
            -
                    else
         | 
| 20 | 
            -
                      "%.3d" % next_migration_number
         | 
| 21 | 
            -
                    end
         | 
| 22 | 
            -
                  end
         | 
| 6 | 
            +
                  include ActiveRecord::Generators::Migration
         | 
| 7 | 
            +
                  source_root File.join(__dir__, "templates")
         | 
| 23 8 |  | 
| 24 9 | 
             
                  def copy_migration
         | 
| 25 10 | 
             
                    migration_template "install.rb", "db/migrate/create_ahoy_messages.rb", migration_version: migration_version
         | 
| 26 11 | 
             
                  end
         | 
| 27 12 |  | 
| 28 13 | 
             
                  def migration_version
         | 
| 29 | 
            -
                     | 
| 30 | 
            -
                      "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
         | 
| 31 | 
            -
                    end
         | 
| 14 | 
            +
                    "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
         | 
| 32 15 | 
             
                  end
         | 
| 33 16 | 
             
                end
         | 
| 34 17 | 
             
              end
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
         | 
| 2 | 
            +
              def change
         | 
| 3 | 
            +
                create_table :ahoy_messages do |t|
         | 
| 4 | 
            +
                  t.references :user, polymorphic: true
         | 
| 5 | 
            +
                  t.text :to
         | 
| 6 | 
            +
                  t.string :mailer
         | 
| 7 | 
            +
                  t.text :subject
         | 
| 8 | 
            +
                  t.timestamp :sent_at
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,57 +1,29 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: ahoy_email
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 1.1.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Andrew Kane
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2019-07-16 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            -
              name: railties
         | 
| 15 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            -
                requirements:
         | 
| 17 | 
            -
                - - ">="
         | 
| 18 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: '0'
         | 
| 20 | 
            -
              type: :runtime
         | 
| 21 | 
            -
              prerelease: false
         | 
| 22 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            -
                requirements:
         | 
| 24 | 
            -
                - - ">="
         | 
| 25 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            -
                    version: '0'
         | 
| 27 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 14 | 
             
              name: actionmailer
         | 
| 29 15 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 16 | 
             
                requirements:
         | 
| 31 17 | 
             
                - - ">="
         | 
| 32 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            -
                    version: ' | 
| 34 | 
            -
              type: :runtime
         | 
| 35 | 
            -
              prerelease: false
         | 
| 36 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            -
                requirements:
         | 
| 38 | 
            -
                - - ">="
         | 
| 39 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            -
                    version: '0'
         | 
| 41 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            -
              name: activerecord
         | 
| 43 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            -
                requirements:
         | 
| 45 | 
            -
                - - ">="
         | 
| 46 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            -
                    version: '0'
         | 
| 19 | 
            +
                    version: '5'
         | 
| 48 20 | 
             
              type: :runtime
         | 
| 49 21 | 
             
              prerelease: false
         | 
| 50 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 23 | 
             
                requirements:
         | 
| 52 24 | 
             
                - - ">="
         | 
| 53 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            -
                    version: ' | 
| 26 | 
            +
                    version: '5'
         | 
| 55 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 56 28 | 
             
              name: addressable
         | 
| 57 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -137,7 +109,7 @@ dependencies: | |
| 137 109 | 
             
                  - !ruby/object:Gem::Version
         | 
| 138 110 | 
             
                    version: '0'
         | 
| 139 111 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 140 | 
            -
              name:  | 
| 112 | 
            +
              name: activerecord
         | 
| 141 113 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 142 114 | 
             
                requirements:
         | 
| 143 115 | 
             
                - - ">="
         | 
| @@ -151,7 +123,7 @@ dependencies: | |
| 151 123 | 
             
                  - !ruby/object:Gem::Version
         | 
| 152 124 | 
             
                    version: '0'
         | 
| 153 125 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 154 | 
            -
              name:  | 
| 126 | 
            +
              name: combustion
         | 
| 155 127 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 156 128 | 
             
                requirements:
         | 
| 157 129 | 
             
                - - ">="
         | 
| @@ -179,39 +151,27 @@ dependencies: | |
| 179 151 | 
             
                  - !ruby/object:Gem::Version
         | 
| 180 152 | 
             
                    version: '0'
         | 
| 181 153 | 
             
            description: 
         | 
| 182 | 
            -
            email:
         | 
| 183 | 
            -
            - andrew@chartkick.com
         | 
| 154 | 
            +
            email: andrew@chartkick.com
         | 
| 184 155 | 
             
            executables: []
         | 
| 185 156 | 
             
            extensions: []
         | 
| 186 157 | 
             
            extra_rdoc_files: []
         | 
| 187 158 | 
             
            files:
         | 
| 188 | 
            -
            - ".gitignore"
         | 
| 189 | 
            -
            - ".travis.yml"
         | 
| 190 159 | 
             
            - CHANGELOG.md
         | 
| 191 | 
            -
            -  | 
| 160 | 
            +
            - CONTRIBUTING.md
         | 
| 192 161 | 
             
            - LICENSE.txt
         | 
| 193 162 | 
             
            - README.md
         | 
| 194 | 
            -
            - Rakefile
         | 
| 195 | 
            -
            - ahoy_email.gemspec
         | 
| 196 163 | 
             
            - app/controllers/ahoy/messages_controller.rb
         | 
| 197 164 | 
             
            - app/models/ahoy/message.rb
         | 
| 198 165 | 
             
            - config/routes.rb
         | 
| 199 166 | 
             
            - lib/ahoy_email.rb
         | 
| 200 167 | 
             
            - lib/ahoy_email/engine.rb
         | 
| 201 | 
            -
            - lib/ahoy_email/interceptor.rb
         | 
| 202 168 | 
             
            - lib/ahoy_email/mailer.rb
         | 
| 169 | 
            +
            - lib/ahoy_email/observer.rb
         | 
| 203 170 | 
             
            - lib/ahoy_email/processor.rb
         | 
| 171 | 
            +
            - lib/ahoy_email/tracker.rb
         | 
| 204 172 | 
             
            - lib/ahoy_email/version.rb
         | 
| 205 173 | 
             
            - lib/generators/ahoy_email/install_generator.rb
         | 
| 206 | 
            -
            - lib/generators/ahoy_email/templates/install.rb
         | 
| 207 | 
            -
            - test/gemfiles/actionmailer42.gemfile
         | 
| 208 | 
            -
            - test/gemfiles/actionmailer50.gemfile
         | 
| 209 | 
            -
            - test/gemfiles/actionmailer51.gemfile
         | 
| 210 | 
            -
            - test/internal/config/database.yml
         | 
| 211 | 
            -
            - test/internal/config/routes.rb
         | 
| 212 | 
            -
            - test/internal/db/schema.rb
         | 
| 213 | 
            -
            - test/mailer_test.rb
         | 
| 214 | 
            -
            - test/test_helper.rb
         | 
| 174 | 
            +
            - lib/generators/ahoy_email/templates/install.rb.tt
         | 
| 215 175 | 
             
            homepage: https://github.com/ankane/ahoy_email
         | 
| 216 176 | 
             
            licenses:
         | 
| 217 177 | 
             
            - MIT
         | 
| @@ -224,24 +184,15 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 224 184 | 
             
              requirements:
         | 
| 225 185 | 
             
              - - ">="
         | 
| 226 186 | 
             
                - !ruby/object:Gem::Version
         | 
| 227 | 
            -
                  version: 2. | 
| 187 | 
            +
                  version: '2.4'
         | 
| 228 188 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 229 189 | 
             
              requirements:
         | 
| 230 190 | 
             
              - - ">="
         | 
| 231 191 | 
             
                - !ruby/object:Gem::Version
         | 
| 232 192 | 
             
                  version: '0'
         | 
| 233 193 | 
             
            requirements: []
         | 
| 234 | 
            -
             | 
| 235 | 
            -
            rubygems_version: 2.7.6
         | 
| 194 | 
            +
            rubygems_version: 3.0.4
         | 
| 236 195 | 
             
            signing_key: 
         | 
| 237 196 | 
             
            specification_version: 4
         | 
| 238 | 
            -
            summary:  | 
| 239 | 
            -
            test_files:
         | 
| 240 | 
            -
            - test/gemfiles/actionmailer42.gemfile
         | 
| 241 | 
            -
            - test/gemfiles/actionmailer50.gemfile
         | 
| 242 | 
            -
            - test/gemfiles/actionmailer51.gemfile
         | 
| 243 | 
            -
            - test/internal/config/database.yml
         | 
| 244 | 
            -
            - test/internal/config/routes.rb
         | 
| 245 | 
            -
            - test/internal/db/schema.rb
         | 
| 246 | 
            -
            - test/mailer_test.rb
         | 
| 247 | 
            -
            - test/test_helper.rb
         | 
| 197 | 
            +
            summary: Email analytics for Rails
         | 
| 198 | 
            +
            test_files: []
         | 
    
        data/.gitignore
    DELETED
    
    | @@ -1,24 +0,0 @@ | |
| 1 | 
            -
            *.gem
         | 
| 2 | 
            -
            *.rbc
         | 
| 3 | 
            -
            .bundle
         | 
| 4 | 
            -
            .config
         | 
| 5 | 
            -
            .yardoc
         | 
| 6 | 
            -
            *.lock
         | 
| 7 | 
            -
            InstalledFiles
         | 
| 8 | 
            -
            _yardoc
         | 
| 9 | 
            -
            coverage
         | 
| 10 | 
            -
            doc/
         | 
| 11 | 
            -
            lib/bundler/man
         | 
| 12 | 
            -
            pkg
         | 
| 13 | 
            -
            rdoc
         | 
| 14 | 
            -
            spec/reports
         | 
| 15 | 
            -
            test/tmp
         | 
| 16 | 
            -
            test/version_tmp
         | 
| 17 | 
            -
            tmp
         | 
| 18 | 
            -
            *.bundle
         | 
| 19 | 
            -
            *.so
         | 
| 20 | 
            -
            *.o
         | 
| 21 | 
            -
            *.a
         | 
| 22 | 
            -
            mkmf.log
         | 
| 23 | 
            -
            *.log
         | 
| 24 | 
            -
            *.sqlite
         | 
    
        data/.travis.yml
    DELETED
    
    | @@ -1,16 +0,0 @@ | |
| 1 | 
            -
            language: ruby
         | 
| 2 | 
            -
            rvm:
         | 
| 3 | 
            -
              - 2.4.2
         | 
| 4 | 
            -
            sudo: false
         | 
| 5 | 
            -
            script: bundle exec rake test
         | 
| 6 | 
            -
            before_script:
         | 
| 7 | 
            -
              - gem install bundler
         | 
| 8 | 
            -
            notifications:
         | 
| 9 | 
            -
              email:
         | 
| 10 | 
            -
                on_success: never
         | 
| 11 | 
            -
                on_failure: change
         | 
| 12 | 
            -
            gemfile:
         | 
| 13 | 
            -
              - Gemfile
         | 
| 14 | 
            -
              - test/gemfiles/actionmailer51.gemfile
         | 
| 15 | 
            -
              - test/gemfiles/actionmailer50.gemfile
         | 
| 16 | 
            -
              - test/gemfiles/actionmailer42.gemfile
         | 
    
        data/Gemfile
    DELETED
    
    
    
        data/Rakefile
    DELETED
    
    
    
        data/ahoy_email.gemspec
    DELETED
    
    | @@ -1,35 +0,0 @@ | |
| 1 | 
            -
            # coding: utf-8
         | 
| 2 | 
            -
            lib = File.expand_path("../lib", __FILE__)
         | 
| 3 | 
            -
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 4 | 
            -
            require "ahoy_email/version"
         | 
| 5 | 
            -
             | 
| 6 | 
            -
            Gem::Specification.new do |spec|
         | 
| 7 | 
            -
              spec.name          = "ahoy_email"
         | 
| 8 | 
            -
              spec.version       = AhoyEmail::VERSION
         | 
| 9 | 
            -
              spec.authors       = ["Andrew Kane"]
         | 
| 10 | 
            -
              spec.email         = ["andrew@chartkick.com"]
         | 
| 11 | 
            -
              spec.summary       = "Simple, powerful email tracking for Rails"
         | 
| 12 | 
            -
              spec.homepage      = "https://github.com/ankane/ahoy_email"
         | 
| 13 | 
            -
              spec.license       = "MIT"
         | 
| 14 | 
            -
             | 
| 15 | 
            -
              spec.files         = `git ls-files -z`.split("\x0")
         | 
| 16 | 
            -
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         | 
| 17 | 
            -
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         | 
| 18 | 
            -
              spec.require_paths = ["lib"]
         | 
| 19 | 
            -
             | 
| 20 | 
            -
              spec.required_ruby_version = ">= 2.2.0"
         | 
| 21 | 
            -
             | 
| 22 | 
            -
              spec.add_runtime_dependency "railties"
         | 
| 23 | 
            -
              spec.add_runtime_dependency "actionmailer"
         | 
| 24 | 
            -
              spec.add_runtime_dependency "activerecord"
         | 
| 25 | 
            -
              spec.add_runtime_dependency "addressable", ">= 2.3.2"
         | 
| 26 | 
            -
              spec.add_runtime_dependency "nokogiri"
         | 
| 27 | 
            -
              spec.add_runtime_dependency "safely_block", ">= 0.1.1"
         | 
| 28 | 
            -
             | 
| 29 | 
            -
              spec.add_development_dependency "bundler"
         | 
| 30 | 
            -
              spec.add_development_dependency "rake"
         | 
| 31 | 
            -
              spec.add_development_dependency "minitest"
         | 
| 32 | 
            -
              spec.add_development_dependency "combustion"
         | 
| 33 | 
            -
              spec.add_development_dependency "rails"
         | 
| 34 | 
            -
              spec.add_development_dependency "sqlite3"
         | 
| 35 | 
            -
            end
         | 
| @@ -1,30 +0,0 @@ | |
| 1 | 
            -
            class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
         | 
| 2 | 
            -
              def change
         | 
| 3 | 
            -
                create_table :ahoy_messages do |t|
         | 
| 4 | 
            -
                  t.string :token
         | 
| 5 | 
            -
             | 
| 6 | 
            -
                  # user
         | 
| 7 | 
            -
                  t.text :to
         | 
| 8 | 
            -
                  t.references :user, polymorphic: true
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                  # optional - feel free to remove
         | 
| 11 | 
            -
                  t.string :mailer
         | 
| 12 | 
            -
                  t.text :subject
         | 
| 13 | 
            -
                  # t.text :content
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                  # optional
         | 
| 16 | 
            -
                  # t.string :utm_source
         | 
| 17 | 
            -
                  # t.string :utm_medium
         | 
| 18 | 
            -
                  # t.string :utm_term
         | 
| 19 | 
            -
                  # t.string :utm_content
         | 
| 20 | 
            -
                  # t.string :utm_campaign
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  # timestamps
         | 
| 23 | 
            -
                  t.timestamp :sent_at
         | 
| 24 | 
            -
                  t.timestamp :opened_at
         | 
| 25 | 
            -
                  t.timestamp :clicked_at
         | 
| 26 | 
            -
                end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                add_index :ahoy_messages, [:token]
         | 
| 29 | 
            -
              end
         | 
| 30 | 
            -
            end
         |