Class: Fluent::MailOutput

Inherits:
Output
  • Object
show all
Defined in:
lib/fluent/plugin/out_mail.rb

Instance Method Summary collapse

Constructor Details

#initializeMailOutput

Returns a new instance of MailOutput.



30
31
32
33
34
35
# File 'lib/fluent/plugin/out_mail.rb', line 30

def initialize
  super
  require 'net/smtp'
  require 'kconv'
  require 'string/scrub' if RUBY_VERSION.to_f < 2.1
end

Instance Method Details

#configure(conf) ⇒ Object



37
38
39
40
41
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
67
68
69
70
71
# File 'lib/fluent/plugin/out_mail.rb', line 37

def configure(conf)
  super

  @out_keys = @out_keys.split(',')
  @message_out_keys = @message_out_keys.split(',')
  @subject_out_keys = @subject_out_keys.split(',')

  if @out_keys.empty? and @message.nil?
    raise Fluent::ConfigError, "Either 'message' or 'out_keys' must be specifed."
  end

  begin
    @message % (['1'] * @message_out_keys.length) if @message
  rescue ArgumentError
    raise Fluent::ConfigError, "string specifier '%s' of message and message_out_keys specification mismatch"
  end

  begin
    @subject % (['1'] * @subject_out_keys.length)
  rescue ArgumentError
    raise Fluent::ConfigError, "string specifier '%s' of subject and subject_out_keys specification mismatch"
  end

  if @time_key
    if @time_format
      f = @time_format
      tf = Fluent::TimeFormatter.new(f, @localtime)
      @time_format_proc = tf.method(:format)
      @time_parse_proc = Proc.new {|str| Time.strptime(str, f).to_i }
    else
      @time_format_proc = Proc.new {|time| time.to_s }
      @time_parse_proc = Proc.new {|str| str.to_i }
    end
  end
end

#create_formatted_message(tag, time, record) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/fluent/plugin/out_mail.rb', line 126

def create_formatted_message(tag, time, record)
  values = []

  values = @message_out_keys.map do |key|
    case key
    when @time_key
      @time_format_proc.call(time)
    when @tag_key
      tag
    else
      record[key].to_s
    end
  end

  message = (@message % values)
  with_scrub(message) {|str| str.gsub(/\\n/, "\n") }
end

#create_formatted_subject(tag, time, record) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/fluent/plugin/out_mail.rb', line 155

def create_formatted_subject(tag, time, record)
  values = []

  values = @subject_out_keys.map do |key|
    case key
    when @time_key
      @time_format_proc.call(time)
    when @tag_key
      tag
    else
      record[key].to_s
    end
  end

  @subject % values
end

#create_key_value_message(tag, time, record) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/fluent/plugin/out_mail.rb', line 109

def create_key_value_message(tag, time, record)
  values = []

  @out_keys.each do |key|
    case key
    when @time_key
      values << @time_format_proc.call(time)
    when @tag_key
      values << tag
    else
      values << "#{key}: #{record[key].to_s}"
    end
  end

  values.join("\n")
end

#emit(tag, es, chain) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/fluent/plugin/out_mail.rb', line 80

def emit(tag, es, chain)
  messages = []
  subjects = []

  es.each {|time,record|
    if @message
      messages << create_formatted_message(tag, time, record)
    else
      messages << create_key_value_message(tag, time, record)
    end
    subjects << create_formatted_subject(tag, time, record)
  }

  messages.each_with_index do |msg, i|
    subject = subjects[i]
    begin
      res = sendmail(subject, msg)
    rescue => e
      log.warn "out_mail: failed to send notice to #{@host}:#{@port}, subject: #{subject}, message: #{msg}, error_class: #{e.class}, error_message: #{e.message}, error_backtrace: #{e.backtrace.first}"
    end
  end

  chain.next
end

#format(tag, time, record) ⇒ Object



105
106
107
# File 'lib/fluent/plugin/out_mail.rb', line 105

def format(tag, time, record)
  "#{Time.at(time).strftime('%Y/%m/%d %H:%M:%S')}\t#{tag}\t#{record.to_json}\n"
end

#sendmail(subject, msg) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/fluent/plugin/out_mail.rb', line 172

def sendmail(subject, msg)
  smtp = Net::SMTP.new(@host, @port)

  if @user and @password
    smtp_auth_option = [@domain, @user, @password, :plain]
    smtp.enable_starttls if @enable_starttls_auto
    smtp.enable_tls if @enable_tls
    smtp.start(@domain,@user,@password,:plain)
  else
    smtp.start
  end

  subject = subject.force_encoding('binary')
  body = msg.force_encoding('binary')

  if time_locale
    date = Time::now.timezone(time_locale)
  else
    date = Time::now
  end

  debug_msg = smtp.send_mail("Date: \#{date.strftime(\"%a, %d %b %Y %X %z\")}\nFrom: \#{@from}\nTo: \#{@to}\nCc: \#{@cc}\nBcc: \#{@bcc}\nSubject: \#{subject}\nMime-Version: 1.0\nContent-Type: text/plain; charset=utf-8\n\n\#{body}\n", @from, @to.split(/,/), @cc.split(/,/), @bcc.split(/,/))
  log.debug "out_mail: email send response: #{debug_msg}"
  smtp.finish
end

#shutdownObject



77
78
# File 'lib/fluent/plugin/out_mail.rb', line 77

def shutdown
end

#startObject



73
74
75
# File 'lib/fluent/plugin/out_mail.rb', line 73

def start

end

#with_scrub(string) ⇒ Object



144
145
146
147
148
149
150
151
152
153
# File 'lib/fluent/plugin/out_mail.rb', line 144

def with_scrub(string)
  begin
    return yield(string)
  rescue ArgumentError => e
    raise e unless e.message.index("invalid byte sequence in") == 0
    log.info "out_mail: invalid byte sequence is replaced in #{string}"
    string.scrub!('?')
    retry
  end
end