require 'base64'
require 'net/smtp'
require 'tmail'
require 'mime/types'

class Email
  def initialize(from, to, subject, body, options={})
    @opts = {:attachments => [], :server => 'localhost'}.update(options)
    @msg = TMail::Mail.new
    @msg.from    = from
    @msg.to      = to
    @msg.subject = subject
    @msg.cc      = @opts[:cc]  if @opts[:cc]
    @msg.bcc     = @opts[:bcc] if @opts[:bcc]

    if @opts[:attachments].empty?
      
      @msg.body = body
    else
      
      @msg.body = 

      msg_body = TMail::Mail.new
      msg_body.body = body
      msg_body.set_content_type(,, {:charset => })
      @msg.parts << msg_body

      octet_stream = MIME::Types['application/octet-stream'].first

      @opts[:attachments].select {|file| File.readable?(file)}.each do |file|
        mime_type = MIME::Types.type_for(file).first || octet_stream
        @msg.parts << create_attachment(file, mime_type)
      end
    end
  end
  attr_reader :msg

  def create_attachment(file, mime_type)
    attach = TMail::Mail.new
    if mime_type.binary?
      attach.body = Base64.encode64(File.read(file))
      attach.transfer_encoding = 'base64'
    else
      attach.body = File.read(file)
    end
    attach.set_disposition(, {:filename => file})
    attach.set_content_type(mime_type.media_type, mime_type.sub_type, {:name=>file})
    attach
  end

  
  def send
    args = @opts.values_at(:server, :port, :helo, :username, :password, :authtype)
    Net::SMTP.start(*args) do |smtp|
      smtp.send_message(@msg.to_s, @msg.from[0], @msg.to)
    end
  end

  
  def self.send(*args)
    self.new(*args).send
  end
end

Email.send(
  'sender@sender.invalid',
  %w{ recip1@recipient.invalid recip2@example.com },
  'the subject',
  ,
  {
    :attachments => %w{ file1 file2 file3 },
    :server => 'mail.example.com',
    :helo => 'sender.invalid',
    :username => 'user',
    :password => 'secret'
  }
)