Class: LogStash::Inputs::IMAP

Inherits:
Base show all
Defined in:
lib/logstash/inputs/imap.rb

Overview

Read mail from IMAP servers

Periodically scans INBOX and moves any read messages to the trash.

Constant Summary collapse

ISO8601_STRFTIME =
"%04d-%02d-%02dT%02d:%02d:%02d.%06d%+03d:00".freeze

Constants included from Config::Mixin

Config::Mixin::CONFIGSORT

Instance Attribute Summary

Attributes inherited from Base

#params, #threadable

Attributes included from Config::Mixin

#config, #original_params

Attributes inherited from Plugin

#logger, #params

Instance Method Summary collapse

Methods inherited from Base

#initialize, #tag

Methods included from Config::Mixin

#config_init, included

Methods inherited from Plugin

#eql?, #finished, #finished?, #hash, #initialize, #inspect, lookup, #reload, #running?, #shutdown, #terminating?, #to_s

Constructor Details

This class inherits a constructor from LogStash::Inputs::Base

Instance Method Details

#check_mail(queue) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/logstash/inputs/imap.rb', line 60

def check_mail(queue)
  # TODO(sissel): handle exceptions happening during runtime:
  # EOFError, OpenSSL::SSL::SSLError
  imap = connect
  imap.select("INBOX")
  ids = imap.search("NOT SEEN")

  ids.each_slice(@fetch_count) do |id_set|
    items = imap.fetch(id_set, "RFC822")
    items.each do |item|
      next unless item.attr.has_key?("RFC822")
      mail = Mail.read_from_string(item.attr["RFC822"])
      queue << parse_mail(mail)
    end

    imap.store(id_set, '+FLAGS', @delete ? :Deleted : :Seen)
  end

  imap.close
  imap.disconnect
end

#connectObject

def register



48
49
50
51
52
# File 'lib/logstash/inputs/imap.rb', line 48

def connect
  imap = Net::IMAP.new(@host, :port => @port, :ssl => @secure)
  imap.(@user, @password.value)
  return imap
end

#parse_mail(mail) ⇒ Object

def run



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/logstash/inputs/imap.rb', line 82

def parse_mail(mail)
  # TODO(sissel): What should a multipart message look like as an event?
  # For now, just take the plain-text part and set it as the message.
  if mail.parts.count == 0
    # No multipart message, just use the body as the event text
    message = mail.body.decoded
  else
    # Multipart message; use the first text/plain part we find
    part = mail.parts.find { |p| p.content_type.match @content_type_re } || mail.parts.first
    message = part.decoded
  end

  event = LogStash::Event.new("message" => message)

  # Use the 'Date' field as the timestamp
  event["@timestamp"] = mail.date.to_time.gmtime

  # Add fields: Add message.header_fields { |h| h.name=> h.value }
  mail.header_fields.each do |header|
    if @lowercase_headers
      # 'header.name' can sometimes be a Mail::Multibyte::Chars, get it in
      # String form
      name = header.name.to_s.downcase
    else
      name = header.name.to_s
    end
    # Call .decoded on the header in case it's in encoded-word form.
    # Details at:
    #   https://github.com/mikel/mail/blob/master/README.md#encodings
    #   http://tools.ietf.org/html/rfc2047#section-2
    value = header.decoded

    # Assume we already processed the 'date' above.
    next if name == "Date"

    case event[name]
      # promote string to array if a header appears multiple times
      # (like 'received')
      when String; event[name] = [event[name], value]
      when Array; event[name].is_a?(Array)
      when nil; event[name] = value
    end
  end # mail.header_fields.each

  decorate(event)

  return event
end

#registerObject



33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/logstash/inputs/imap.rb', line 33

def register
  require "net/imap" # in stdlib
  require "mail" # gem 'mail'

  if @port.nil?
    if @secure
      @port = 993
    else
      @port = 143
    end
  end

  @content_type_re = Regexp.new("^" + @content_type)
end

#run(queue) ⇒ Object



54
55
56
57
58
# File 'lib/logstash/inputs/imap.rb', line 54

def run(queue)
  Stud.interval(@check_interval) do
    check_mail(queue)
  end
end

#teardownObject



132
133
134
135
# File 'lib/logstash/inputs/imap.rb', line 132

def teardown
  $stdin.close
  finished
end