Macでpostfixのメール受信を契機にRubyでSlackのWebhookに送信

## 背景
 - Macで定期Job(cron)でスクレイピング処理を実行
 - cron実行時に、標準エラー出力(=2)の場合、postfixにメールが飛ぶ
 - メール受信を契機に何かしらで通知を受け取りたい

Rubyが実行された後のエラーについては、別途ハンドリングして通知する仕組みがある。
しかし、端末由来のエラー(ex. ライブラリ不整合, 端末不具合, ネットワーク不具合 etc)が拾えてない。

## 環境

```shell
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.3
BuildVersion:	18D109

$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin18]

$ which postfix
/usr/sbin/postfix
```
```
$ crontab -l
0 7 * * 1-7 ruby [ファイル] 1>/dev/null
```

## 作業フロー
  1. Postfixについて
  2. Postfixの設定
  3. SlackWebhook用URLの発行
  4. rubyプログラム追加
  5. 動作確認
  
### 1. Postfixについて
恐らくMacに標準で入っているはず。
なかったらググる。
インストールとかは省きます。
  
#### 1-1. 各種ディレクトリ
 - 既読にしたメール
  - ~/mbox
 - 設定ファイル
  - /etc/aliases
  - /etc/postfix/main.cf

#### 1-2. メールの確認＆送信
 - メールの送信([参考](https://blog.ch3cooh.jp/entry/20170704/1499130000))
 
```shell
# メール送信
$ date | mail -s test [端末のユーザー名]@[端末のユーザー名].local
# メール確認
$ mail
```
```shell
# メール一覧
>N  1 [アドレス] Fri Mar  1 10:51 102/10829 [エラー内容]
 N  2 [アドレス] Fri Mar  1 16:15  30/2363  [エラー内容]
 N  3 [アドレス] Fri Mar  1 16:20  30/2372  [エラー内容]
```
```shell

# メールコマンド後に、対象のメールを選択
? 1
```
```shell
# メール内容
From [端末のユーザー名]@[端末のユーザー名].local  Tue Mar 26 14:57:56 2019
X-Original-To: [端末のユーザー名]@[端末のユーザー名].local
Delivered-To: [端末のユーザー名]@[端末のユーザー名].local
To: [端末のユーザー名]@[端末のユーザー名].local
Subject: test
Date: Tue, 26 Mar 2019 14:57:56 +0900 (JST)
From: [端末のユーザー名]@[端末のユーザー名].local

2019年 3月26日 火曜日 14時57分56秒 JST #-> ここにエラーメッセージとかが表示
```

#### 1-3. 他参考
 - [受信イベントを契機にプログラムを実行](http://k-1-ne-jp.blogspot.com/2013/01/postfix_11.html)
 - [メール受信をトリガーにプログラムを起動する](http://k-1-ne-jp.blogspot.com/2013/01/postfix_11.html)
 - [alias駆動プログラムの実行ユーザーを任意のユーザーからの実行にする](http://www.omakase.org/mail/aliasenobody.html)

### 2. Postfixの設定

#### 2-1. 設定ファイルを編集

 - /etc/aliases
 - /etc/postfix/main.cf

```shell
# わかりやすいように、ユーザー名を指定
$ echo $USER
hoge
```
```shell
$ sudo vi /etc/aliases
-----
[/etc/aliases]
  # Put your local aliases here.
  hoge: hoge, :include:/Users/hoge/sample 
  # ・/Users/hoge/sampleファイルを作成する
  # ・hoge, がないと、メールがパイプで転送されてmailコマンドで見れなくなる
-----
```
```shell
$ sudo vi /etc/postfix/main.cf
-----
[/etc/postfix/main.cf]
alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
allow_mail_to_commands = alias,forward,include
-----
```
#### 2-2. 設定を反映
```shell
$ sudo newaliases
$ sudo postfix reload
```

#### 2-3. /Users/hoge/sampleファイルの作成
```shell
$ vi /Users/hoge/sample
-----
[/Users/hoge/sample]
"|cd /Users/hoge/hoge_project/ && /Users/hoge/.rbenv/shims/bundle exec ruby test.rb"
-----
```

#### 2-4. Tips

[メール受信をトリガーにプログラムを起動する](http://k-1-ne-jp.blogspot.com/2013/01/postfix_11.html)

の前者のやり方だと、実行ユーザーの問題でエラーになった。

なので、後者のやり方↓

[alias駆動プログラムの実行ユーザーを任意のユーザーからの実行にする](http://www.omakase.org/mail/aliasenobody.html)

を採用した形

### 3. SlackWebhook用URLの発行
ちょい古いが...[この辺り](http://48n.jp/blog/2015/09/28/introduce-slack-incoming-webhooks/)を参考に

### 4. /Users/hoge/hoge_project/test.rbの作成
```shell
$ vi /Users/hoge/hoge_project/test.rb
```
```ruby
# ---
[/Users/hoge/hoge_project/test.rb]
require 'fileutils'
require 'slack/incoming/webhooks'

# TODO: 3. SlackWebhook用URLの発行で取得したURLを設定する
url = 'https://hooks.slack.com/services/xxxxxxxxxxxxxxxx'

std_in_str = STDIN.read.to_s
message = '```' + std_in_str.force_encoding("utf-8") + '```'
slack = Slack::Incoming::Webhooks.new url
slack.post message, link_names: true
# ---

# gem 'slack-incoming-webhooks' が必要なので良しなに
# STDINがなぜかASCIIだったので、強制エンコードしてる
```

#### 5. 動作確認
```shell
$ date | mail -s test hoge@hoge.local
↓
Slackの対象チャンネルに飛ぶことを確認!!
```

## まとめ
あんまり意識してなかったpostfixを有効に使えそうということで、今回仕組みを追加してみました。
postfixはローカルからのメールしか受け付けてないので、他の諸々は特に考えてません。
これで障害とかに早く気付けるようになればいいなー....泣