Skip to content

Commit

Permalink
Add mustache templating for email body (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
jstoja authored and jsvd committed Jan 8, 2018
1 parent 80cd0d3 commit a777e19
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 4 deletions.
26 changes: 22 additions & 4 deletions lib/logstash/outputs/email.rb
Expand Up @@ -80,6 +80,9 @@ class LogStash::Outputs::Email < LogStash::Outputs::Base
# Body for the email - plain text only.
config :body, :validate => :string, :default => ""

# Email template file to be used - as mustache template.
config :template_file, :validate => :path

# HTML Body for the email, which may contain HTML markup.
config :htmlbody, :validate => :string, :default => ""

Expand All @@ -93,6 +96,7 @@ class LogStash::Outputs::Email < LogStash::Outputs::Base
public
def register
require "mail"
require "mustache"

options = {
:address => @address,
Expand All @@ -118,6 +122,7 @@ def register
delivery_method :@via, options
end
end # @via tests
@htmlTemplate = File.open(@template_file, "r").read unless @template_file.nil?
@logger.debug("Email Output Registered!", :config => options, :via => @via)
end # def register

Expand All @@ -129,6 +134,7 @@ def receive(event)
formatedSubject = event.sprintf(@subject)
formattedBody = event.sprintf(@body)
formattedHtmlBody = event.sprintf(@htmlbody)

mail = Mail.new
mail.from = event.sprintf(@from)
mail.to = event.sprintf(@to)
Expand All @@ -137,18 +143,30 @@ def receive(event)
end
mail.cc = event.sprintf(@cc)
mail.subject = formatedSubject
if @htmlbody.empty?

if @htmlbody.empty? and @template_file.nil?
formattedBody.gsub!(/\\n/, "\n") # Take new line in the email
mail.body = formattedBody
else
# This handles multipart emails
# cf: https://github.com/mikel/mail/#writing-and-sending-a-multipartalternative-html-and-text-email
mail.text_part = Mail::Part.new do
content_type "text/plain; charset=UTF-8"
formattedBody.gsub!(/\\n/, "\n") # Take new line in the email
body formattedBody
end
mail.html_part = Mail::Part.new do
content_type "text/html; charset=UTF-8"
body formattedHtmlBody

if @template_file.nil?
mail.html_part = Mail::Part.new do
content_type "text/html; charset=UTF-8"
body formattedHtmlBody
end
else
templatedHtmlBody = Mustache.render(@htmlTemplate, event.to_hash)
mail.html_part = Mail::Part.new do
content_type "text/html; charset=UTF-8"
body templatedHtmlBody
end
end
end
@attachments.each do |fileLocation|
Expand Down
2 changes: 2 additions & 0 deletions logstash-output-email.gemspec
Expand Up @@ -26,6 +26,8 @@ Gem::Specification.new do |s|
# mime-types >= 3 require ruby 2.0 support
s.add_runtime_dependency 'mime-types', '< 3'

s.add_runtime_dependency 'mustache', '>= 0.99.8'

s.add_development_dependency 'logstash-devutils'
s.add_development_dependency 'rumbster'
s.add_development_dependency 'logstash-input-generator'
Expand Down
1 change: 1 addition & 0 deletions spec/fixtures/template.mustache
@@ -0,0 +1 @@
<h1>{{message}}</h1>
15 changes: 15 additions & 0 deletions spec/outputs/email_spec.rb
Expand Up @@ -89,5 +89,20 @@

end
end

context "mustache template for email body" do
it "uses the template file" do
subject = plugin.new("to" => "me@host",
"subject" => "Hello World",
"template_file" => File.dirname(__FILE__) + "/../fixtures/template.mustache",
"port" => port)
subject.register
subject.receive(LogStash::Event.new("message" => "hello"))

expect(message_observer.messages.size).to eq(1)
expect(message_observer.messages[0].subject).to eq("Hello World")
expect(message_observer.messages[0].body.decoded).to eq(craft_multi_part_email('', '<h1>hello</h1>', message_observer.messages[0].content_type))
end
end
end
end
14 changes: 14 additions & 0 deletions spec/spec_helper.rb
Expand Up @@ -12,3 +12,17 @@ def filter(event)
filter_matched(event)
end
end

def craft_multi_part_email(body, htmlbody, content_type)
charset = "charset=UTF-8"
content_encoding = "Content-Transfer-Encoding: 7bit"

# Have to get the generated part of the header, eg:
# --==_mimepart_5a462a1fda04b_efe7d032127
mimetype = content_type.split('; ')[1][10..-2]

plain_header = "\n--#{mimetype}\nContent-Type: text/plain;\n #{charset}\n#{content_encoding}\n\n"
html_header = "\n--#{mimetype}\nContent-Type: text/html;\n #{charset}\n#{content_encoding}\n\n"

"#{plain_header}#{body}#{html_header}#{htmlbody}\n\n--#{mimetype}--\n"
end

0 comments on commit a777e19

Please sign in to comment.