Slack × Heroku x SendGrid

Slackからメール送信できるWebアプリケーションをつくろう

15分でできる、Slack一行でメールが送れるシステム

前提条件

  • SlackとHerokuのアカウントを持っている
  • terminalなどのCLIを触ったことがある
  • XcodeとCommand Line Toolsがインストールされている
  • Homebrewがインストールされている

執筆環境

  • OS X 10.10
  • Atom 0.2

Slackとは?

いまや飛ぶ鳥を落とす勢いのチーム向けコミュニケーションツール・Slack。単にメッセンジャーとしても便利ですが、Integrationと呼ばれる外部ツールとの連携機能を使うと格段に出来ることの幅が広がります。

Hubotなどを使って様々なbotを動かしているSlackを他のTech Blogなどで見たことがある方も多いのではないでしょうか。

しかし、いくらSlackが便利でも、ビジネスではまだまだメールを使う機会が多いのも事実です。事実、SlackのCEOも「Eメールはなくならない」と言っています。

そこで、Slackからサクッとメールを送れるようにできないかなと思い、Integrationを使って簡単なWebアプリケーションを作ってみました。

Heroku、SendGridとは?

Webアプリケーションを作るためにはWebサーバが必要です。また、今回はメールを送信するのでSMTPサーバも必要になります。

これらを一から準備するのは大変なので、いま流行のPaaS・HerokuをWebサーバとして、Foursquareなどにも使われているメール送信サービス・SendGridをSMTPサーバとして使いたいと思います。

Herokuは登録さえすれば一定量までのコンピューティングを無料で行え、大変便利なのでこの機会にぜひ使ってみて下さい。
SlackでHubotを動かす際にも大抵、Herokuが使われています。

SendGridも登録さえすれば(今回はHerokuのadd-onを使うので登録する必要はありません)、一日に400通までのメールを無料で送信できるメール配信サービスです。
その他に、開封率の調査や強力なAPI連携など、便利な機能が多くあり、MailChimp(Mandrill)と人気を二分するメール配信サービスになっています。

今回は、SlackのWebHooksというIntegrationを使って、Slackから自分で設定したコマンド(「mail [送信先メールアドレス] [タイトル] [本文]」を想定)を打つことで、Herokuを通してSendGridでメールを送信するWebアプリケーションを作っていきたいと思います。

HerokuのCLIツールをインストールして、add-onを追加

以降の作業は基本的にすべてterminalで行います。

まずは、HerokuのCLIツールをインストールしましょう。$ brew install herokuと入力するとHomebrewでインストールが始まります。

CLIツールのインストールが終わったら$ heroku loginと入力し、herokuにログインします。指示に従って、Herokuのユーザー名とパスワードを入力して下さい。

ログインできたら、$ heroku createで新しいAppを作成しましょう。
作成されたら適当なディレクトリに移動し、$ heroku git:clone -a [App Name]でローカルにクローンします([App Name]はHerokuのサブドメイン部分で、$ heroku openとすれば確認できます)。

$ cd [App Name]でディレクトリに移動しましょう。
一見何のファイルもないように見えますが、「.git」という不可視フォルダがダウンロードされ、HerokuのリモートサーバとローカルがGitを使って相互に運用できるようになっています。

次に、Herokuで用意されているSendGridのadd-onを導入しましょう。
$ heroku addons:create sendgrid:starterと入力すれば完了です。

これで自動的にSendGridのアカウントが発行されます。
また、自動的にユーザー名とパスワードが、Herokuの環境変数として定義されます。

PHPでメールを送信

いよいよPHPでプログラムを書いていきますが、その前にHerokuで使われているPHPのパッケージ管理システム「Composer」をインストールしましょう。

「Composer」をHomebrewでインストールするためにはPHPもHomebrewでインストールしていなければならないので、まずはPHPをインストールします。
バージョンはHerokuと同じ最新の5.6系がいいでしょう。$ brew install homebrew/php/php56$ brew install homebrew/php/composerと入力しインストールします。

「Composer」は、Node.jsのnpmと同じような役割で、異存関係にあるプログラムなどを一括でインストールしてくれる優れもの。必要となるプログラムを「composer.json」に記述するだけです。

1
2
3
4
5
{
    "require": {
        "sendgrid/sendgrid": "~3.2"
    }
}

上のように記述し$ composer installとすれば必要なプログラムがすべて「vendor」というディレクトリにインストールされます。
自動的に作成される「composer.lock」はHerokuにpushする際に必要になるので、push前に一度は$ composer installしましょう。

App本体は「app.php」とし、以下のように記述します。
SendGridのアカウント情報はユーザー名:getenv('SENDGRID_USERNAME')、パスワード:getenv('SENDGRID_PASSWORD')と記述することで取得できます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
    require 'vendor/autoload.php';
    $sendgrid = new SendGrid(getenv('SENDGRID_USERNAME'), getenv('SENDGRID_PASSWORD'));

    $mail = new SendGrid\Email();
    $mail
        ->addTo('[送信先メールアドレス]')
        ->setFrom('[送信元メールアドレス]')
        ->setSubject('[タイトル]')
        ->setText('[本文]')
    ;

    $result = $sendgrid->send($mail);
