├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── Gemfile
├── Gemfile.0.12
├── LICENSE
├── README.md
├── Rakefile
├── example
├── example.conf
└── to_cc_bcc_key.conf
├── fluent-plugin-mail.gemspec
├── lib
└── fluent
│ └── plugin
│ └── out_mail.rb
└── test
├── helper.rb
└── plugin
└── test_out_mail.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | *.rbc
3 | .bundle
4 | .config
5 | .yardoc
6 | Gemfile.lock
7 | InstalledFiles
8 | _yardoc
9 | coverage
10 | doc/
11 | lib/bundler/man
12 | pkg
13 | rdoc
14 | spec/reports
15 | test/tmp
16 | test/version_tmp
17 | tmp
18 | vendor/bundle
19 | .ruby-version
20 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | rvm:
2 | - 2.2.*
3 | - 2.3.*
4 | - 2.4.*
5 | gemfile:
6 | - Gemfile
7 | - Gemfile.0.12
8 | before_install: gem update bundler
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 0.3.0 (2017-11-25)
2 |
3 | Changes:
4 |
5 | * Drop Fluentd v0.10 support
6 | * Use array type for array like parameters (thanks to @cosmo0920)
7 |
8 | # 0.2.5 (2017-11-25)
9 |
10 | Enhancements:
11 |
12 | * Add `authtype` option (thanks to Ruilin Huang @hrl)
13 |
14 | # 0.2.4
15 |
16 | Enhancements:
17 |
18 | * Add to_key, cc_key, bcc_key options (thanks to authorNari)
19 |
20 | # 0.2.3
21 |
22 | Enhancements:
23 |
24 | * Add content_type option (thanks to okkez)
25 | * Support desc if it is available. see http://qiita.com/repeatedly/items/bce628ba75b442424bcf (thanks to okkez)
26 |
27 | # 0.2.2
28 |
29 | Enhancements:
30 |
31 | * Support secret parameter for `password` option (thanks to cosmo0920)
32 |
33 | # 0.2.1
34 |
35 | Fixes:
36 |
37 | * Fix `create_key_value_message` was broken because of 0.2.0 refactoring
38 |
39 | # 0.2.0
40 |
41 | Changes:
42 |
43 | * Refactoring
44 |
45 | Fixes:
46 |
47 | * Fix so that `time_locale` option works for time field in mail body
48 |
49 | Enhancements:
50 |
51 | * Add `localtime` option
52 |
53 | # 0.1.2
54 |
55 | Enhancement:
56 |
57 | * Send mail with Message-Id header field
58 |
59 | # 0.1.1
60 |
61 | Enhancement:
62 |
63 | * Avoid invalid byte seuqnce in UTF-8 error
64 |
65 | # 0.1.0
66 |
67 | Enhancement:
68 |
69 | * Add `enable_tls` option (thanks to @mash)
70 | * Add more debug messages (thanks to @glaci)
71 |
72 | # 0.0.5
73 |
74 | olders
75 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gemspec
4 |
--------------------------------------------------------------------------------
/Gemfile.0.12:
--------------------------------------------------------------------------------
1 | source "http://rubygems.org"
2 |
3 | gemspec
4 | gem 'fluentd', '~> 0.12.0'
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012- Yuichi UEMURA
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Fluent::Plugin::Mail, a plugin for [Fluentd](http://fluentd.org)
2 |
3 |
4 | ## Installation
5 |
6 | Add this line to your application's Gemfile:
7 |
8 | gem 'fluent-plugin-mail'
9 |
10 | Or install it yourself as:
11 |
12 | $ gem install fluent-plugin-mail
13 |
14 | Or use td-agent 2: (on Ubuntu12.04)
15 |
16 | $ sudo /usr/sbin/td-agent-gem install fluent-plugin-mail
17 |
18 | Or use td-agent 1: (not recommeded. Use td-agent 2 instead)
19 |
20 | $ sudo /usr/lib/fluent/ruby/bin/fluent-gem install fluent-plugin-mail
21 |
22 | ## Mail Configuration with out_keys (no auth)
23 |
24 |
25 | type mail
26 | host SMTPSERVER
27 | port 25
28 | from SOURCE
29 | to DEST1,DEST2,DEST3
30 | subject SUBJECT: %s
31 | subject_out_keys tag
32 | out_keys tag,foo,message
33 | time_locale UTC # optional
34 |
35 |
36 | Assume following input:
37 |
38 | tag.example: {"foo":"bar","message":"awesome!"}
39 |
40 | Email is sent like
41 |
42 | From: SOURCE
43 | To: DEST1,DEST2,DEST3
44 | Subject: SUBJECT: tag.example
45 | Mime-Version: 1.0
46 | Content-Type: text/plain; charset=utf-8
47 |
48 | tag: tag.example
49 | foo: bar
50 | message: awesome!
51 |
52 | ## Mail Configuration with Message Format (no auth)
53 |
54 | You may use `message` parameter to define mail format as you like. Use `\n` to put a return code.
55 |
56 |
57 | type mail
58 | host SMTPSERVER
59 | port 25
60 | from SOURCE
61 | to DEST1,DEST2,DEST3
62 | subject SUBJECT: %s
63 | subject_out_keys tag
64 | message %s\n%s %s
65 | message_out_keys tag,foo,message
66 | time_locale UTC # optional
67 |
68 |
69 | Assume following input:
70 |
71 | tag.example: {"foo":"bar","message":"awesome!"}
72 |
73 | Email is sent like
74 |
75 | From: SOURCE
76 | To: DEST1,DEST2,DEST3
77 | Subject: SUBJECT: tag.example
78 | Mime-Version: 1.0
79 | Content-Type: text/plain; charset=utf-8
80 |
81 | tag.example
82 | bar awesome!
83 |
84 | ## Mail Configuration for Gmail(use STARTTLS)
85 |
86 |
87 | type mail
88 | host smtp.gmail.com
89 | port 587
90 | domain gmail.com
91 | from SOURCE
92 | to DEST1,DEST2,DEST3
93 | subject SUBJECT
94 | user USERNAME( ex. hoge@gmail.com)
95 | password PASSWORD
96 | enable_starttls_auto true
97 | enable_tls false
98 | out_keys tag,foo,message
99 | time_locale UTC # optional
100 |
101 |
102 |
103 | ## Usage Sample
104 |
105 | ### SingleNode's syslog check
106 |
107 | use fluent_plugin_notifier(https://github.com/tagomoris/fluent-plugin-notifier)
108 |
109 | $ gem install fluent-plugin-notifier
110 |
111 | configure td-agent.conf for single node
112 |
113 |
114 | type tail
115 | tag syslog
116 | path /var/log/syslog
117 |
118 |
119 | type notifier
120 |
121 | pattern check_syslog
122 | check string_find
123 | warn_regexp .*warn.*
124 | crit_regexp .*crit.*
125 | target_key_pattern message
126 |
127 |
128 | pattern check_syslog
129 | check string_find
130 | warn_regexp .*Error.*
131 | crit_regexp .*Down.*
132 | target_key_pattern message
133 |
134 |
135 |
136 | type mail
137 | host MAILSERVER
138 | port MAILSERVER_PORT
139 | domain DOMAIN
140 | from SOURCE_MAIL_ADDRESS
141 | to DESTINATION_MAIL_ADDRESS
142 | subject SUBJECT
143 | out_keys target_tag, pattern, value, message_time
144 |
145 |
146 |
147 | ### MultiNode's syslog check
148 |
149 | use config_expander(https://github.com/tagomoris/fluent-plugin-config-expander)
150 |
151 | $ gem install fluent-plugin-config-expander
152 |
153 | source node("/etc/td-agent/td-agent.conf")
154 |
155 |
156 | type config_expander
157 |
158 | type tail
159 | format syslog
160 | path /var/log/syslog
161 | tag syslog.${hostname}
162 | pos_file /tmp/syslog.pos
163 |
164 | a
165 |
166 | type forward
167 |
168 | host HOST_ADDRESS
169 |
170 |
171 |
172 |
173 | log server("/etc/td-agent/td-agent.conf")
174 |
175 |
176 | type forward
177 |
178 |
179 | type copy
180 |
181 | type file
182 | path /var/log-server/syslog
183 |
184 |
185 | type notifier
186 |
187 | pattern check_syslog
188 | check string_find
189 | warn_regexp .*warn.*
190 | crit_regexp .*crit.*
191 | target_key_pattern message
192 |
193 |
194 |
195 |
196 | type mail
197 | host MAILSERVER
198 | port MAILSERVER_PORT
199 | domain DOMAIN
200 | from SOURCE_MAIL_ADDRESS
201 | to DESTINATION_MAIL_ADDRESS
202 | subject SUBJECT
203 | outkeys target_tag, pattern, value
204 | time_locale UTC # optional
205 |
206 |
207 |
208 | ### Dynamic identiciation of mail destination (to, cc, bcc)
209 |
210 | You can dynamically identify mail destination (to, cc, bcc) from event records as:
211 |
212 |
213 | ```
214 |
215 | type mail
216 | from from@example.com
217 | to_key to
218 | cc_key cc
219 | bcc_key bcc
220 | ....
221 |
222 | ```
223 |
224 | With this example, `to`, `cc`, `bcc` are dynamically extracted from `record["to"]`, `record["cc"]`, `record["bcc"]` respectively.
225 |
226 | ## ChangeLog
227 |
228 | See [CHANGELOG.md](CHANGELOG.md) for more details.
229 |
230 | ## Development
231 |
232 | Run mail server using [mailcatcher](http://mailcatcher.me/) gem as:
233 |
234 | ```
235 | $ gem install mailcatcher
236 | $ mailcatcher
237 | ```
238 |
239 | It starts STMP server on localhost:1025, and has Web UI running on localhost:1080.
240 |
241 | Run Fluentd as:
242 |
243 | ```
244 | $ bundle exec fluentd -c example/example.conf
245 | ```
246 |
247 | Put a message to the Fluentd as:
248 |
249 | ```
250 | $ echo '{"message":"This is a test"}' | bundle exec fluent-cat mail.test
251 | ```
252 |
253 | ## Copyright
254 |
255 | * Copyright
256 | * Copyright (c) 2012- Yuichi UEMURA
257 | * Copyright (c) 2014- Naotoshi Seo
258 | * License
259 | * Apache License, Version 2.0
260 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | require "bundler/gem_tasks"
3 |
4 | require 'rake/testtask'
5 | Rake::TestTask.new(:test) do |test|
6 | test.libs << 'lib' << 'test'
7 | test.pattern = 'test/**/test_*.rb'
8 | test.verbose = true
9 | end
10 |
11 | task :default => :test
12 |
--------------------------------------------------------------------------------
/example/example.conf:
--------------------------------------------------------------------------------
1 | # echo '{"message":"This is a test"}' | bundle exec fluent-cat mail.test
2 |
3 |
4 | type forward
5 |
6 |
7 |
8 | type mail
9 | log_level debug
10 | host localhost
11 | port 1025
12 | from from@example.com
13 | to to@example.com
14 | bcc bcc@example.com
15 | subject this is a test
16 | message Hello from out_mail\n[%s] %s
17 | message_out_keys time,message
18 | time_key time
19 | time_locale Asia/Taipei
20 | # localtime false
21 | time_format %Y-%m-%d %H:%M:%S %z
22 |
23 |
--------------------------------------------------------------------------------
/example/to_cc_bcc_key.conf:
--------------------------------------------------------------------------------
1 | # echo '{"message":"This is a test","bcc":"bcc@example.com"}' | bundle exec fluent-cat mail.test
2 |
3 |
4 | type forward
5 |
6 |
7 |
8 | type mail
9 | log_level debug
10 | host localhost
11 | port 1025
12 | from from@example.com
13 | to to@example.com
14 | to_key to
15 | bcc_key bcc
16 | subject this is a test
17 | message Hello from out_mail\n[%s] %s
18 | message_out_keys time,message
19 | time_key time
20 | time_locale Asia/Taipei
21 | # localtime false
22 | time_format %Y-%m-%d %H:%M:%S %z
23 |
24 |
--------------------------------------------------------------------------------
/fluent-plugin-mail.gemspec:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | Gem::Specification.new do |gem|
4 | gem.authors = ["Yuichi UEMURA", "Naotoshi Seo"]
5 | gem.email = ["yuichi.u@gmail.com", "sonots@gmail.com"]
6 | gem.description = %q{output plugin for Mail}
7 | gem.summary = %q{output plugin for Mail}
8 | gem.homepage = "https://github.com/u-ichi/fluent-plugin-mail"
9 | gem.files = `git ls-files`.split($\)
10 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
11 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
12 | gem.name = "fluent-plugin-mail"
13 | gem.require_paths = ["lib"]
14 | gem.version = '0.3.0'
15 | gem.license = "Apache-2.0"
16 |
17 | gem.add_runtime_dependency "fluentd", '>= 0.12.0'
18 | gem.add_runtime_dependency "string-scrub" if RUBY_VERSION.to_f < 2.1
19 | gem.add_development_dependency "rake"
20 | gem.add_development_dependency "test-unit"
21 | end
22 |
--------------------------------------------------------------------------------
/lib/fluent/plugin/out_mail.rb:
--------------------------------------------------------------------------------
1 | require 'securerandom'
2 |
3 | class Fluent::MailOutput < Fluent::Output
4 | Fluent::Plugin.register_output('mail', self)
5 |
6 | # Define `log` method for v0.10.42 or earlier
7 | unless method_defined?(:log)
8 | define_method("log") { $log }
9 | end
10 |
11 | # For fluentd v0.12.16 or earlier
12 | class << self
13 | unless method_defined?(:desc)
14 | def desc(description)
15 | end
16 | end
17 | end
18 |
19 | desc "Output comma delimited keys"
20 | config_param :out_keys, :array, :default => []
21 | desc "Format string to construct message body"
22 | config_param :message, :string, :default => nil
23 | desc "Specify comma delimited keys output to `message`"
24 | config_param :message_out_keys, :array, :default => []
25 | desc "Identify the timestamp of the record"
26 | config_param :time_key, :string, :default => nil
27 | desc "Identify the tag of the record"
28 | config_param :tag_key, :string, :default => 'tag'
29 | desc "SMTP server hostname"
30 | config_param :host, :string
31 | desc "SMTP server port number"
32 | config_param :port, :integer, :default => 25
33 | desc "HELO domain"
34 | config_param :domain, :string, :default => 'localdomain'
35 | desc "User for SMTP Auth"
36 | config_param :user, :string, :default => nil
37 | desc "Password for SMTP Auth"
38 | config_param :password, :string, :default => nil, :secret => true
39 | desc "Type for SMTP Auth such as 'plain', 'login', and 'cram_md5'"
40 | config_param :authtype, :string, :default => 'plain'
41 | desc "MAIL FROM this value"
42 | config_param :from, :string, :default => 'localhost@localdomain'
43 | desc "Mail destination (To)"
44 | config_param :to, :string, :default => ''
45 | desc "Mail destination (Cc)"
46 | config_param :cc, :string, :default => ''
47 | desc "Mail destination (Bcc)"
48 | config_param :bcc, :string, :default => ''
49 | desc "Dyanmically identify mail destination (To) from records"
50 | config_param :to_key, :string, :default => nil
51 | desc "Dynamically identify mail destination (Cc) from records"
52 | config_param :cc_key, :string, :default => nil
53 | desc "Dynamically identify mail destination (Bcc) from records"
54 | config_param :bcc_key, :string, :default => nil
55 | desc "Format string to construct mail subject"
56 | config_param :subject, :string, :default => 'Fluent::MailOutput plugin'
57 | desc "Specify comma delimited keys output to `subject`"
58 | config_param :subject_out_keys, :array, :default => []
59 | desc "If set to true, enable STARTTLS"
60 | config_param :enable_starttls_auto, :bool, :default => false
61 | desc "If set to true, enable TLS"
62 | config_param :enable_tls, :bool, :default => false
63 | desc "Format string to parse time"
64 | config_param :time_format, :string, :default => "%F %T %z"
65 | desc "Use local time or not"
66 | config_param :localtime, :bool, :default => true
67 | desc "Locale of time"
68 | config_param :time_locale, :default => nil
69 | desc "Specify Content-Type"
70 | config_param :content_type, :string, :default => "text/plain; charset=utf-8"
71 |
72 | def initialize
73 | super
74 | require 'net/smtp'
75 | require 'string/scrub' if RUBY_VERSION.to_f < 2.1
76 | end
77 |
78 | def configure(conf)
79 | super
80 |
81 | if @out_keys.empty? and @message.nil?
82 | raise Fluent::ConfigError, "Either 'message' or 'out_keys' must be specifed."
83 | end
84 |
85 | if @message
86 | begin
87 | @message % (['1'] * @message_out_keys.length)
88 | rescue ArgumentError
89 | raise Fluent::ConfigError, "string specifier '%s' of message and message_out_keys specification mismatch"
90 | end
91 | @create_message_proc = Proc.new {|tag, time, record| create_formatted_message(tag, time, record) }
92 | else
93 | # The default uses the old `key=value` format for old version compatibility
94 | @create_message_proc = Proc.new {|tag, time, record| create_key_value_message(tag, time, record) }
95 | end
96 |
97 | if @to_key or @cc_key or @bcc_key
98 | @process_event_stream_proc = Proc.new {|tag, es|
99 | messages = []
100 | subjects = []
101 | dests = []
102 |
103 | es.each do |time, record|
104 | messages << @create_message_proc.call(tag, time, record)
105 | subjects << create_formatted_subject(tag, time, record)
106 | dests << %w(to cc bcc).each_with_object({}){|t, dest| dest[t] = create_dest_addr(t, record) }
107 | end
108 |
109 | [messages, subjects, dests]
110 | }
111 | else
112 | @process_event_stream_proc = Proc.new {|tag, es|
113 | messages = []
114 | subjects = []
115 | dests = []
116 |
117 | es.each do |time, record|
118 | messages << @create_message_proc.call(tag, time, record)
119 | subjects << create_formatted_subject(tag, time, record)
120 | end
121 |
122 | [messages, subjects, dests]
123 | }
124 | end
125 |
126 | begin
127 | @subject % (['1'] * @subject_out_keys.length)
128 | rescue ArgumentError
129 | raise Fluent::ConfigError, "string specifier '%s' of subject and subject_out_keys specification mismatch"
130 | end
131 | end
132 |
133 | def start
134 | end
135 |
136 | def shutdown
137 | end
138 |
139 | def emit(tag, es, chain)
140 | messages, subjects, dests = @process_event_stream_proc.call(tag, es)
141 |
142 | messages.each_with_index do |message, i|
143 | subject = subjects[i]
144 | dest = dests[i]
145 | begin
146 | sendmail(subject, message, dest)
147 | rescue => e
148 | log.warn "out_mail: failed to send notice to #{@host}:#{@port}, subject: #{subject}, message: #{message}, " <<
149 | "error_class: #{e.class}, error_message: #{e.message}, error_backtrace: #{e.backtrace.first}"
150 | end
151 | end
152 |
153 | chain.next
154 | end
155 |
156 | # The old `key=value` format for old version compatibility
157 | def create_key_value_message(tag, time, record)
158 | values = []
159 |
160 | values = @out_keys.map do |key|
161 | case key
162 | when @time_key
163 | format_time(time, @time_format)
164 | when @tag_key
165 | tag
166 | else
167 | "#{key}: #{record[key].to_s}"
168 | end
169 | end
170 |
171 | values.join("\n")
172 | end
173 |
174 | def create_formatted_message(tag, time, record)
175 | values = []
176 |
177 | values = @message_out_keys.map do |key|
178 | case key
179 | when @time_key
180 | format_time(time, @time_format)
181 | when @tag_key
182 | tag
183 | else
184 | record[key].to_s
185 | end
186 | end
187 |
188 | message = (@message % values)
189 | with_scrub(message) {|str| str.gsub(/\\n/, "\n") }
190 | end
191 |
192 | def create_formatted_subject(tag, time, record)
193 | values = []
194 |
195 | values = @subject_out_keys.map do |key|
196 | case key
197 | when @time_key
198 | format_time(time, @time_format)
199 | when @tag_key
200 | tag
201 | else
202 | record[key].to_s
203 | end
204 | end
205 |
206 | @subject % values
207 | end
208 |
209 | def sendmail(subject, msg, dest = nil)
210 | smtp = Net::SMTP.new(@host, @port)
211 |
212 | if @user and @password
213 | smtp_auth_option = [@domain, @user, @password, @authtype.to_sym]
214 | smtp.enable_starttls if @enable_starttls_auto
215 | smtp.enable_tls if @enable_tls
216 | smtp.start(@domain, @user, @password, @authtype.to_sym)
217 | else
218 | smtp.start
219 | end
220 |
221 | subject = subject.force_encoding('binary')
222 | body = msg.force_encoding('binary')
223 | to = (dest && dest['to']) ? dest['to'] : @to
224 | cc = (dest && dest['cc']) ? dest['cc'] : @cc
225 | bcc = (dest && dest['bcc']) ? dest['bcc'] : @bcc
226 |
227 | # Date: header has timezone, so usually it is not necessary to set locale explicitly
228 | # But, for people who would see mail header text directly, the locale information may help something
229 | # (for example, they can tell the sender should live in Tokyo if +0900)
230 | date = format_time(Time.now, "%a, %d %b %Y %X %z")
231 |
232 | mid = sprintf("<%s@%s>", SecureRandom.uuid, SecureRandom.uuid)
233 | content = <= v0.12's TimeFormatter supports timezone, but v0.10 does not
254 | if @time_locale
255 | with_timezone(@time_locale) { Fluent::TimeFormatter.new(time_format, @localtime).format(time) }
256 | else
257 | Fluent::TimeFormatter.new(time_format, @localtime).format(time)
258 | end
259 | end
260 |
261 | def with_timezone(tz)
262 | oldtz, ENV['TZ'] = ENV['TZ'], tz
263 | yield
264 | ensure
265 | ENV['TZ'] = oldtz
266 | end
267 |
268 | def with_scrub(string)
269 | begin
270 | return yield(string)
271 | rescue ArgumentError => e
272 | raise e unless e.message.index("invalid byte sequence in") == 0
273 | log.info "out_mail: invalid byte sequence is replaced in #{string}"
274 | string.scrub!('?')
275 | retry
276 | end
277 | end
278 |
279 | def create_dest_addr(dest_type, record)
280 | addr = instance_variable_get(:"@#{dest_type}")
281 | dest_key = instance_variable_get(:"@#{dest_type}_key")
282 | if dest_key
283 | return record[dest_key] || addr
284 | else
285 | return addr
286 | end
287 | end
288 | end
289 |
--------------------------------------------------------------------------------
/test/helper.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'bundler'
3 | begin
4 | Bundler.setup(:default, :test)
5 | rescue Bundler::BundlerError => e
6 | $stderr.puts e.message
7 | $stderr.puts "Run `bundle install` to install missing gems"
8 | exit e.status_code
9 | end
10 | require 'test/unit'
11 |
12 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13 | $LOAD_PATH.unshift(File.dirname(__FILE__))
14 | require 'fluent/test'
15 | unless ENV.has_key?('VERBOSE')
16 | nulllogger = Object.new
17 | nulllogger.instance_eval {|obj|
18 | def method_missing(method, *args)
19 | # pass
20 | end
21 | }
22 | $log = nulllogger
23 | end
24 |
25 | require 'fluent/plugin/out_mail'
26 |
27 | class Test::Unit::TestCase
28 | end
29 |
--------------------------------------------------------------------------------
/test/plugin/test_out_mail.rb:
--------------------------------------------------------------------------------
1 | require_relative '../helper'
2 |
3 | class MailOutputTest < Test::Unit::TestCase
4 | def setup
5 | Fluent::Test.setup
6 | end
7 |
8 | CONFIG_OUT_KEYS = %[
9 | out_keys tag,time,value
10 | time_key time
11 | time_format %Y/%m/%d %H:%M:%S
12 | tag_key tag
13 | subject Fluentd Notification Alarm %s
14 | subject_out_keys tag
15 | host localhost
16 | port 25
17 | from localhost@localdomain
18 | to localhost@localdomain
19 | ]
20 |
21 | CONFIG_CC_BCC = %[
22 | out_keys tag,time,value
23 | time_key time
24 | time_format %Y/%m/%d %H:%M:%S
25 | tag_key tag
26 | subject Fluentd Notification Alarm %s
27 | subject_out_keys tag
28 | host localhost
29 | port 25
30 | from localhost@localdomain
31 | cc localhost@localdomain
32 | bcc localhost@localdomain
33 | ]
34 |
35 | CONFIG_MESSAGE = %[
36 | message out_mail: %s [%s]\\n%s
37 | message_out_keys tag,time,value
38 | time_key time
39 | time_format %Y/%m/%d %H:%M:%S
40 | tag_key tag
41 | subject Fluentd Notification Alarm %s
42 | subject_out_keys tag
43 | host localhost
44 | port 25
45 | from localhost@localdomain
46 | to localhost@localdomain
47 | ]
48 |
49 | CONFIG_DEST_ADDR = %[
50 | out_keys tag,time,value
51 | time_key time
52 | time_format %Y/%m/%d %H:%M:%S
53 | tag_key tag
54 | subject Fluentd Notification Alarm %s
55 | subject_out_keys tag
56 | host localhost
57 | port 25
58 | from localhost@localdomain
59 | to_key to
60 | cc_key cc
61 | bcc_key bcc
62 | ]
63 | CONFIG_KEYS_WITH_WHITESPACES = %[
64 | out_keys tag,time, value
65 | time_key time
66 | time_format %Y/%m/%d %H:%M:%S
67 | tag_key tag
68 | message_out_keys msg, log_level
69 | subject Fluentd Notification Alarm %s
70 | subject_out_keys tag, content_id
71 | host localhost
72 | port 25
73 | from localhost@localdomain
74 | to localhost@localdomain
75 | ]
76 |
77 | def create_driver(conf=CONFIG_OUT_KEYS,tag='test')
78 | Fluent::Test::OutputTestDriver.new(Fluent::MailOutput, tag).configure(conf)
79 | end
80 |
81 | def test_configure
82 | d = create_driver(CONFIG_OUT_KEYS)
83 | assert_equal 'localhost', d.instance.host
84 | assert_equal ['tag', 'time', 'value'], d.instance.out_keys
85 | d = create_driver(CONFIG_CC_BCC)
86 | assert_equal 'localhost', d.instance.host
87 | assert_equal ['tag', 'time', 'value'], d.instance.out_keys
88 | d = create_driver(CONFIG_MESSAGE)
89 | assert_equal 'localhost', d.instance.host
90 | assert_equal ['tag', 'time', 'value'], d.instance.message_out_keys
91 | d = create_driver(CONFIG_KEYS_WITH_WHITESPACES)
92 | assert_equal 'localhost', d.instance.host
93 | assert_equal ['tag', 'time', 'value'], d.instance.out_keys
94 | assert_equal ['tag', 'content_id'], d.instance.subject_out_keys
95 | assert_equal ['msg', 'log_level'], d.instance.message_out_keys
96 | end
97 |
98 | def test_out_keys
99 | d = create_driver(CONFIG_OUT_KEYS)
100 | time = Time.now.to_i
101 | d.run do
102 | d.emit({'value' => "out_keys mail from fluentd out_mail"}, time)
103 | end
104 | end
105 |
106 | def test_message
107 | d = create_driver(CONFIG_MESSAGE)
108 | time = Time.now.to_i
109 | d.run do
110 | d.emit({'value' => "message mail from fluentd out_mail"}, time)
111 | end
112 | end
113 |
114 | def test_dest_addr
115 | d = create_driver(CONFIG_DEST_ADDR)
116 | time = Time.now.to_i
117 | d.run do
118 | d.emit({
119 | 'value' => "message mail from fluentd out_mail",
120 | 'to' => "localhost@localdomain",
121 | 'cc' => "localhost@localdomain",
122 | 'bcc' => "localhost@localdomain",
123 | },
124 | time)
125 | end
126 | end
127 |
128 | def test_with_scrub
129 | d = create_driver(CONFIG_MESSAGE)
130 | invalid_string = "\xff".force_encoding('UTF-8')
131 | assert_nothing_raised {
132 | res = d.instance.with_scrub(invalid_string) {|str| str.gsub(/\\n/, "\n") }
133 | assert_equal '?', res
134 | }
135 | end
136 | end
137 |
138 |
--------------------------------------------------------------------------------