diff --git a/bin/malpd b/bin/malpd
index 53ab682..1122fc4 100755
--- a/bin/malpd
+++ b/bin/malpd
@@ -4,6 +4,7 @@ require "socket"
require "fileutils"
require "json"
require "shellwords"
+require "etc"
SOCKET_PATH = "/run/malpd/malpd.sock"
@@ -212,6 +213,33 @@ def read_server_info
info
end
+def read_mail
+ users = []
+
+ ["root", "josh"].each do |user|
+ begin
+ home = Etc.getpwnam(user).dir
+ rescue ArgumentError
+ next
+ end
+
+ count = 0
+ mbox = ["/var/mail/#{user}", "/var/spool/mail/#{user}"].find { |p| File.exist?(p) }
+ if mbox
+ content = File.read(mbox) rescue ""
+ count = content.scan(/^From /).size
+ end
+
+ users << {
+ "user" => user,
+ "count" => count,
+ "dead_letter" => File.exist?(File.join(home, "dead.letter"))
+ }
+ end
+
+ { "type" => "mail", "users" => users }
+end
+
def read_ups
out = `apcaccess 2>/dev/null`
return nil unless $?.success? && !out.empty?
@@ -279,6 +307,7 @@ def handle_info(conn)
info.concat(read_virtual_machines)
info << read_server_info
+ info << read_mail
if (ups = read_ups)
info << ups
diff --git a/cgi-bin/malp.rb b/cgi-bin/malp.rb
index 745eb56..293d228 100755
--- a/cgi-bin/malp.rb
+++ b/cgi-bin/malp.rb
@@ -369,7 +369,10 @@ if cgi.params.key?("content")
end
upses = info.select { |e| e["type"] == "ups" }
- if drives.any? || upses.any?
+ mail = info.find { |e| e["type"] == "mail" }
+ mail_visible = mail && (mail["users"] || []).any?
+
+ if drives.any? || upses.any? || mail_visible
html << %(
)
end
@@ -411,56 +414,93 @@ if cgi.params.key?("content")
html << %(
)
end
- upses.each do |ups|
- status = ups["status"].to_s
- online = status.include?("ONLINE")
- card_cls = online ? "ok" : "bad"
-
- model = ups["model"] ? "APC " + CGI.escapeHTML(ups["model"]) : "UPS"
-
- stats = []
- stats << [online ? "ok" : "bad", CGI.escapeHTML(status)] unless status.empty?
-
- if (charge = ups["charge"])
- cls = charge >= 80 ? "ok" : charge >= 50 ? "warn" : "bad"
- stats << [cls, "Charge #{charge.round}%"]
- end
- if (timeleft = ups["timeleft"])
- cls = timeleft >= 10 ? "ok" : timeleft >= 5 ? "warn" : "bad"
- stats << [cls, "#{timeleft.round(1)} min left"]
- end
- if (load = ups["load"])
- cls = load >= 90 ? "bad" : load >= 70 ? "warn" : "ok"
- stats << [cls, "Load #{load.round}%"]
- end
- if (lv = ups["line_voltage"])
- stats << ["ok", "Line #{lv.round} V"]
- end
- if (bv = ups["battery_voltage"])
- stats << ["ok", "Batt #{bv.round(1)} V"]
- end
-
- stats_html = stats.map { |c, txt|
- %(#{txt})
- }.join
- stats_block = stats.empty? ? "" :
- %(#{stats_html}
)
-
+ if upses.any? || mail_visible
html << %()
- html << %(
UPS
)
- html << <<~HTML
-
-
- HTML
+ HTML
+ end
+
+ if mail_visible
+ users = mail["users"]
+ has_warn = users.any? { |u| u["count"].to_i > 0 || u["dead_letter"] }
+ mail_card_cls = has_warn ? "warn" : "ok"
+
+ html << %(
Mail
)
+ html << %(
)
+
+ users.each do |u|
+ count = u["count"].to_i
+ cls = count > 0 ? "warn" : "ok"
+ label = count == 1 ? "1 message" : "#{count} messages"
+ html << <<~HTML
+
+
#{CGI.escapeHTML(u["user"].to_s)}
+
#{label}
+
+ HTML
+ end
+
+ html << %(
)
+
+ dead = users.select { |u| u["dead_letter"] }
+ if dead.any?
+ stats_html = dead.map { |u|
+ %(
dead.letter in ~#{CGI.escapeHTML(u["user"].to_s)})
+ }.join
+ html << %(
#{stats_html}
)
+ end
+
+ html << %(
)
+ end
+
html << %(
)
end
- if drives.any? || upses.any?
+ if drives.any? || upses.any? || mail_visible
html << %(
)
end