サーバーからのメールをslackへ投稿する


はじめに

slackいいですよね。最近はメールとかで送っていた物もSlack通知を多用するようになってきました。
今まで処理終了時やアラートをGmailに送信していたのですが、利便性のためにSlack投稿に変更した際の手順について説明したいと思います。

手順としては大きく二つ、Incoming WebHooksの登録と、perlスクリプトの作成になります。
perlスクリプトは本当はシェルスクリプトかpython辺りでやりたかったのですが、時間が足りなかったので(言い訳)

Incoming WebHooksの登録

slackにログインします。
名前をクリックして「Apps & integrations」を選択します。

下記のような画面が出てきますが、Incoming WebHooksを検索すると楽です。

そうすると下記のような画面になりますのでAdd Configurationをクリックします。

次の画面では投稿先のチャンネルを選択してAdd Incoming WebHooks integrationをクリックします。
投稿先のチャンネルはスクリプトで変更できるので#generalでいいと思います。

最後の画面ではWebhook URLを控えます。
このURLはスクリプト内に転記して使用します。

サーバ・バージョン情報

  • CentOS Linux release 7.3.1611 (Core)
  • postfix-2.10.1-6.el7.x86_64

サーバ側事前準備

必要なperlのパッケージをインストールしておきます。

sudo yum install -y perl-Email-MIME perl-JSON

スクリプトの作成

今回はわかりやすさのために/usr/local/bin/mail2slackとして保存しています。

/usr/local/bin/mail2slack
#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use JSON;
use Email::MIME;

$ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

my $curl     = '/usr/bin/curl -s --data-urlencode';
# 控えておいたWebhook URLを設定してください
my $hook_url = 'https://hooks.slack.com/services/hogehoge/foobar';
# 投稿先のチャンネルを設定してください
my $channel  = '#general',
# 投稿時の名前を設定してください
my $username = 'mail2Slack bot',
# アイコンを設定してください
my $icon_emoji  = ':house:',

my $raw_mail = join '', <STDIN>;

my $mail = &parse_mail($raw_mail);
my %json= (
  'username'    => "$username",
  'icon_emoji'    => "$icon_emoji",
  'channel' => "$channel",
  'attachments' => [
    {
      "pretext" => "「$$mail{from}」からメールが届きました。",
      "title"   => "$$mail{subj}",
      "text"    => "$$mail{body}"
    }
  ]
);

my $payload = &escape_html( 'payload=' . encode_json( \%json ) );

my $cmd=$curl . " '" . $payload . "' " . $hook_url;

system( "$cmd" );

exit;

sub parse_mail {
  my ($raw_mail) = @_;
  my $parsed_mail = Email::MIME->new($raw_mail);
  my %hash = (
    "rcpt" => scalar($parsed_mail->header('Delivered-To')),
    "from" => scalar($parsed_mail->header('From')),
    "subj" => scalar($parsed_mail->header('Subject')),
    "body" => $parsed_mail->body_str
  );
  $hash{body} =~ s/\r\n?|\n\r?/\n/g;
  return(\%hash);
}

sub escape_html {
  my ($str) = @_;
  $str =~ s/&/&amp;/g;
  $str =~ s/</&lt;/g;
  $str =~ s/>/&gt;/g;
  $str =~ s/'/&#39;/g;
  return $str;
}

メールを受信したらコマンド実行されるようにする

末尾に追記します。今回はroot宛のメールをSlackに投稿しています。

/etc/aliases
root: "| /usr/local/bin/mail2slack"

結果

私はサーバーにsshログインがあった時にメールを飛ばすように設定しているので、サーバーにログインされるたびに下記のような投稿がされるようになりました。

おわりに

駆け足で説明してしまいましたが、サーバのrootユーザに送られるメールがslackに投稿されるようになりました。
yum-cronなどはrootに結果を送ってたりして、結構メールが飛んでうざいのでslackに投稿するようになってからはメールが減って快眠出来そうです。