tuktuk 0.5.3 → 0.5.4
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.
- data/README.md +15 -11
- data/lib/tuktuk/bounce.rb +8 -8
- data/lib/tuktuk/package.rb +5 -4
- data/lib/tuktuk/tuktuk.rb +4 -3
- data/lib/tuktuk/version.rb +1 -1
- data/spec/deliver_spec.rb +208 -206
- metadata +94 -75
- checksums.yaml +0 -7
    
        data/README.md
    CHANGED
    
    | @@ -16,9 +16,9 @@ Delivering mail | |
| 16 16 | 
             
            require 'tuktuk'
         | 
| 17 17 |  | 
| 18 18 | 
             
            message = {
         | 
| 19 | 
            -
              :from | 
| 20 | 
            -
              :to | 
| 21 | 
            -
              :body | 
| 19 | 
            +
              :from    => 'you@username.com',
         | 
| 20 | 
            +
              :to      => 'user@yoursite.com',
         | 
| 21 | 
            +
              :body    => 'Hello there',
         | 
| 22 22 | 
             
              :subject => 'Hiya'
         | 
| 23 23 | 
             
            }
         | 
| 24 24 |  | 
| @@ -74,8 +74,8 @@ require 'tuktuk' | |
| 74 74 |  | 
| 75 75 | 
             
            Tuktuk.options = {
         | 
| 76 76 | 
             
              :dkim => {
         | 
| 77 | 
            -
                :domain | 
| 78 | 
            -
                :selector | 
| 77 | 
            +
                :domain      => 'yoursite.com',
         | 
| 78 | 
            +
                :selector    => 'mailer',
         | 
| 79 79 | 
             
                :private_key => IO.read('ssl/yoursite.com.key')
         | 
| 80 80 | 
             
              }
         | 
| 81 81 | 
             
            }
         | 
| @@ -85,13 +85,13 @@ message = { ... } | |
| 85 85 | 
             
            response, email = Tuktuk.deliver(message)
         | 
| 86 86 | 
             
            ```
         | 
| 87 87 |  | 
| 88 | 
            -
            For DKIM to work, you need to set up  | 
| 88 | 
            +
            For DKIM to work, you need to set up some TXT records in your domain's DNS. You can use [this tool](http://www.socketlabs.com/domainkey-dkim-generation-wizard/) to generate the key. You should also create [SPF records](http://www.spfwizard.net/) if you haven't.
         | 
| 89 89 |  | 
| 90 90 | 
             
            All available options, with their defaults:
         | 
| 91 91 |  | 
| 92 92 | 
             
            ``` ruby
         | 