?>

ここまできたら一旦、Herokuにプッシュしてみましょう。

まずは$ git add .でファイルをindexに登録し、$ git commit -am "[コメント]"でローカルのGitにcommit。
$ git push heroku masterでHerokuサーバにpushします。

サーバにpushすると、先ほどの「package.json」から記述したファイルがHerokuにダウンロードされている進行状況が表示されます。

pushが完了すれば、それでメールの送信も完了です。1分ほど待つと指定したメールアドレスにメールが届きます。

もう一度同じメールを送りたい場合は、AppのURLにアクセスすれば再度送信されます(何度もリロードするとその回数だけメールが届いてしまうので注意!)。

届かない場合は、空の項目がないか確認しましょう。タイトルや本文など、ひとつでも入力されていない部分があると送信されません。空にしたい場合は' 'と半角スペースを入力します。

WebHooksでSlackからPOST

Slackには、WebHooksという仕組みを用いてデータをSlack外に送信してくれる機能があります。

「Incoming WebHooks」と「Outgoing WebHooks」という二つのWebHooksがありますが、今回は「Outgoing WebHooks」を使います。
メールの送信先とタイトル、本文のデータをHerokuに受け渡し、Slackからメールを送れるようにしましょう。

「Outgoing WebHooks」は、指定した文字列に反応して起動します。

まずは設定で、起動させる文字列、データをPOSTするURLを指定しましょう。

今回は、mailという文字列に反応させたいので「mail」と入力します。
URLは先ほど作ったPHPアプリケーションのURL(https://***.herokuapp.com/app.php)です。

POSTされるデータは以下のような構成になっています。

1
2
3
4
5
6
7
8
9
10
token=XXXXXXXXXXXXXXXXXX
team_id=T0001
team_domain=example
channel_id=C2147483705
channel_name=test
timestamp=1355517523.000005
user_id=U2147483697
user_name=Steve
text=googlebot: What is the air-speed velocity of an unladen swallow?
trigger_word=googlebot:

重要なのは「text」という要素です。

app.phpで以下のように書き「text」要素が受け取れるようにしましょう。
また、半角スペースで区切ってメールアドレスとタイトル、本文を入力しているので、二行目でスペースを起点に$text_arrという変数に配列として分けて格納します。

1
2
$text = $_POST['text'];
$text_arr = preg_split('/[\s]+/', $text, 4);

次に、以下のように変数を定義しましょう。
メールアドレスは曲者で、Slackからの入力が「<to@example.com|to@example.com>」という形式になっていますので、正規表現などを使い「to@example.com」という形に直してやります。

1
2
3
4
$addTo_arr = preg_split('/[\|]+/', $text_arr[1]);
$addTo = substr($addTo_arr[1], 0, -1);
$setSubject = $text_arr[2];
$setText = $text_arr[3];

これを先ほどのapp.phpに追加し、変数を当てはめましょう。ここまで完了すると、全文は以下のようになります。
先ほどのように、URLをロードしてもメールの送信動作が起こらないよう(送信先を変数で指定しているのでどっちにしても送信はされませんが)、全体をPOSTが来たときにだけ動作するようにif ($_POST)で括っています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

if ($_POST) {
    $text = $_POST['text'];
    $text_arr = preg_split('/[\s]+/', $text, 4);

    $addTo_arr = preg_split('/[\|]+/', $text_arr[1]);
    $addTo = substr($addTo_arr[1], 0, -1);
    $setSubject = $text_arr[2];
    $setText = $text_arr[3];

    require 'vendor/autoload.php';

    $sendgrid = new SendGrid(getenv('SENDGRID_USERNAME'), getenv('SENDGRID_PASSWORD'));

    $mail = new SendGrid\Email();
    $mail
        ->addTo($addTo)
        ->setFrom('from@example.com')
        ->setSubject($setSubject)
        ->setText($setText)
    ;

    $result = $sendgrid->send($mail);
}

?>

ここまで書いたら、もう一度Herokuにpushします。
これで正常に動作するようになっているはずです。

試しに、Slackに「mail to@example.com テスト テストメールです。」と入力してみましょう。
to@example.com宛に、タイトルが「テスト」、本文が「テストメールです。」となったメールが送信されれば正常に動作しています。

JSONで「送信しました!」とフィードバックを返す

最後に、メール送信が完了したら「送信しました!」とSlackに返事が来るようにしましょう。

「Outgoing WebHooks」は、以下のようなJSON形式で結果を返すだけで、自動的にbotとしてSlackに通知してくれます。

1
2
3
{
    "text": "African or European?"
}

ですから、以下のように書き加えれば、Slackで返事が返ってくるはずです。

1
2
3
if ($result = '200') {
    echo json_encode(array('text' => '送信しました!'));
}

いかがでしょうか?
Slackからちょっとしたメールを送る際に参考にしてみて下さい。

Tech Blog

(編集部)

株式会社リクルートライフスタイルのTech Blog編集部です。いま流行りのTechネタやちょっと使えるTipsなどをお届けしていきます。

NEXT