logstash-output-email 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/logstash/outputs/email.rb +35 -196
- data/logstash-output-email.gemspec +1 -1
- data/spec/outputs/email_spec.rb +29 -47
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fb4c27da8842a79052b5274c3e3f418ba106559
|
4
|
+
data.tar.gz: 0ec34781d9e6e54ab5cdfb3a7e81d0a1915cca76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24be2f1aa8ea57d9a2e5919ac0d66618e42c5d7d1c2af0e28bf76049ad362a10959ccd7a14d390b7d955fce222c8679b06d12783f6ca4a8891b224a325dfc779
|
7
|
+
data.tar.gz: 85eb7feb2ad575fd3dff7648cffd916732da230cba9ccfabe21afaac25a588be2edd6c672a2b5665ccfe0b713d44d2eec120f679830f1d237f96e622cf63f7a2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
# 2.0.0
|
2
|
+
- Introduced new configuration options for the smtp server, the
|
3
|
+
options option is gone and now you need to specify each option
|
4
|
+
independetly. This require you to change your previous configuration
|
5
|
+
when updating.
|
6
|
+
- Removed the deprecated option match. This option was deprecatred in
|
7
|
+
favor of using conditionals. This change also require you to change
|
8
|
+
your current cnofiguration if using this option.
|
9
|
+
|
1
10
|
# 1.1.0
|
2
11
|
- Make the delivery method more reliable to failure by catching and
|
3
12
|
logging exceptions when happen, like this LS is not going to break
|
@@ -8,14 +8,6 @@ class LogStash::Outputs::Email < LogStash::Outputs::Base
|
|
8
8
|
|
9
9
|
config_name "email"
|
10
10
|
|
11
|
-
# This setting is deprecated in favor of Logstash's "conditionals" feature
|
12
|
-
# If you were using this setting previously, please use conditionals instead.
|
13
|
-
#
|
14
|
-
# If you need help converting your older `match` setting to a conditional,
|
15
|
-
# I welcome you to join the #logstash irc channel on freenode or to post
|
16
|
-
# a message on https://discuss.elastic.co/c/logstash and ask for help! :)
|
17
|
-
config :match, :validate => :hash, :deprecated => true
|
18
|
-
|
19
11
|
# The fully-qualified email address to send the email to.
|
20
12
|
#
|
21
13
|
# This field also accepts a comma-separated string of addresses, for example:
|
@@ -39,51 +31,29 @@ class LogStash::Outputs::Email < LogStash::Outputs::Base
|
|
39
31
|
# How Logstash should send the email, either via SMTP or by invoking sendmail.
|
40
32
|
config :via, :validate => :string, :default => "smtp"
|
41
33
|
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
#
|
52
|
-
|
53
|
-
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
#
|
61
|
-
|
62
|
-
|
63
|
-
#
|
64
|
-
|
65
|
-
#
|
66
|
-
# Mail.delivery_method.new #=> Mail::SMTP instance
|
67
|
-
# Mail.retriever_method.new #=> Mail::POP3 instance
|
68
|
-
# end
|
69
|
-
#
|
70
|
-
# Each mail object inherits the defaults set in Mail.delivery_method. However, on
|
71
|
-
# a per email basis, you can override the method:
|
72
|
-
# [source,ruby]
|
73
|
-
# mail.delivery_method :sendmail
|
74
|
-
#
|
75
|
-
# Or you can override the method and pass in settings:
|
76
|
-
# [source,ruby]
|
77
|
-
# mail.delivery_method :sendmail, { :address => 'some.host' }
|
78
|
-
#
|
79
|
-
# You can also just modify the settings:
|
80
|
-
# [source,ruby]
|
81
|
-
# mail.delivery_settings = { :address => 'some.host' }
|
82
|
-
#
|
83
|
-
# The hash you supply is just merged against the defaults with "merge!" and the result
|
84
|
-
# assigned to the mail object. For instance, the above example will change only the
|
85
|
-
# `:address` value of the global `smtp_settings` to be 'some.host', retaining all other values.
|
86
|
-
config :options, :validate => :hash, :default => {}
|
34
|
+
# The address used to connect to the mail server
|
35
|
+
config :address, :validate => :string, :default => "localhost"
|
36
|
+
|
37
|
+
# Port used to communicate with the mail server
|
38
|
+
config :port, :validate => :number, :default => 25
|
39
|
+
|
40
|
+
# Domain used to send the email messages
|
41
|
+
config :domain, :validate => :string, :default => "localhost"
|
42
|
+
|
43
|
+
# Username to authenticate with the server
|
44
|
+
config :username, :validate => :string
|
45
|
+
|
46
|
+
# Password to authenticate with the server
|
47
|
+
config :password, :validate => :string
|
48
|
+
|
49
|
+
# Authentication method used when identifying with the server
|
50
|
+
config :authentication, :validate => :string
|
51
|
+
|
52
|
+
# Enables TLS when communicating with the server
|
53
|
+
config :use_tls, :validate => :boolean, :default => false
|
54
|
+
|
55
|
+
# Run the mail relay in debug mode
|
56
|
+
config :debug, :validate => :boolean, :default => false
|
87
57
|
|
88
58
|
# Subject: for the email.
|
89
59
|
config :subject, :validate => :string, :default => ""
|
@@ -105,22 +75,20 @@ class LogStash::Outputs::Email < LogStash::Outputs::Base
|
|
105
75
|
def register
|
106
76
|
require "mail"
|
107
77
|
|
108
|
-
|
109
|
-
|
110
|
-
|
78
|
+
options = {
|
79
|
+
:address => @address,
|
80
|
+
:port => @port,
|
81
|
+
:domain => @domain,
|
82
|
+
:user_name => @username,
|
83
|
+
:password => @password,
|
84
|
+
:authentication => @authentication,
|
85
|
+
:enable_starttls_auto => @use_tls,
|
86
|
+
:debug => @debug
|
87
|
+
}
|
111
88
|
|
112
89
|
if @via == "smtp"
|
113
90
|
Mail.defaults do
|
114
|
-
delivery_method :smtp,
|
115
|
-
:address => options.fetch("smtpIporHost", "localhost"),
|
116
|
-
:port => options.fetch("port", 25),
|
117
|
-
:domain => options.fetch("domain", "localhost"),
|
118
|
-
:user_name => options.fetch("userName", nil),
|
119
|
-
:password => options.fetch("password", nil),
|
120
|
-
:authentication => options.fetch("authenticationType", nil),
|
121
|
-
:enable_starttls_auto => options.fetch("starttls", false),
|
122
|
-
:debug => options.fetch("debug", false)
|
123
|
-
}
|
91
|
+
delivery_method :smtp, options
|
124
92
|
end
|
125
93
|
elsif @via == 'sendmail'
|
126
94
|
Mail.defaults do
|
@@ -131,96 +99,17 @@ class LogStash::Outputs::Email < LogStash::Outputs::Base
|
|
131
99
|
delivery_method :@via, options
|
132
100
|
end
|
133
101
|
end # @via tests
|
134
|
-
@logger.debug("Email Output Registered!", :config => @
|
102
|
+
@logger.debug("Email Output Registered!", :config => options, :via => @via)
|
135
103
|
end # def register
|
136
104
|
|
137
105
|
public
|
138
106
|
def receive(event)
|
139
107
|
return unless output?(event)
|
140
|
-
@logger.debug("Event being tested for Email", :tags => @tags, :event => event)
|
141
|
-
# Set Intersection - returns a new array with the items that are the same between the two
|
142
|
-
if !@tags.empty? && (event["tags"] & @tags).size == 0
|
143
|
-
# Skip events that have no tags in common with what we were configured
|
144
|
-
@logger.debug("No Tags match for Email Output!")
|
145
|
-
return
|
146
|
-
end
|
147
108
|
|
148
|
-
@logger.debug? && @logger.debug("Match data for Email - ", :match => @match)
|
149
|
-
successful = false
|
150
|
-
matchName = ""
|
151
|
-
operator = ""
|
152
|
-
|
153
|
-
# TODO(sissel): Delete this once match support is removed.
|
154
|
-
@match && @match.each do |name, query|
|
155
|
-
if successful
|
156
|
-
break
|
157
|
-
else
|
158
|
-
matchName = name
|
159
|
-
end
|
160
|
-
# now loop over the csv query
|
161
|
-
queryArray = query.split(',')
|
162
|
-
index = 1
|
163
|
-
while index < queryArray.length
|
164
|
-
field = queryArray.at(index -1)
|
165
|
-
value = queryArray.at(index)
|
166
|
-
index = index + 2
|
167
|
-
if field == ""
|
168
|
-
if value.downcase == "and"
|
169
|
-
operator = "and"
|
170
|
-
elsif value.downcase == "or"
|
171
|
-
operator = "or"
|
172
|
-
else
|
173
|
-
operator = "or"
|
174
|
-
@logger.error("Operator Provided Is Not Found, Currently We Only Support AND/OR Values! - defaulting to OR")
|
175
|
-
end
|
176
|
-
else
|
177
|
-
hasField = event[field]
|
178
|
-
@logger.debug? and @logger.debug("Does Event Contain Field - ", :hasField => hasField)
|
179
|
-
isValid = false
|
180
|
-
# if we have maching field and value is wildcard - we have a success
|
181
|
-
if hasField
|
182
|
-
if value == "*"
|
183
|
-
isValid = true
|
184
|
-
else
|
185
|
-
# we get an array so we need to loop over the values and find if we have a match
|
186
|
-
eventFieldValues = event[field]
|
187
|
-
@logger.debug? and @logger.debug("Event Field Values - ", :eventFieldValues => eventFieldValues)
|
188
|
-
eventFieldValues = [eventFieldValues] if not eventFieldValues.respond_to?(:each)
|
189
|
-
eventFieldValues.each do |eventFieldValue|
|
190
|
-
isValid = validateValue(eventFieldValue, value)
|
191
|
-
if isValid # no need to iterate any further
|
192
|
-
@logger.debug("VALID CONDITION FOUND - ", :eventFieldValue => eventFieldValue, :value => value)
|
193
|
-
break
|
194
|
-
end
|
195
|
-
end # end eventFieldValues.each do
|
196
|
-
end # end value == "*"
|
197
|
-
end # end hasField
|
198
|
-
# if we have an AND operator and we have a successful == false break
|
199
|
-
if operator == "and" && !isValid
|
200
|
-
successful = false
|
201
|
-
elsif operator == "or" && (isValid || successful)
|
202
|
-
successful = true
|
203
|
-
else
|
204
|
-
successful = isValid
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end # @match.each do
|
209
|
-
|
210
|
-
# The 'match' setting is deprecated and optional. If not set,
|
211
|
-
# default to success.
|
212
|
-
successful = true if @match.nil?
|
213
|
-
|
214
|
-
@logger.debug? && @logger.debug("Email Did we match any alerts for event : ", :successful => successful)
|
215
|
-
|
216
|
-
if successful
|
217
|
-
# first add our custom field - matchName - so we can use it in the sprintf function
|
218
|
-
event["matchName"] = matchName unless matchName.empty?
|
219
109
|
@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)
|
220
110
|
formatedSubject = event.sprintf(@subject)
|
221
111
|
formattedBody = event.sprintf(@body)
|
222
112
|
formattedHtmlBody = event.sprintf(@htmlbody)
|
223
|
-
# we have a match(s) - send email
|
224
113
|
mail = Mail.new
|
225
114
|
mail.from = event.sprintf(@from)
|
226
115
|
mail.to = event.sprintf(@to)
|
@@ -253,55 +142,5 @@ class LogStash::Outputs::Email < LogStash::Outputs::Base
|
|
253
142
|
@logger.error("Something happen while delivering an email", :exception => e)
|
254
143
|
@logger.debug? && @logger.debug("Processed event: ", :event => event)
|
255
144
|
end
|
256
|
-
end # end if successful
|
257
145
|
end # def receive
|
258
|
-
|
259
|
-
|
260
|
-
private
|
261
|
-
def validateValue(eventFieldValue, value)
|
262
|
-
valid = false
|
263
|
-
# order of this if-else is important - please don't change it
|
264
|
-
if value.start_with?(">=")# greater than or equal
|
265
|
-
value.gsub!(">=","")
|
266
|
-
if eventFieldValue.to_i >= value.to_i
|
267
|
-
valid = true
|
268
|
-
end
|
269
|
-
elsif value.start_with?("<=")# less than or equal
|
270
|
-
value.gsub!("<=","")
|
271
|
-
if eventFieldValue.to_i <= value.to_i
|
272
|
-
valid = true
|
273
|
-
end
|
274
|
-
elsif value.start_with?(">")# greater than
|
275
|
-
value.gsub!(">","")
|
276
|
-
if eventFieldValue.to_i > value.to_i
|
277
|
-
valid = true
|
278
|
-
end
|
279
|
-
elsif value.start_with?("<")# less than
|
280
|
-
value.gsub!("<","")
|
281
|
-
if eventFieldValue.to_i < value.to_i
|
282
|
-
valid = true
|
283
|
-
end
|
284
|
-
elsif value.start_with?("*")# contains
|
285
|
-
value.gsub!("*","")
|
286
|
-
if eventFieldValue.include?(value)
|
287
|
-
valid = true
|
288
|
-
end
|
289
|
-
elsif value.start_with?("!*")# does not contain
|
290
|
-
value.gsub!("!*","")
|
291
|
-
if !eventFieldValue.include?(value)
|
292
|
-
valid = true
|
293
|
-
end
|
294
|
-
elsif value.start_with?("!")# not equal
|
295
|
-
value.gsub!("!","")
|
296
|
-
if eventFieldValue != value
|
297
|
-
valid = true
|
298
|
-
end
|
299
|
-
else # default equal
|
300
|
-
if eventFieldValue == value
|
301
|
-
valid = true
|
302
|
-
end
|
303
|
-
end
|
304
|
-
return valid
|
305
|
-
end # end validateValue()
|
306
|
-
|
307
146
|
end # class LogStash::Outputs::Email
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-output-email'
|
4
|
-
s.version = '
|
4
|
+
s.version = '2.0.0'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = "Send email when an output is received."
|
7
7
|
s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
|
data/spec/outputs/email_spec.rb
CHANGED
@@ -27,25 +27,23 @@ describe "outputs/email" do
|
|
27
27
|
|
28
28
|
it "supports list of emails in to field" do
|
29
29
|
subject = plugin.new("to" => ["email1@host, email2@host"],
|
30
|
-
"
|
31
|
-
"options" => ["port", port])
|
30
|
+
"port" => port)
|
32
31
|
subject.register
|
33
|
-
subject.receive(LogStash::Event.new("message" => "hello"
|
32
|
+
subject.receive(LogStash::Event.new("message" => "hello"))
|
34
33
|
expect(message_observer.messages.size).to eq(1)
|
35
34
|
expect(message_observer.messages[0].to).to eq(["email1@host", "email2@host"])
|
36
35
|
end
|
37
36
|
|
38
37
|
it "multiple *to* addresses in a field" do
|
39
38
|
subject = plugin.new("to" => "%{to_addr}",
|
40
|
-
"
|
41
|
-
"options" => ["port", port])
|
39
|
+
"port" => port)
|
42
40
|
subject.register
|
43
41
|
subject.receive(LogStash::Event.new("message" => "hello",
|
44
|
-
"dummy_match" => "ok",
|
45
42
|
"to_addr" => ["email1@host", "email2@host"]))
|
46
43
|
expect(message_observer.messages.size).to eq(1)
|
47
44
|
expect(message_observer.messages[0].to).to eq(["email1@host", "email2@host"])
|
48
45
|
end
|
46
|
+
|
49
47
|
end
|
50
48
|
|
51
49
|
context "multi-lined text body (LOGSTASH-841)" do
|
@@ -53,59 +51,43 @@ describe "outputs/email" do
|
|
53
51
|
subject = plugin.new("to" => "me@host",
|
54
52
|
"subject" => "Hello World",
|
55
53
|
"body" => "Line1\\nLine2\\nLine3",
|
56
|
-
"
|
57
|
-
"options" => ["port", port])
|
54
|
+
"port" => port)
|
58
55
|
subject.register
|
59
|
-
subject.receive(LogStash::Event.new("message" => "hello"
|
56
|
+
subject.receive(LogStash::Event.new("message" => "hello"))
|
60
57
|
expect(message_observer.messages.size).to eq(1)
|
61
58
|
expect(message_observer.messages[0].subject).to eq("Hello World")
|
62
59
|
expect(message_observer.messages[0].body.raw_source).to eq("Line1\r\nLine2\r\nLine3\r\n")
|
63
60
|
end
|
64
|
-
end
|
65
61
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
79
|
-
end
|
62
|
+
context "use nil authenticationType (LOGSTASH-559)" do
|
63
|
+
it "reads messages correctly" do
|
64
|
+
subject = plugin.new("to" => "me@host",
|
65
|
+
"subject" => "Hello World",
|
66
|
+
"body" => "Line1\\nLine2\\nLine3",
|
67
|
+
"port" => port)
|
68
|
+
subject.register
|
69
|
+
subject.receive(LogStash::Event.new("message" => "hello"))
|
70
|
+
expect(message_observer.messages.size).to eq(1)
|
71
|
+
expect(message_observer.messages[0].subject).to eq("Hello World")
|
72
|
+
expect(message_observer.messages[0].body.raw_source).to eq("Line1\r\nLine2\r\nLine3\r\n")
|
73
|
+
end
|
80
74
|
|
81
|
-
context "match on source and message (LOGSTASH-826)" do
|
82
|
-
it "reads messages correctly" do
|
83
|
-
subject = plugin.new("to" => "me@host",
|
84
|
-
"subject" => "Hello World",
|
85
|
-
"body" => "Mail body",
|
86
|
-
"match" => [ "messageAndSourceMatch", "message,*hello,,and,type,*generator"],
|
87
|
-
"options" => ["port", port, "authenticationType", "nil"])
|
88
|
-
subject.register
|
89
|
-
subject.receive(LogStash::Event.new("message" => "hello world", "type" => "generator"))
|
90
|
-
expect(message_observer.messages.size).to eq(1)
|
91
|
-
expect(message_observer.messages[0].subject).to eq("Hello World")
|
92
|
-
expect(message_observer.messages[0].body.raw_source).to eq("Mail body\r\n")
|
93
|
-
end
|
94
|
-
end
|
95
75
|
|
96
|
-
|
76
|
+
context "having no connection to the email server" do
|
97
77
|
|
98
|
-
|
99
|
-
|
78
|
+
subject { plugin.new("to" => "me@host") }
|
79
|
+
let(:event) { LogStash::Event.new("message" => "hello world") }
|
100
80
|
|
101
|
-
|
102
|
-
|
103
|
-
|
81
|
+
before(:each) do
|
82
|
+
subject.register
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should send without throwing an error" do
|
86
|
+
expect { subject.receive(event) }.not_to raise_error
|
87
|
+
end
|
88
|
+
end
|
104
89
|
|
105
|
-
it "should send without throwing an error" do
|
106
|
-
expect { subject.receive(event) }.not_to raise_error
|
107
90
|
end
|
108
91
|
end
|
109
|
-
|
110
92
|
end
|
111
93
|
end
|