| 93 93 | 
             
            Tuktuk.options = {
         | 
| 94 | 
            -
              :log_to       => nil,   # e.g. log/mailer.log
         | 
| 94 | 
            +
              :log_to       => nil,   # e.g. log/mailer.log or STDOUT
         | 
| 95 95 | 
             
              :helo_domain  => nil,   # your server's domain goes here
         | 
| 96 96 | 
             
              :max_workers  => 0,     # controls number of threads for delivering_many emails (read below)
         | 
| 97 97 | 
             
              :open_timeout => 20,    # max seconds to wait for opening a connection
         | 
| @@ -130,13 +130,17 @@ config.action_mailer.delivery_method = :tuktuk | |
| 130 130 | 
             
            config.action_mailer.tuktuk_settings = {
         | 
| 131 131 | 
             
              :log_to => 'log/mailer.log', # when not set, Tuktuk will use Rails.logger
         | 
| 132 132 | 
             
              :dkim => {
         | 
| 133 | 
            -
                :domain | 
| 134 | 
            -
                :selector | 
| 133 | 
            +
                :domain      => 'yoursite.com',
         | 
| 134 | 
            +
                :selector    => 'mailer',
         | 
| 135 135 | 
             
                :private_key => IO.read('ssl/yoursite.com.key')
         | 
| 136 136 | 
             
              }
         | 
| 137 137 | 
             
            }
         | 
| 138 138 | 
             
            ```
         | 
| 139 139 |  | 
| 140 | 
            -
             | 
| 140 | 
            +
            # Contributions
         | 
| 141 141 |  | 
| 142 | 
            -
             | 
| 142 | 
            +
            You're more than welcome. Send a pull request, including tests, and make sure you don't break anything. That's it.
         | 
| 143 | 
            +
             | 
| 144 | 
            +
            # Copyright
         | 
| 145 | 
            +
             | 
| 146 | 
            +
            (c) Fork Limited. MIT license.
         | 
    
        data/lib/tuktuk/bounce.rb
    CHANGED
    
    | @@ -3,8 +3,8 @@ module Tuktuk | |
| 3 3 | 
             
            class Bounce < RuntimeError
         | 
| 4 4 |  | 
| 5 5 | 
             
              HARD_BOUNCE_CODES = [
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 6 | 
            +
                501, # Bad address syntax (eg. "i.user.@hotmail.com")
         | 
| 7 | 
            +
                504, # mailbox is disabled
         | 
| 8 8 | 
             
                511, # sorry, no mailbox here by that name (#5.1.1 - chkuser)
         | 
| 9 9 | 
             
                540, # recipient's email account has been suspended.
         | 
| 10 10 | 
             
                550, # Requested action not taken: mailbox unavailable
         | 
| @@ -18,19 +18,19 @@ class Bounce < RuntimeError | |
| 18 18 | 
             
                if e.is_a?(Net::SMTPFatalError) and code = e.to_s[0..2] and HARD_BOUNCE_CODES.include? code.to_i
         | 
| 19 19 | 
             
                  HardBounce.new(e)
         | 
| 20 20 | 
             
                else
         | 
| 21 | 
            -
                  SoftBounce.new(e) # either soft mailbox bounce or server bounce
         | 
| 21 | 
            +
                  SoftBounce.new(e) # either soft mailbox bounce, timeout or server bounce
         | 
| 22 22 | 
             
                end
         | 
| 23 23 | 
             
              end
         | 
| 24 24 |  | 
| 25 25 | 
             
              def code
         | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 26 | 
            +
                if str = to_s[0..2] and str.gsub(/[^0-9]/, '') != ''
         | 
| 27 | 
            +
                  str.to_i
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 30 |  | 
| 31 31 | 
             
            end
         | 
| 32 32 |  | 
| 33 33 | 
             
            class HardBounce < Bounce; end
         | 
| 34 34 | 
             
            class SoftBounce < Bounce; end
         | 
| 35 35 |  | 
| 36 | 
            -
            end
         | 
| 36 | 
            +
            end
         | 
    
        data/lib/tuktuk/package.rb
    CHANGED
    
    | @@ -20,10 +20,11 @@ module Package | |
| 20 20 | 
             
                  mail = message[:html_body] ? mixed(message) : plain(message)
         | 
| 21 21 | 
             
                  mail.charset = 'UTF-8'
         | 
| 22 22 |  | 
| 23 | 
            -
                  mail['In-Reply-To'] | 
| 24 | 
            -
                  mail['List- | 
| 25 | 
            -
                  mail['List- | 
| 26 | 
            -
                  mail[' | 
| 23 | 
            +
                  mail['In-Reply-To']      = message[:in_reply_to] if message[:in_reply_to]
         | 
| 24 | 
            +
                  mail['List-Unsubscribe'] = message[:list_unsubscribe] if message[:list_unsubscribe]
         | 
| 25 | 
            +
                  mail['List-Archive']     = message[:list_archive] if message[:list_archive]
         | 
| 26 | 
            +
                  mail['List-Id']          = message[:list_id] if message[:list_id]
         | 
| 27 | 
            +
                  mail['X-Mailer']         = "Tuktuk SMTP v#{Tuktuk::VERSION}"
         | 
| 27 28 |  | 
| 28 29 | 
             
                  if message[:return_path]
         | 
| 29 30 | 
             
                    mail['Return-Path'] = message[:return_path]
         | 
    
        data/lib/tuktuk/tuktuk.rb
    CHANGED
    
    | @@ -14,7 +14,7 @@ DEFAULTS = { | |
| 14 14 | 
             
              :read_timeout => 20,
         | 
| 15 15 | 
             
              :open_timeout => 20,
         | 
| 16 16 | 
             
              :verify_ssl   => true,
         | 
| 17 | 
            -
              :debug        => false, | 
| 17 | 
            +
              :debug        => false,
         | 
| 18 18 | 
             
              :log_to       => nil # $stdout,
         | 
| 19 19 | 
             
            }
         | 
| 20 20 |  | 
| @@ -42,7 +42,7 @@ module Tuktuk | |
| 42 42 | 
             
                end
         | 
| 43 43 |  | 
| 44 44 | 
             
                def deliver_many(messages, opts = {})
         | 
| 45 | 
            -
                  raise  | 
| 45 | 
            +
                  raise ArgumentError, "Not an array of messages: #{messages.inspect}" unless messages.any?
         | 
| 46 46 | 
             
                  self.options = opts if opts.any?
         | 
| 47 47 | 
             
                  messages_by_domain = reorder_by_domain(messages)
         | 
| 48 48 | 
             
                  lookup_and_deliver_many(messages_by_domain)
         | 
| @@ -121,7 +121,7 @@ module Tuktuk | |
| 121 121 | 
             
                      begin
         | 
| 122 122 | 
             
                        response = send_now(mail, server, to)
         | 
| 123 123 | 
             
                        break
         | 
| 124 | 
            -
                      rescue => e
         | 
| 124 | 
            +
                      rescue Exception => e # explicitly rescue Exception so we catch Timeout:Error's too
         | 
| 125 125 | 
             
                        last_error = e
         | 
| 126 126 | 
             
                      end
         | 
| 127 127 | 
             
                    end
         | 
| @@ -262,6 +262,7 @@ module Tuktuk | |
| 262 262 | 
             
                    logger.warn "Debug option enabled. Connecting to localhost!"
         | 
| 263 263 | 
             
                    server = 'localhost'
         | 
| 264 264 | 
             
                  end
         | 
| 265 | 
            +
             | 
| 265 266 | 
             
                  smtp = Net::SMTP.new(server, nil)
         | 
| 266 267 | 
             
                  smtp.enable_starttls_auto(context)
         | 
| 267 268 | 
             
                  smtp.read_timeout = config[:read_timeout] if config[:read_timeout]
         | 
    
        data/lib/tuktuk/version.rb
    CHANGED
    
    
    
        data/spec/deliver_spec.rb
    CHANGED
    
    | @@ -2,212 +2,214 @@ require './lib/tuktuk/tuktuk' | |
| 2 2 | 
             
            require 'rspec/mocks'
         | 
| 3 3 |  | 
| 4 4 | 
             
            describe 'deliver' do
         | 
| 5 | 
            -
             | 
| 5 | 
            +
             | 
| 6 6 | 
             
            end
         | 
| 7 7 |  | 
| 8 8 | 
             
            describe 'deliver many' do
         | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 161 | 
            -
             | 
| 162 | 
            -
             | 
| 163 | 
            -
             | 
| 164 | 
            -
             | 
| 165 | 
            -
             | 
| 166 | 
            -
             | 
| 167 | 
            -
             | 
| 168 | 
            -
             | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
             | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              before(:each) do
         | 
| 11 | 
            +
                @mock_smtp = double('Net::SMTP')
         | 
| 12 | 
            +
                Net::SMTP.stub(:new).and_return(@mock_smtp)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              describe 'when no emails are passed' do
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                it 'raises' do
         | 
| 18 | 
            +
                  lambda do
         | 
| 19 | 
            +
                    Tuktuk.deliver_many []
         | 
| 20 | 
            +
                  end.should raise_error
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              describe 'when one email contains multiple addresses' do
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                it 'raises' do
         | 
| 28 | 
            +
                  lambda do
         | 
| 29 | 
            +
                    Tuktuk.deliver_many [ email, email(:to => 'one@user.com, two@user.com')]
         | 
| 30 | 
            +
                  end.should raise_error
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              describe 'when emails are valid' do
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                it 'groups them by domain' do
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                describe 'and max_workers is 0' do
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  it 'does not start any threads' do
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                describe 'and max_workers is >0' do
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  it 'does not spawn any more threads than the max allowed' do
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                describe 'and max workers is auto' do
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  it 'spawns a new thread for each domain' do
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                describe 'when delivering to domain' do
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  before do
         | 
| 68 | 
            +
                    @mock_smtp.stub(:start).and_yield('foo')
         | 
| 69 | 
            +
                    @emails = [email, email, email]
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                    @success = double('Net::SMTP::Response')
         | 
| 72 | 
            +
                    @soft_email_bounce  = Tuktuk::SoftBounce.new('503 Sender already specified')
         | 
| 73 | 
            +
                    @hard_email_bounce  = Tuktuk::HardBounce.new('505 Mailbox not found')
         | 
| 74 | 
            +
                    @soft_server_bounce = Tuktuk::SoftBounce.new('Be back in a sec')
         | 
| 75 | 
            +
                    @hard_server_bounce = Tuktuk::HardBounce.new('No MX records found.')
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                  describe 'when domain exists' do
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                    before do
         | 
| 81 | 
            +
                      @domain = 'domain.com'
         | 
| 82 | 
            +
                    end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    describe 'and has valid MX servers' do
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                      before do
         | 
| 87 | 
            +
                        @servers = ['mx1.domain.com', 'mx2.domain.com', 'mx3.domain.com']
         | 
| 88 | 
            +
                        Tuktuk.stub(:smtp_servers_for_domain).and_return(@servers)
         | 
| 89 | 
            +
                      end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                      it 'starts by delivering to first one' do
         | 
| 92 | 
            +
                        Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', [1]).and_return([[1,'ok']])
         | 
| 93 | 
            +
                        Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', [1])
         | 
| 94 | 
            +
                      end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                      describe 'and first server processes all our mail' do
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                        describe 'and all mail goes through' do
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                          before do
         | 
| 101 | 
            +
                            @responses = []
         | 
| 102 | 
            +
                            @emails.each { |e| @responses.push [e, @success] }
         | 
| 103 | 
            +
                          end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                          it 'does not try to connect to second server' do
         | 
| 106 | 
            +
                            Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', @emails).and_return(@responses)
         | 
| 107 | 
            +
                            Tuktuk.should_not_receive(:send_many_now).with('mx2.domain.com')
         | 
| 108 | 
            +
                            Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
         | 
| 109 | 
            +
                          end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                        end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                        describe 'and all emails were hard failures (bounces)' do
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                          before do
         | 
| 116 | 
            +
                            @responses = []
         | 
| 117 | 
            +
                            @emails.each { |e| @responses.push [e, @hard_email_bounce] }
         | 
| 118 | 
            +
                          end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                          it 'does not try to connect to second server' do
         | 
| 121 | 
            +
                            Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', @emails).and_return(@responses)
         | 
| 122 | 
            +
                            Tuktuk.should_not_receive(:send_many_now).with('mx2.domain.com')
         | 
| 123 | 
            +
                            Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
         | 
| 124 | 
            +
                          end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                        end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                      end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                      describe 'and first server is down' do
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                        before do
         | 
| 133 | 
            +
                          @responses = []
         | 
| 134 | 
            +
                          @emails.each { |e| @responses.push [e, @success] }
         | 
| 135 | 
            +
                        end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                        it 'does not raise error' do
         | 
| 138 | 
            +
                          Tuktuk.should_receive(:init_connection).once.with('mx1.domain.com').and_raise('Unable to connect.')
         | 
| 139 | 
            +
                          Tuktuk.should_receive(:init_connection).once.with('mx2.domain.com').and_raise('Unable to connect.')
         | 
| 140 | 
            +
                          Tuktuk.should_receive(:init_connection).once.with('mx3.domain.com').and_raise('Unable to connect.')
         | 
| 141 | 
            +
                          # Tuktuk.should_receive(:init_connection).once.and_raise('Unable to connect.')
         | 
| 142 | 
            +
                          expect do
         | 
| 143 | 
            +
                            Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
         | 
| 144 | 
            +
                          end.not_to raise_error # (RuntimeError)
         | 
| 145 | 
            +
                        end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                        it 'returns empty responses' do
         | 
| 148 | 
            +
                          Tuktuk.should_receive(:init_connection).once.with('mx1.domain.com').and_raise('Unable to connect.')
         | 
| 149 | 
            +
                          responses = Tuktuk.send(:send_many_now, 'mx1.domain.com', @emails)
         | 
| 150 | 
            +
                          responses.should be_empty
         | 
| 151 | 
            +
                        end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                        it 'tries to connect to second server' do
         | 
| 154 | 
            +
                          Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', @emails).and_return([])
         | 
| 155 | 
            +
                          Tuktuk.should_receive(:send_many_now).once.with('mx2.domain.com', @emails).and_return(@responses)
         | 
| 156 | 
            +
                          Tuktuk.should_not_receive(:send_many_now).with('mx3.domain.com')
         | 
| 157 | 
            +
                          Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
         | 
| 158 | 
            +
                        end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                      end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                      describe 'and first server receives only one email' do
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                        before do
         | 
| 165 | 
            +
                          @first = [@emails[0], @success]
         | 
| 166 | 
            +
                          @last_two = [[@emails[1], @success], [@emails[2], @soft_email_bounce]]
         | 
| 167 | 
            +
                        end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                        it 'does not try to send that same email to second server' do
         | 
| 170 | 
            +
                          Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', @emails).and_return([@first])
         | 
| 171 | 
            +
                          last_two_emails = @emails.last(2)
         | 
| 172 | 
            +
                          last_two_emails.include?(@emails.first).should be_false
         | 
| 173 | 
            +
                          Tuktuk.should_receive(:send_many_now).once.with('mx2.domain.com', last_two_emails).and_return(@last_two)
         | 
| 174 | 
            +
                          Tuktuk.should_not_receive(:send_many_now).with('mx3.domain.com')
         | 
| 175 | 
            +
                          Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
         | 
| 176 | 
            +
                        end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                        describe 'and other servers are down' do
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                          before do
         | 
| 181 | 
            +
                            # TODO: for some reason the :init_connection on line  138 is affecting this
         | 
| 182 | 
            +
                            # this test should pass when running on its own
         | 
| 183 | 
            +
                            # Tuktuk.should_receive(:init_connection).once.with('mx1.domain.com').and_return(@mock_smtp)
         | 
| 184 | 
            +
                            # Tuktuk.should_receive(:init_connection).once.with('mx2.domain.com').and_raise('Unable to connect.')
         | 
| 185 | 
            +
                            # Tuktuk.should_receive(:init_connection).once.with('mx3.domain.com').and_raise('Unable to connect.')
         | 
| 186 | 
            +
                          end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                          it 'should not mark first email as bounced' do
         | 
| 189 | 
            +
                            Tuktuk.should_receive(:send_many_now).and_return([@first], [], [])
         | 
| 190 | 
            +
                            responses = Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
         | 
| 191 | 
            +
                            responses[1][0].should be_a(Tuktuk::Bounce) if responses[1]
         | 
| 192 | 
            +
                            responses[0][0].should_not be_a(Tuktuk::Bounce)
         | 
| 193 | 
            +
                          end
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                        end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                      end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                    end
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                  end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                end
         | 
| 204 | 
            +
             | 
| 205 | 
            +
              end
         | 
| 206 | 
            +
             | 
| 207 | 
            +
              def email(attrs = {})
         | 
| 208 | 
            +
                { :to => "user#{rand(1000)}@domain.com",
         | 
| 209 | 
            +
                  :from => 'me@company.com',
         | 
| 210 | 
            +
                  :subject => 'Test email',
         | 
| 211 | 
            +
                  :body => 'Hello world.'
         | 
| 212 | 
            +
                }.merge(attrs)
         | 
| 213 | 
            +
              end
         | 
| 214 | 
            +
             | 
| 215 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,92 +1,101 @@ | |
| 1 | 
            -
            --- !ruby/object:Gem::Specification
         | 
| 1 | 
            +
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: tuktuk
         | 
| 3 | 
            -
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
               | 
| 3 | 
            +
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            +
              prerelease: false
         | 
| 5 | 
            +
              segments: 
         | 
| 6 | 
            +
              - 0
         | 
| 7 | 
            +
              - 5
         | 
| 8 | 
            +
              - 4
         | 
| 9 | 
            +
              version: 0.5.4
         | 
| 5 10 | 
             
            platform: ruby
         | 
| 6 | 
            -
            authors:
         | 
| 7 | 
            -
            -  | 
| 11 | 
            +
            authors: 
         | 
| 12 | 
            +
            - "Tom\xC3\xA1s Pollak"
         | 
| 8 13 | 
             
            autorequire: 
         | 
| 9 14 | 
             
            bindir: bin
         | 
| 10 15 | 
             
            cert_chain: []
         | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 16 | 
            +
             | 
| 17 | 
            +
            date: 2015-04-08 00:00:00 -07:00
         | 
| 18 | 
            +
            default_executable: 
         | 
| 19 | 
            +
            dependencies: 
         | 
| 20 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 14 21 | 
             
              name: bundler
         | 
| 15 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            -
                requirements:
         | 
| 17 | 
            -
                - - '>='
         | 
| 18 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: 1.0.0
         | 
| 20 | 
            -
              type: :development
         | 
| 21 22 | 
             
              prerelease: false
         | 
| 22 | 
            -
               | 
| 23 | 
            -
                requirements:
         | 
| 24 | 
            -
                - -  | 
| 25 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 23 | 
            +
              requirement: &id001 !ruby/object:Gem::Requirement 
         | 
| 24 | 
            +
                requirements: 
         | 
| 25 | 
            +
                - - ">="
         | 
| 26 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 27 | 
            +
                    segments: 
         | 
| 28 | 
            +
                    - 1
         | 
| 29 | 
            +
                    - 0
         | 
| 30 | 
            +
                    - 0
         | 
| 26 31 | 
             
                    version: 1.0.0
         | 
| 27 | 
            -
             | 
| 32 | 
            +
              type: :development
         | 
| 33 | 
            +
              version_requirements: *id001
         | 
| 34 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 28 35 | 
             
              name: net-dns
         | 
| 29 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            -
                requirements:
         | 
| 31 | 
            -
                - - '='
         | 
| 32 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            -
                    version: 0.6.1
         | 
| 34 | 
            -
              type: :runtime
         | 
| 35 36 | 
             
              prerelease: false
         | 
| 36 | 
            -
               | 
| 37 | 
            -
                requirements:
         | 
| 38 | 
            -
                - -  | 
| 39 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 37 | 
            +
              requirement: &id002 !ruby/object:Gem::Requirement 
         | 
| 38 | 
            +
                requirements: 
         | 
| 39 | 
            +
                - - "="
         | 
| 40 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 41 | 
            +
                    segments: 
         | 
| 42 | 
            +
                    - 0
         | 
| 43 | 
            +
                    - 6
         | 
| 44 | 
            +
                    - 1
         | 
| 40 45 | 
             
                    version: 0.6.1
         | 
| 41 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            -
              name: mail
         | 
| 43 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            -
                requirements:
         | 
| 45 | 
            -
                - - ~>
         | 
| 46 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            -
                    version: '2.3'
         | 
| 48 46 | 
             
              type: :runtime
         | 
| 47 | 
            +
              version_requirements: *id002
         | 
| 48 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 49 | 
            +
              name: mail
         | 
| 49 50 | 
             
              prerelease: false
         | 
| 50 | 
            -
               | 
| 51 | 
            -
                requirements:
         | 
| 51 | 
            +
              requirement: &id003 !ruby/object:Gem::Requirement 
         | 
| 52 | 
            +
                requirements: 
         | 
| 52 53 | 
             
                - - ~>
         | 
| 53 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            -
                     | 
| 55 | 
            -
            -  | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
                requirements:
         | 
| 59 | 
            -
                - - ~>
         | 
| 60 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            -
                    version: 0.0.2
         | 
| 54 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 55 | 
            +
                    segments: 
         | 
| 56 | 
            +
                    - 2
         | 
| 57 | 
            +
                    - 3
         | 
| 58 | 
            +
                    version: "2.3"
         | 
| 62 59 | 
             
              type: :runtime
         | 
| 60 | 
            +
              version_requirements: *id003
         | 
| 61 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 62 | 
            +
              name: dkim
         | 
| 63 63 | 
             
              prerelease: false
         | 
| 64 | 
            -
               | 
| 65 | 
            -
                requirements:
         | 
| 64 | 
            +
              requirement: &id004 !ruby/object:Gem::Requirement 
         | 
| 65 | 
            +
                requirements: 
         | 
| 66 66 | 
             
                - - ~>
         | 
| 67 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 68 | 
            +
                    segments: 
         | 
| 69 | 
            +
                    - 0
         | 
| 70 | 
            +
                    - 0
         | 
| 71 | 
            +
                    - 2
         | 
| 68 72 | 
             
                    version: 0.0.2
         | 
| 69 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 70 | 
            -
              name: work_queue
         | 
| 71 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 | 
            -
                requirements:
         | 
| 73 | 
            -
                - - ~>
         | 
| 74 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 75 | 
            -
                    version: 2.5.0
         | 
| 76 73 | 
             
              type: :runtime
         | 
| 74 | 
            +
              version_requirements: *id004
         | 
| 75 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 76 | 
            +
              name: work_queue
         | 
| 77 77 | 
             
              prerelease: false
         | 
| 78 | 
            -
               | 
| 79 | 
            -
                requirements:
         | 
| 78 | 
            +
              requirement: &id005 !ruby/object:Gem::Requirement 
         | 
| 79 | 
            +
                requirements: 
         | 
| 80 80 | 
             
                - - ~>
         | 
| 81 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 81 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 82 | 
            +
                    segments: 
         | 
| 83 | 
            +
                    - 2
         | 
| 84 | 
            +
                    - 5
         | 
| 85 | 
            +
                    - 0
         | 
| 82 86 | 
             
                    version: 2.5.0
         | 
| 87 | 
            +
              type: :runtime
         | 
| 88 | 
            +
              version_requirements: *id005
         | 
| 83 89 | 
             
            description: Easy way of sending DKIM-signed emails from Ruby, no dependencies needed.
         | 
| 84 | 
            -
            email:
         | 
| 90 | 
            +
            email: 
         | 
| 85 91 | 
             
            - tomas@forkhq.com
         | 
| 86 92 | 
             
            executables: []
         | 
| 93 | 
            +
             | 
| 87 94 | 
             
            extensions: []
         | 
| 95 | 
            +
             | 
| 88 96 | 
             
            extra_rdoc_files: []
         | 
| 89 | 
            -
             | 
| 97 | 
            +
             | 
| 98 | 
            +
            files: 
         | 
| 90 99 | 
             
            - .gitignore
         | 
| 91 100 | 
             
            - Gemfile
         | 
| 92 101 | 
             
            - README.md
         | 
| @@ -101,27 +110,37 @@ files: | |
| 101 110 | 
             
            - lib/tuktuk/version.rb
         | 
| 102 111 | 
             
            - spec/deliver_spec.rb
         | 
| 103 112 | 
             
            - tuktuk.gemspec
         | 
| 113 | 
            +
            has_rdoc: true
         | 
| 104 114 | 
             
            homepage: https://github.com/tomas/tuktuk
         | 
| 105 115 | 
             
            licenses: []
         | 
| 106 | 
            -
             | 
| 116 | 
            +
             | 
| 107 117 | 
             
            post_install_message: 
         | 
| 108 118 | 
             
            rdoc_options: []
         | 
| 109 | 
            -
             | 
| 119 | 
            +
             | 
| 120 | 
            +
            require_paths: 
         | 
| 110 121 | 
             
            - lib
         | 
| 111 | 
            -
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 112 | 
            -
              requirements:
         | 
| 113 | 
            -
              - -  | 
| 114 | 
            -
                - !ruby/object:Gem::Version
         | 
| 115 | 
            -
                   | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 122 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         | 
| 123 | 
            +
              requirements: 
         | 
| 124 | 
            +
              - - ">="
         | 
| 125 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 126 | 
            +
                  segments: 
         | 
| 127 | 
            +
                  - 0
         | 
| 128 | 
            +
                  version: "0"
         | 
| 129 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 130 | 
            +
              requirements: 
         | 
| 131 | 
            +
              - - ">="
         | 
| 132 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 133 | 
            +
                  segments: 
         | 
| 134 | 
            +
                  - 1
         | 
| 135 | 
            +
                  - 3
         | 
| 136 | 
            +
                  - 6
         | 
| 120 137 | 
             
                  version: 1.3.6
         | 
| 121 138 | 
             
            requirements: []
         | 
| 139 | 
            +
             | 
| 122 140 | 
             
            rubyforge_project: tuktuk
         | 
| 123 | 
            -
            rubygems_version:  | 
| 141 | 
            +
            rubygems_version: 1.3.6
         | 
| 124 142 | 
             
            signing_key: 
         | 
| 125 | 
            -
            specification_version:  | 
| 143 | 
            +
            specification_version: 3
         | 
| 126 144 | 
             
            summary: SMTP client for Ruby with DKIM support.
         | 
| 127 145 | 
             
            test_files: []
         | 
| 146 | 
            +
             | 
    
        checksums.yaml
    DELETED
    
    | @@ -1,7 +0,0 @@ | |
| 1 | 
            -
            ---
         | 
| 2 | 
            -
            SHA1:
         | 
| 3 | 
            -
              metadata.gz: 2d959f61646d7f24739699b467abdd6d3b11a1aa
         | 
| 4 | 
            -
              data.tar.gz: 1fd5e0c66ee7aabd178810a0877964913898d5eb
         | 
| 5 | 
            -
            SHA512:
         | 
| 6 | 
            -
              metadata.gz: c5a744fbeab5b4a3316b822d898052c151f495193918ecc029505ff1fd71c53ba3fc55619a9f74f05ed179f8fec89d62303c80c627fb59b80a554d7f5c02c93b
         | 
| 7 | 
            -
              data.tar.gz: f705920b165a4b872003373dc838000a05f5704879515211e2160aaa339c194c76a35b5c187006d78e499f2586679b4e3c2da7b3bfa42d85020df2550aec6b53
         |