logstash-output-email 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MGExYjgwYzBlYTE4OGRjY2I1YjQ0MzdkZjNjZjliNWEwNDM4OTcxZg==
5
+ data.tar.gz: !binary |-
6
+ OTQ5MWUwNjhjNzNjMDQ5OTk5YzAyOWE4MzRkMzIwNWJiYTJmYzEwNQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NzRiYmFjMjM5MjliYzVmZDQwNzQ3Mjk0NDBlMjg3ZGJkZGY4YjkwZDQ2Zjkw
10
+ MDc1OGQ2Mzc4N2U4NTM0ODVlMGQ5MTQzMjE2ZDc1NTM4NWIwYThjMjU4OWUw
11
+ NGM1YmNmYTVmM2U1ZjVlYTIwYzk1ZmI4ZjY3YTJjODQyMjg3YTA=
12
+ data.tar.gz: !binary |-
13
+ MGE4Y2U3ZjM2M2QyNzIxNDcxYWUwNmFlNThlMjZlNGEzZDA2M2Q4ZTMyMzQw
14
+ MTljZmMzYzJmZDA5Y2M4ZjRiY2U4MzIzYWM5YjNlNThkZDM4NGFlNWY3Nzk2
15
+ MTc2ZTRlYThhYjU2MjhjNjllZTcxMmI1MDQ3ODAzZjkxNGVkZDg=
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ Gemfile.lock
3
+ .bundle
4
+ vendor
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+ gem 'rake'
3
+ gem 'gem_publisher'
4
+ gem 'archive-tar-minitar'
@@ -0,0 +1,6 @@
1
+ @files=[]
2
+
3
+ task :default do
4
+ system("rake -T")
5
+ end
6
+
@@ -0,0 +1,303 @@
1
+ # encoding: utf-8
2
+ require "logstash/outputs/base"
3
+ require "logstash/namespace"
4
+
5
+ # Send email when an output is received. Alternatively, you may include or
6
+ # exclude the email output execution using conditionals.
7
+ class LogStash::Outputs::Email < LogStash::Outputs::Base
8
+
9
+ config_name "email"
10
+ milestone 1
11
+
12
+ # This setting is deprecated in favor of Logstash's "conditionals" feature
13
+ # If you were using this setting previously, please use conditionals instead.
14
+ #
15
+ # If you need help converting your older 'match' setting to a conditional,
16
+ # I welcome you to join the #logstash irc channel on freenode or to email
17
+ # the logstash-users@googlegroups.com mailling list and ask for help! :)
18
+ config :match, :validate => :hash, :deprecated => true
19
+
20
+ # The fully-qualified email address to send the email to.
21
+ #
22
+ # This field also accepts a comma-separated string of addresses, for example:
23
+ # "me@host.com, you@host.com"
24
+ #
25
+ # You can also use dynamic fields from the event with the %{fieldname} syntax.
26
+ config :to, :validate => :string, :required => true
27
+
28
+ # The fully-qualified email address for the From: field in the email.
29
+ config :from, :validate => :string, :default => "logstash.alert@nowhere.com"
30
+
31
+ # The fully qualified email address for the Reply-To: field.
32
+ config :replyto, :validate => :string
33
+
34
+ # The fully-qualified email address(es) to include as cc: address(es).
35
+ #
36
+ # This field also accepts a comma-separated string of addresses, for example:
37
+ # "me@host.com, you@host.com"
38
+ config :cc, :validate => :string
39
+
40
+ # How Logstash should send the email, either via SMTP or by invoking sendmail.
41
+ config :via, :validate => :string, :default => "smtp"
42
+
43
+ # Specify the options to use:
44
+ #
45
+ # Via SMTP: smtpIporHost, port, domain, userName, password, authenticationType, starttls
46
+ #
47
+ # Via sendmail: location, arguments
48
+ #
49
+ # If you do not specify any `options`, you will get the following equivalent code set in
50
+ # every new mail object:
51
+ #
52
+ # Mail.defaults do
53
+ # delivery_method :smtp, { :smtpIporHost => "localhost",
54
+ # :port => 25,
55
+ # :domain => 'localhost.localdomain',
56
+ # :userName => nil,
57
+ # :password => nil,
58
+ # :authenticationType => nil,(plain, login and cram_md5)
59
+ # :starttls => true }
60
+ #
61
+ # retriever_method :pop3, { :address => "localhost",
62
+ # :port => 995,
63
+ # :user_name => nil,
64
+ # :password => nil,
65
+ # :enable_ssl => true }
66
+ #
67
+ # Mail.delivery_method.new #=> Mail::SMTP instance
68
+ # Mail.retriever_method.new #=> Mail::POP3 instance
69
+ # end
70
+ #
71
+ # Each mail object inherits the defaults set in Mail.delivery_method. However, on
72
+ # a per email basis, you can override the method:
73
+ #
74
+ # mail.delivery_method :sendmail
75
+ #
76
+ # Or you can override the method and pass in settings:
77
+ #
78
+ # mail.delivery_method :sendmail, { :address => 'some.host' }
79
+ #
80
+ # You can also just modify the settings:
81
+ #
82
+ # mail.delivery_settings = { :address => 'some.host' }
83
+ #
84
+ # The hash you supply is just merged against the defaults with "merge!" and the result
85
+ # assigned to the mail object. For instance, the above example will change only the
86
+ # `:address` value of the global `smtp_settings` to be 'some.host', retaining all other values.
87
+ config :options, :validate => :hash, :default => {}
88
+
89
+ # Subject: for the email.
90
+ config :subject, :validate => :string, :default => ""
91
+
92
+ # Body for the email - plain text only.
93
+ config :body, :validate => :string, :default => ""
94
+
95
+ # HTML Body for the email, which may contain HTML markup.
96
+ config :htmlbody, :validate => :string, :default => ""
97
+
98
+ # Attachments - specify the name(s) and location(s) of the files.
99
+ config :attachments, :validate => :array, :default => []
100
+
101
+ # contenttype : for multipart messages, set the content-type and/or charset of the HTML part.
102
+ # NOTE: this may not be functional (KH)
103
+ config :contenttype, :validate => :string, :default => "text/html; charset=UTF-8"
104
+
105
+ public
106
+ def register
107
+ require "mail"
108
+
109
+ # Mail uses instance_eval which changes the scope of self so @options is
110
+ # inaccessible from inside 'Mail.defaults'. So set a local variable instead.
111
+ options = @options
112
+
113
+ if @via == "smtp"
114
+ Mail.defaults do
115
+ delivery_method :smtp, {
116
+ :address => options.fetch("smtpIporHost", "localhost"),
117
+ :port => options.fetch("port", 25),
118
+ :domain => options.fetch("domain", "localhost"),
119
+ :user_name => options.fetch("userName", nil),
120
+ :password => options.fetch("password", nil),
121
+ :authentication => options.fetch("authenticationType", nil),
122
+ :enable_starttls_auto => options.fetch("starttls", false),
123
+ :debug => options.fetch("debug", false)
124
+ }
125
+ end
126
+ elsif @via == 'sendmail'
127
+ Mail.defaults do
128
+ delivery_method :sendmail
129
+ end
130
+ else
131
+ Mail.defaults do
132
+ delivery_method :@via, options
133
+ end
134
+ end # @via tests
135
+ @logger.debug("Email Output Registered!", :config => @config)
136
+ end # def register
137
+
138
+ public
139
+ def receive(event)
140
+ return unless output?(event)
141
+ @logger.debug("Event being tested for Email", :tags => @tags, :event => event)
142
+ # Set Intersection - returns a new array with the items that are the same between the two
143
+ if !@tags.empty? && (event["tags"] & @tags).size == 0
144
+ # Skip events that have no tags in common with what we were configured
145
+ @logger.debug("No Tags match for Email Output!")
146
+ return
147
+ end
148
+
149
+ @logger.debug? && @logger.debug("Match data for Email - ", :match => @match)
150
+ successful = false
151
+ matchName = ""
152
+ operator = ""
153
+
154
+ # TODO(sissel): Delete this once match support is removed.
155
+ @match && @match.each do |name, query|
156
+ if successful
157
+ break
158
+ else
159
+ matchName = name
160
+ end
161
+ # now loop over the csv query
162
+ queryArray = query.split(',')
163
+ index = 1
164
+ while index < queryArray.length
165
+ field = queryArray.at(index -1)
166
+ value = queryArray.at(index)
167
+ index = index + 2
168
+ if field == ""
169
+ if value.downcase == "and"
170
+ operator = "and"
171
+ elsif value.downcase == "or"
172
+ operator = "or"
173
+ else
174
+ operator = "or"
175
+ @logger.error("Operator Provided Is Not Found, Currently We Only Support AND/OR Values! - defaulting to OR")
176
+ end
177
+ else
178
+ hasField = event[field]
179
+ @logger.debug? and @logger.debug("Does Event Contain Field - ", :hasField => hasField)
180
+ isValid = false
181
+ # if we have maching field and value is wildcard - we have a success
182
+ if hasField
183
+ if value == "*"
184
+ isValid = true
185
+ else
186
+ # we get an array so we need to loop over the values and find if we have a match
187
+ eventFieldValues = event[field]
188
+ @logger.debug? and @logger.debug("Event Field Values - ", :eventFieldValues => eventFieldValues)
189
+ eventFieldValues = [eventFieldValues] if not eventFieldValues.respond_to?(:each)
190
+ eventFieldValues.each do |eventFieldValue|
191
+ isValid = validateValue(eventFieldValue, value)
192
+ if isValid # no need to iterate any further
193
+ @logger.debug("VALID CONDITION FOUND - ", :eventFieldValue => eventFieldValue, :value => value)
194
+ break
195
+ end
196
+ end # end eventFieldValues.each do
197
+ end # end value == "*"
198
+ end # end hasField
199
+ # if we have an AND operator and we have a successful == false break
200
+ if operator == "and" && !isValid
201
+ successful = false
202
+ elsif operator == "or" && (isValid || successful)
203
+ successful = true
204
+ else
205
+ successful = isValid
206
+ end
207
+ end
208
+ end
209
+ end # @match.each do
210
+
211
+ # The 'match' setting is deprecated and optional. If not set,
212
+ # default to success.
213
+ successful = true if @match.nil?
214
+
215
+ @logger.debug? && @logger.debug("Email Did we match any alerts for event : ", :successful => successful)
216
+
217
+ if successful
218
+ # first add our custom field - matchName - so we can use it in the sprintf function
219
+ event["matchName"] = matchName unless matchName.empty?
220
+ @logger.debug? and @logger.debug("Creating mail with these settings : ", :via => @via, :options => @options, :from => @from, :to => @to, :cc => @cc, :subject => @subject, :body => @body, :content_type => @contenttype, :htmlbody => @htmlbody, :attachments => @attachments, :to => to, :to => to)
221
+ formatedSubject = event.sprintf(@subject)
222
+ formattedBody = event.sprintf(@body)
223
+ formattedHtmlBody = event.sprintf(@htmlbody)
224
+ # we have a match(s) - send email
225
+ mail = Mail.new
226
+ mail.from = event.sprintf(@from)
227
+ mail.to = event.sprintf(@to)
228
+ if @replyto
229
+ mail.reply_to = event.sprintf(@replyto)
230
+ end
231
+ mail.cc = event.sprintf(@cc)
232
+ mail.subject = formatedSubject
233
+ if @htmlbody.empty?
234
+ formattedBody.gsub!(/\\n/, "\n") # Take new line in the email
235
+ mail.body = formattedBody
236
+ else
237
+ mail.text_part = Mail::Part.new do
238
+ content_type "text/plain; charset=UTF-8"
239
+ formattedBody.gsub!(/\\n/, "\n") # Take new line in the email
240
+ body formattedBody
241
+ end
242
+ mail.html_part = Mail::Part.new do
243
+ content_type "text/html; charset=UTF-8"
244
+ body formattedHtmlBody
245
+ end
246
+ end
247
+ @attachments.each do |fileLocation|
248
+ mail.add_file(fileLocation)
249
+ end # end @attachments.each
250
+ @logger.debug? and @logger.debug("Sending mail with these values : ", :from => mail.from, :to => mail.to, :cc => mail.cc, :subject => mail.subject)
251
+ mail.deliver!
252
+ end # end if successful
253
+ end # def receive
254
+
255
+
256
+ private
257
+ def validateValue(eventFieldValue, value)
258
+ valid = false
259
+ # order of this if-else is important - please don't change it
260
+ if value.start_with?(">=")# greater than or equal
261
+ value.gsub!(">=","")
262
+ if eventFieldValue.to_i >= value.to_i
263
+ valid = true
264
+ end
265
+ elsif value.start_with?("<=")# less than or equal
266
+ value.gsub!("<=","")
267
+ if eventFieldValue.to_i <= value.to_i
268
+ valid = true
269
+ end
270
+ elsif value.start_with?(">")# greater than
271
+ value.gsub!(">","")
272
+ if eventFieldValue.to_i > value.to_i
273
+ valid = true
274
+ end
275
+ elsif value.start_with?("<")# less than
276
+ value.gsub!("<","")
277
+ if eventFieldValue.to_i < value.to_i
278
+ valid = true
279
+ end
280
+ elsif value.start_with?("*")# contains
281
+ value.gsub!("*","")
282
+ if eventFieldValue.include?(value)
283
+ valid = true
284
+ end
285
+ elsif value.start_with?("!*")# does not contain
286
+ value.gsub!("!*","")
287
+ if !eventFieldValue.include?(value)
288
+ valid = true
289
+ end
290
+ elsif value.start_with?("!")# not equal
291
+ value.gsub!("!","")
292
+ if eventFieldValue != value
293
+ valid = true
294
+ end
295
+ else # default equal
296
+ if eventFieldValue == value
297
+ valid = true
298
+ end
299
+ end
300
+ return valid
301
+ end # end validateValue()
302
+
303
+ end # class LogStash::Outputs::Email
@@ -0,0 +1,28 @@
1
+ Gem::Specification.new do |s|
2
+
3
+ s.name = 'logstash-output-email'
4
+ s.version = '0.1.0'
5
+ s.licenses = ['Apache License (2.0)']
6
+ s.summary = "Send email when an output is received."
7
+ s.description = "Send email when an output is received."
8
+ s.authors = ["Elasticsearch"]
9
+ s.email = 'richard.pijnenburg@elasticsearch.com'
10
+ s.homepage = "http://logstash.net/"
11
+ s.require_paths = ["lib"]
12
+
13
+ # Files
14
+ s.files = `git ls-files`.split($\)+::Dir.glob('vendor/*')
15
+
16
+ # Tests
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+
19
+ # Special flag to let us know this is actually a logstash plugin
20
+ s.metadata = { "logstash_plugin" => "true", "group" => "output" }
21
+
22
+ # Gem dependencies
23
+ s.add_runtime_dependency 'logstash', '>= 1.4.0', '< 2.0.0'
24
+
25
+ s.add_runtime_dependency 'mail'
26
+
27
+ end
28
+
@@ -0,0 +1,9 @@
1
+ require "gem_publisher"
2
+
3
+ desc "Publish gem to RubyGems.org"
4
+ task :publish_gem do |t|
5
+ gem_file = Dir.glob(File.expand_path('../*.gemspec',File.dirname(__FILE__))).first
6
+ gem = GemPublisher.publish_if_updated(gem_file, :rubygems)
7
+ puts "Published #{gem}" if gem
8
+ end
9
+
@@ -0,0 +1,169 @@
1
+ require "net/http"
2
+ require "uri"
3
+ require "digest/sha1"
4
+
5
+ def vendor(*args)
6
+ return File.join("vendor", *args)
7
+ end
8
+
9
+ directory "vendor/" => ["vendor"] do |task, args|
10
+ mkdir task.name
11
+ end
12
+
13
+ def fetch(url, sha1, output)
14
+
15
+ puts "Downloading #{url}"
16
+ actual_sha1 = download(url, output)
17
+
18
+ if actual_sha1 != sha1
19
+ fail "SHA1 does not match (expected '#{sha1}' but got '#{actual_sha1}')"
20
+ end
21
+ end # def fetch
22
+
23
+ def file_fetch(url, sha1)
24
+ filename = File.basename( URI(url).path )
25
+ output = "vendor/#{filename}"
26
+ task output => [ "vendor/" ] do
27
+ begin
28
+ actual_sha1 = file_sha1(output)
29
+ if actual_sha1 != sha1
30
+ fetch(url, sha1, output)
31
+ end
32
+ rescue Errno::ENOENT
33
+ fetch(url, sha1, output)
34
+ end
35
+ end.invoke
36
+
37
+ return output
38
+ end
39
+
40
+ def file_sha1(path)
41
+ digest = Digest::SHA1.new
42
+ fd = File.new(path, "r")
43
+ while true
44
+ begin
45
+ digest << fd.sysread(16384)
46
+ rescue EOFError
47
+ break
48
+ end
49
+ end
50
+ return digest.hexdigest
51
+ ensure
52
+ fd.close if fd
53
+ end
54
+
55
+ def download(url, output)
56
+ uri = URI(url)
57
+ digest = Digest::SHA1.new
58
+ tmp = "#{output}.tmp"
59
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => (uri.scheme == "https")) do |http|
60
+ request = Net::HTTP::Get.new(uri.path)
61
+ http.request(request) do |response|
62
+ fail "HTTP fetch failed for #{url}. #{response}" if [200, 301].include?(response.code)
63
+ size = (response["content-length"].to_i || -1).to_f
64
+ count = 0
65
+ File.open(tmp, "w") do |fd|
66
+ response.read_body do |chunk|
67
+ fd.write(chunk)
68
+ digest << chunk
69
+ if size > 0 && $stdout.tty?
70
+ count += chunk.bytesize
71
+ $stdout.write(sprintf("\r%0.2f%%", count/size * 100))
72
+ end
73
+ end
74
+ end
75
+ $stdout.write("\r \r") if $stdout.tty?
76
+ end
77
+ end
78
+
79
+ File.rename(tmp, output)
80
+
81
+ return digest.hexdigest
82
+ rescue SocketError => e
83
+ puts "Failure while downloading #{url}: #{e}"
84
+ raise
85
+ ensure
86
+ File.unlink(tmp) if File.exist?(tmp)
87
+ end # def download
88
+
89
+ def untar(tarball, &block)
90
+ require "archive/tar/minitar"
91
+ tgz = Zlib::GzipReader.new(File.open(tarball))
92
+ # Pull out typesdb
93
+ tar = Archive::Tar::Minitar::Input.open(tgz)
94
+ tar.each do |entry|
95
+ path = block.call(entry)
96
+ next if path.nil?
97
+ parent = File.dirname(path)
98
+
99
+ mkdir_p parent unless File.directory?(parent)
100
+
101
+ # Skip this file if the output file is the same size
102
+ if entry.directory?
103
+ mkdir path unless File.directory?(path)
104
+ else
105
+ entry_mode = entry.instance_eval { @mode } & 0777
106
+ if File.exists?(path)
107
+ stat = File.stat(path)
108
+ # TODO(sissel): Submit a patch to archive-tar-minitar upstream to
109
+ # expose headers in the entry.
110
+ entry_size = entry.instance_eval { @size }
111
+ # If file sizes are same, skip writing.
112
+ next if stat.size == entry_size && (stat.mode & 0777) == entry_mode
113
+ end
114
+ puts "Extracting #{entry.full_name} from #{tarball} #{entry_mode.to_s(8)}"
115
+ File.open(path, "w") do |fd|
116
+ # eof? check lets us skip empty files. Necessary because the API provided by
117
+ # Archive::Tar::Minitar::Reader::EntryStream only mostly acts like an
118
+ # IO object. Something about empty files in this EntryStream causes
119
+ # IO.copy_stream to throw "can't convert nil into String" on JRuby
120
+ # TODO(sissel): File a bug about this.
121
+ while !entry.eof?
122
+ chunk = entry.read(16384)
123
+ fd.write(chunk)
124
+ end
125
+ #IO.copy_stream(entry, fd)
126
+ end
127
+ File.chmod(entry_mode, path)
128
+ end
129
+ end
130
+ tar.close
131
+ File.unlink(tarball) if File.file?(tarball)
132
+ end # def untar
133
+
134
+ def ungz(file)
135
+
136
+ outpath = file.gsub('.gz', '')
137
+ tgz = Zlib::GzipReader.new(File.open(file))
138
+ begin
139
+ File.open(outpath, "w") do |out|
140
+ IO::copy_stream(tgz, out)
141
+ end
142
+ File.unlink(file)
143
+ rescue
144
+ File.unlink(outpath) if File.file?(outpath)
145
+ raise
146
+ end
147
+ tgz.close
148
+ end
149
+
150
+ desc "Process any vendor files required for this plugin"
151
+ task "vendor" do |task, args|
152
+
153
+ @files.each do |file|
154
+ download = file_fetch(file['url'], file['sha1'])
155
+ if download =~ /.tar.gz/
156
+ prefix = download.gsub('.tar.gz', '').gsub('vendor/', '')
157
+ untar(download) do |entry|
158
+ if !file['files'].nil?
159
+ next unless file['files'].include?(entry.full_name.gsub(prefix, ''))
160
+ out = entry.full_name.split("/").last
161
+ end
162
+ File.join('vendor', out)
163
+ end
164
+ elsif download =~ /.gz/
165
+ ungz(download)
166
+ end
167
+ end
168
+
169
+ end
@@ -0,0 +1,173 @@
1
+ require "spec_helper"
2
+ require "rumbster"
3
+ require "message_observers"
4
+
5
+ describe "outputs/email", :broken => true do
6
+
7
+
8
+ @@port=2525
9
+ let (:rumbster) { Rumbster.new(@@port) }
10
+ let (:message_observer) { MailMessageObserver.new }
11
+
12
+ before :each do
13
+ rumbster.add_observer message_observer
14
+ rumbster.start
15
+ end
16
+
17
+ after :each do
18
+ rumbster.stop
19
+ end
20
+
21
+ describe "use a list of email as mail.to (LOGSTASH-827)" do
22
+ config <<-CONFIG
23
+ input {
24
+ generator {
25
+ message => "hello world"
26
+ count => 1
27
+ type => "generator"
28
+ }
29
+ }
30
+ filter {
31
+ noop {
32
+ add_field => ["dummy_match", "ok"]
33
+ }
34
+ }
35
+ output{
36
+ email {
37
+ to => "email1@host, email2@host"
38
+ match => ["mymatch", "dummy_match,ok"]
39
+ options => ["port", #{@@port}]
40
+ }
41
+ }
42
+ CONFIG
43
+
44
+ agent do
45
+ insist {message_observer.messages.size} == 1
46
+ insist {message_observer.messages[0].to} == ["email1@host", "email2@host"]
47
+ end
48
+ end
49
+
50
+ describe "use an array of email as mail.to (LOGSTASH-827)" do
51
+ config <<-CONFIG
52
+ input {
53
+ generator {
54
+ message => "hello world"
55
+ count => 1
56
+ type => "generator"
57
+ }
58
+ }
59
+ filter {
60
+ noop {
61
+ add_field => ["dummy_match", "ok"]
62
+ add_field => ["to_addr", "email1@host"]
63
+ add_field => ["to_addr", "email2@host"]
64
+ }
65
+ }
66
+ output{
67
+ email {
68
+ to => "%{to_addr}"
69
+ match => ["mymatch", "dummy_match,ok"]
70
+ options => ["port", #{@@port}]
71
+ }
72
+ }
73
+ CONFIG
74
+
75
+ agent do
76
+ insist {message_observer.messages.size} == 1
77
+ insist {message_observer.messages[0].to} == ["email1@host", "email2@host"]
78
+ end
79
+ end
80
+
81
+ describe "multi-lined text body (LOGSTASH-841)" do
82
+ config <<-CONFIG
83
+ input {
84
+ generator {
85
+ message => "hello world"
86
+ count => 1
87
+ type => "generator"
88
+ }
89
+ }
90
+ filter {
91
+ noop {
92
+ add_field => ["dummy_match", "ok"]
93
+ }
94
+ }
95
+ output{
96
+ email {
97
+ to => "me@host"
98
+ subject => "Hello World"
99
+ body => "Line1\\nLine2\\nLine3"
100
+ match => ["mymatch", "dummy_match,*"]
101
+ options => ["port", #{@@port}]
102
+ }
103
+ }
104
+ CONFIG
105
+
106
+ agent do
107
+ insist {message_observer.messages.size} == 1
108
+ insist {message_observer.messages[0].subject} == "Hello World"
109
+ insist {message_observer.messages[0].body.raw_source} == "Line1\r\nLine2\r\nLine3"
110
+ end
111
+ end
112
+
113
+ describe "use nil authenticationType (LOGSTASH-559)" do
114
+ config <<-CONFIG
115
+ input {
116
+ generator {
117
+ message => "hello world"
118
+ count => 1
119
+ type => "generator"
120
+ }
121
+ }
122
+ filter {
123
+ noop {
124
+ add_field => ["dummy_match", "ok"]
125
+ }
126
+ }
127
+ output{
128
+ email {
129
+ to => "me@host"
130
+ subject => "Hello World"
131
+ body => "Line1\\nLine2\\nLine3"
132
+ match => ["mymatch", "dummy_match,*"]
133
+ options => ["port", #{@@port}, "authenticationType", "nil"]
134
+ }
135
+ }
136
+ CONFIG
137
+
138
+ agent do
139
+ insist {message_observer.messages.size} == 1
140
+ insist {message_observer.messages[0].subject} == "Hello World"
141
+ insist {message_observer.messages[0].body.raw_source} == "Line1\r\nLine2\r\nLine3"
142
+ end
143
+ end
144
+
145
+ describe "match on source and message (LOGSTASH-826)" do
146
+ config <<-CONFIG
147
+ input {
148
+ generator {
149
+ message => "hello world"
150
+ count => 1
151
+ type => "generator"
152
+ }
153
+ }
154
+ output{
155
+ email {
156
+ to => "me@host"
157
+ subject => "Hello World"
158
+ body => "Mail body"
159
+ match => ["messageAndSourceMatch", "message,*hello,,and,source,*generator"]
160
+ options => ["port", #{@@port}, "authenticationType", "nil"]
161
+ }
162
+ }
163
+ CONFIG
164
+
165
+ agent do
166
+ insist {message_observer.messages.size} == 1
167
+ insist {message_observer.messages[0].subject} == "Hello World"
168
+ insist {message_observer.messages[0].body.raw_source} == "Mail body"
169
+ end
170
+ end
171
+ end
172
+
173
+
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-output-email
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Elasticsearch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logstash
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.0
20
+ - - <
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.4.0
30
+ - - <
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: mail
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ description: Send email when an output is received.
48
+ email: richard.pijnenburg@elasticsearch.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - Rakefile
56
+ - lib/logstash/outputs/email.rb
57
+ - logstash-output-email.gemspec
58
+ - rakelib/publish.rake
59
+ - rakelib/vendor.rake
60
+ - spec/outputs/email_spec.rb
61
+ homepage: http://logstash.net/
62
+ licenses:
63
+ - Apache License (2.0)
64
+ metadata:
65
+ logstash_plugin: 'true'
66
+ group: output
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.4.1
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Send email when an output is received.
87
+ test_files:
88
+ - spec/outputs/email_spec.rb