require 'mail' module Mail # @private class Message # @private include Sinatra::Templates include Padrino::Rendering if defined?(Padrino::Rendering) include Padrino::Helpers::RenderHelpers if defined? Padrino::Helpers::RenderHelpers attr_reader :template_cache attr_accessor :mailer_name, :message_name 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 settings.views = File.expand_path("./mailers") settings.reload_templates = true end initialize_template_settings! initialize_without_app(*args, &block) end alias_method :initialize_without_app, :initialize alias_method :initialize, :initialize_with_app ## # Setup like in Sinatra/Padrino apps content_type and template lookup. # # @example # # This add an 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. # # @example # text_part "Some text" # text_part { render('multipart/basic.text') } # def text_part(value = nil, &block) add_resolved_part(:variable => :text_part, :value => value, :content_type => 'text/plain', &block) 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. # # @example # html_part "Some Html text" # html_part { render('multipart/basic.html') } # def html_part(value = nil, &block) add_resolved_part(:variable => :html_part, :value => value, :content_type => 'text/html', &block) end def add_resolved_part(attributes = {}, &block) variable, value, content_type = attributes.values_at(:variable, :value, :content_type) if block_given? || value instance_variable_set "@#{variable}", self.part(:content_type => content_type, :body => value, :part_block => block) add_multipart_alternate_header if self.send(variable) else instance_variable_get("@#{variable}") || find_first_mime_type(content_type) end end ## # Allows you to add a part in block form to an existing mail message object. # # @example # 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) new_part end def do_delivery_with_logging logger.debug "Sending email to: #{destinations.join(" ")}" encoded.each_line { |line| logger << (" " + line.strip) } if logger.debug? do_delivery_without_logging end if Padrino.respond_to?(:logger) alias_method :do_delivery_without_logging, :do_delivery alias_method :do_delivery, :do_delivery_with_logging end ## # Sinatra and Padrino compatibility. # def settings self.class end ## # Sinatra almost compatibility. # def self.set(name, value) self.class.instance_eval{ define_method(name) { value } unless method_defined?(:erb) } end ## # 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 compatibility 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 ## # Check if we can log. # def self.logging? @_logging end def self.logging=(value) @_logging = value 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 represent 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 :content_type_without_symbol, :content_type alias_method :content_type, :content_type_with_symbol private ## # Defines the render for the mailer utilizing the padrino 'rendering' module # def render(engine=nil, data=nil, options={}, locals={}, &block) locals = @_locals || {} if !options[:locals] && locals.empty? @template_cache.clear if settings.reload_templates? engine ||= message_name if mailer_name && !engine.to_s.index('/') settings.views += "/#{mailer_name}" engine = engine.to_s.sub(%r{^#{mailer_name}/}, '') end provides.each do |format| part do |p| p.content_type(format) p.send(:render, engine, data, options, locals, &block) add_multipart_alternate_header if html_part || provides.include?(:html) end end self.body = super(engine, data, options, locals, &block) if provides.empty? end alias_method :original_partial, :partial if instance_methods.include?(:partial) def partial(template, options={}, &block) raise "gem 'padrino-helpers' is required to render partials" unless respond_to?(:original_partial) self.body = original_partial(template, options, &block) end ## # Register all special template configurations Padrino has to our fake settings object. # def initialize_template_settings! Padrino::Rendering.engine_configurations.each do |name, value| settings.class.instance_eval { define_method(name) { value } } end end end end