module Mail #:nodoc:
class Message #:nodoc:
include Sinatra::Templates
include Padrino::Rendering if defined?(Padrino::Rendering)
attr_reader :template_cache
def initialize_with_app(*args, &block)
@template_cache = Tilt::Cache.new
# Check if we have an app passed into initialize
if args[0].respond_to?(:views) && args[0].respond_to?(:reload_templates?)
app = args.shift
settings.views = File.join(app.views, 'mailers')
settings.reload_templates = app.reload_templates?
else
# Set a default view for this class
settings.views = File.expand_path("./mailers")
settings.reload_templates = true
end
# Run the original initialize
initialize_without_app(*args, &block)
end
alias_method_chain :initialize, :app
##
# Setup like in Sinatra/Padrino apps content_type and template lookup.
#
# ==== Examples
#
# # This add a email plain part if a template called bar.plain.* is found
# # and a html part if a template called bar.html.* is found
# email do
# from 'from@email.com'
# to 'to@email.com'
# subject 'Welcome here'
# provides :plain, :html
# render "foo/bar"
# end
#
def provides(*formats)
if formats.empty?
@_provides ||= []
else
@_provides = formats.flatten.compact
end
end
##
# Helper to add a text part to a multipart/alternative email. If this and
# html_part are both defined in a message, then it will be a multipart/alternative
# message and set itself that way.
#
# ==== Examples
#
# text_part "Some text"
# text_part { render('multipart/basic.text') }
#
def text_part(value=nil, &block)
if block_given? || value
@text_part = self.part(:content_type => "text/plain", :body => value, :part_block => block)
add_multipart_alternate_header unless html_part.blank?
else
@text_part || find_first_mime_type("text/plain")
end
end
##
# Helper to add a html part to a multipart/alternative email. If this and
# text_part are both defined in a message, then it will be a multipart/alternative
# message and set itself that way.
#
# ==== Examples
#
# html_part "Some Html text"
# html_part { render('multipart/basic.html') }
#
def html_part(value=nil, &block)
if block_given? || value
@html_part = self.part(:content_type => "text/html", :body => value, :part_block => block)
add_multipart_alternate_header unless text_part.blank?
else
@html_part || find_first_mime_type("text/html")
end
end
##
# Allows you to add a part in block form to an existing mail message object
#
# ==== Examples
#
# mail = Mail.new do
# part :content_type => "multipart/alternative", :content_disposition => "inline" do |p|
# p.part :content_type => "text/plain", :body => "test text\nline #2"
# p.part :content_type => "text/html", :body => "test HTML
\nline #2"
# end
# end
#
def part(params = {}, &block)
part_block = params.delete(:part_block)
new_part = Mail::Part.new(params)
new_part.settings.views = settings.views
new_part.settings.reload_templates = settings.reload_templates?
new_part.instance_eval(&part_block) if part_block
yield new_part if block_given?
add_part(new_part)
end
def do_delivery_with_logging
logger.debug "Sending email to: #{destinations.join(" ")}"
encoded.to_lf.split("\n").each { |line| logger << (" " + line) } if logger.debug?
do_delivery_without_logging
end
alias_method_chain :do_delivery, :logging if Padrino.respond_to?(:logger)
##
# Sinatra and Padrino compatibility
#
def settings
self.class
end
alias :options :settings
##
# Sets the message defined template path to the given view path
#
def views(value)
settings.views = value
end
##
# Sets the local variables available within the message template
#
def locals(value)
@_locals = value
end
##
# Returns the templates for this message
#
def self.templates
@_templates ||= {}
end
##
# Sets the message defined template path to the given view path
#
def self.views=(value)
@_views = value
end
##
# Returns the template view path defined for this message
#
def self.views
@_views
end
##
# Modify whether templates should be reloaded (for development)
#
def self.reload_templates=(value)
@_reload_templates = value
end
##
# Returns true if the templates will be reloaded; false otherwise.
#
def self.reload_templates?
@_reload_templates
end
##
# Return the path of this file, only for compatiblity with sinatra rendering methods
#
def self.caller_locations
[[File.dirname(__FILE__), 1]]
end
##
# Return the default encoding
#
def self.default_encoding
"utf-8"
end
##
# Modify the default attributes for this message (if not explicitly specified)
#
def defaults=(attributes)
@_defaults = attributes
@_defaults.each_pair { |k, v| default(k.to_sym, v) } if @_defaults.is_a?(Hash)
end
# Shortcut for delivery_method with smarter smtp overwrites
def via(method = nil, settings = {})
if method.nil?
delivery_method
elsif method.to_sym != :smtp
delivery_method(method, settings)
elsif method.to_sym == :smtp && (settings.any? || delivery_method.class.to_s !~ /smtp/i)
delivery_method(method, settings)
end
end
##
# If the value is empty return a symbol that rappresent the content type so:
#
# "text/plain" => :plain
#
# See Padrino::Mailer::Mime for more usage informations.
#
def content_type_with_symbol(value=nil)
value = Padrino::Mailer::Mime::MIME_TYPES.find { |k,v| v == value }[0] rescue value if value.is_a?(Symbol)
mime = content_type_without_symbol(value)
Padrino::Mailer::Mime.mime_type(mime)
end
alias_method_chain :content_type, :symbol
private
# Defines the render for the mailer utilizing the padrino 'rendering' module
def render(engine, data=nil, options={}, locals={}, &block)
locals = @_locals if options[:locals].blank? && locals.blank?
# Reload templates
@template_cache.clear if settings.reload_templates?
# Setup provides
provides.each do |format|
part do |p|
p.content_type(format)
p.send(:render, engine, data, options, locals, &block)
add_multipart_alternate_header unless html_part.blank?
end
end
# Setup the body if we don't have provides
self.body = super(engine, data, options, locals, &block) if provides.empty?
end
end # Message
end # Mail