RosettaCodeData/Task/Send-email/Ruby/send-email.rb

78 lines
2.1 KiB
Ruby

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?
# just specify the body
@msg.body = body
else
# attach attachments, including the body
@msg.body = "This is a multi-part message in MIME format.\n"
msg_body = TMail::Mail.new
msg_body.body = body
msg_body.set_content_type("text","plain", {:charset => "ISO-8859-1"})
@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("attachment", {:filename => file})
attach.set_content_type(mime_type.media_type, mime_type.sub_type, {:name=>file})
attach
end
# instance method to send an Email object
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
# class method to construct an Email object and send it
def self.send(*args)
self.new(*args).send
end
end
Email.send(
'sender@sender.invalid',
%w{ recip1@recipient.invalid recip2@example.com },
'the subject',
"the body\nhas lines",
{
:attachments => %w{ file1 file2 file3 },
:server => 'mail.example.com',
:helo => 'sender.invalid',
:username => 'user',
:password => 'secret'
}
)