Tuktuk - SMTP client for Ruby ============================= Unlike famous ol' Pony gem (which is friggin' awesome by the way), Tuktuk does not rely on `sendmail` or a separate SMTP server in order to deliver email. Tuktuk looks up the MX servers of the destination address and connects directly using Net::SMTP. This way you don't need to install Exim or Postfix and you can actually handle response status codes -- like bounces, 5xx -- within your application. Plus, it supports DKIM out of the box. Delivering mail --------------- ``` ruby require 'tuktuk' message = { :from => 'you@username.com', :to => 'user@yoursite.com', :body => 'Hello there', :subject => 'Hiya' } response, email = Tuktuk.deliver(message) ``` The `response` is either a Net::SMTP::Response object, or a Bounce exception (HardBounce or SoftBounce, depending on the cause). `email` is a [mail](https://github.com/mikel/mail) object. So, to handle bounces you'd do: ``` ruby [...] response, email = Tuktuk.deliver(message) if response.is_a?(Tuktuk::Bounce) puts 'Email bounced. Type: ' + response.class.name # => HardBounce or SoftBounce else puts 'Email delivered!' end ``` Delivering multiple ------------------- With Tuktuk, you can also deliver multiple messages at once. Depending on the `max_workers` config parameter, Tuktuk will either connect sequentially to the target domain's MX servers, or do it in parallel by spawning threads. Tuktuk will try to send all emails targeted for a specific domain on the same SMTP session. If a MX server is not responding -- or times out in the middle --, Tuktuk will try to deliver the remaining messages to next MX server, and so on. To #deliver_many, you need to pass an array of messages, and you'll receive an array of [response, email] elements, just as above. ``` ruby messages = [ { ... }, { ... }, { ... }, { ... } ] # array of messages result = Tuktuk.deliver_many(messages) result.each do |response, email| if response.is_a?(Tuktuk::Bounce) puts 'Email bounced. Type: ' + response.class.name else puts 'Email delivered!' end end ``` Options & DKIM -------------- Now, if you want to enable DKIM (and you should): ``` ruby require 'tuktuk' Tuktuk.options = { :dkim => { :domain => 'yoursite.com', :selector => 'mailer', :private_key => IO.read('ssl/yoursite.com.key') } } message = { ... } response, email = Tuktuk.deliver(message) ``` For DKIM to work, you need to set up a TXT record in your domain's DNS. All available options, with their defaults: ``` ruby Tuktuk.options = { :log_to => nil, # e.g. log/mailer.log :helo_domain => nil, # your server's domain goes here :max_workers => 0, # controls number of threads for delivering_many emails (read below) :open_timeout => 20, # max seconds to wait for opening a connection :read_timeout => 20, # 20 seconds to wait for a response, once connected :verify_ssl => true, # whether to skip SSL keys verification or not :debug => false, # connects and delivers email to localhost, instead of real target server. CAUTION! :dkim => { ... } } ``` You can set the `max_threads` option to `auto`, which will spawn the necessary threads to connect in paralell to all target MX servers when delivering multiple messages. When set to `0`, these batches will be delivered sequentially. In other words, if you have three emails targeted to Gmail users and two for Hotmail users, using `auto` Tuktuk will spawn two threads and connect to both servers at once. Using `0` will have email deliveried to one host and then the other. Using with Rails ---------------- Tuktuk comes with ActionMailer support out of the box. In your environment.rb or environments/{env}.rb: ``` ruby require 'tuktuk/rails' [...] config.action_mailer.delivery_method = :tuktuk ``` Since Tuktuk delivers email directly to the user's MX servers, it's probably a good idea to set `config.action_mailer.raise_delivery_errors` to true. That way you can actually know if an email couldn't make it to its destination. When used with ActionMailer, you can pass options using ActionMailer's interface, like this: ``` ruby config.action_mailer.delivery_method = :tuktuk config.action_mailer.tuktuk_settings = { :log_to => 'log/mailer.log', # when not set, Tuktuk will use Rails.logger :dkim => { :domain => 'yoursite.com', :selector => 'mailer', :private_key => IO.read('ssl/yoursite.com.key') } } ``` -- (c) 2013 Fork Limited. MIT license.