RedmineとSlackの連携の方法


きっかけ

最近はSlackが結構増えてきて、メールで通知受けてると見逃しそうでヤダ。
見るものを極力Slackに集約したい。

そんな中で、Redmineの通知をSlackに渡す簡単な方法を探していた。

前提

  • Redmineのサーバをいじる権限はないけど、管理者権限は持ってる
  • Slackは無料版のまま使っている
  • Slackの管理者権限は持ってる。

サーバ触れるか有料版Slackであれば、もうちょっとやりようはあったなぁ。

2019/3末を以って、IFTTTでGmailが使えなくなる

ネットで探して結構多かった手段として、
1. Redmineに通知用ユーザ追加(Gmail)
2. IFTTTにGmailアカウントで参加して、Gmailサービス+Slackサービスの設定
が多かったように思う。

しかし、2019/3末を以って、IFTTTでGmailが使えなくなるってよ。

Σ(゚Д゚)

ということで、方針を変更。

実践

設計

  1. Redmineに通知用ユーザ追加(Gmail)
  2. IFTTTにGmailアカウントで参加して、メールサービス+Slackサービスの設定
  3. Gmailから自動でIFTTTにメール転送するGASを作る

٩( ''ω'' )و

ポイントだけ解説

まぁ、設計を見れば「そうだよね」ってなる人は細かいこと要らないよね。

なので、ポイントだけ・・・

IFTTTにサインアップするメールアドレスは通知用Gmailで!

IFTTTの仕組みを微妙に分かっていなかったところとして、メールサービスって「サインアップしたメールアドレスからの受信」だったんだ。

なので、IFTTTにアカウントを作るときは作成したGmailアカウントで。

SlackとIFTTTの連携はメールアドレスは通知用Gmailで!

まぁ、言わずもがなかな。
SlackでAppの追加でIFTTTを追加するわけだけど、その時にIFTTTログインを求められる。
もちろんその時に通知用Gmailのアカウントでログインしなければならない。

GASのスクリプトはこんな感じ

通知用GmailのGoogleDriveで、新規のGoogle Apps Script(最初期は「その他」→「アプリの追加」が必要)を作成。

// XXXXXXXXXXXXXXXXXXXXはフィルタする件名
var FindSubject = 'subject:(XXXXXXXXXXXXXXXXXXXX) label:inbox -in:starred';

function getMail(){

  //指定した件名のスレッドを検索して取得 
  var myThreads = GmailApp.search(FindSubject, 0, 10); 
  //スレッドからメールを取得し二次元配列に格納
  var myMessages = GmailApp.getMessagesForThreads(myThreads);


  for(var i in myMessages){
    for(var j in myMessages[i]){  
      var strSubject = '#DrSmile ' + myMessages[i][j].getSubject();
      var strMessage = myMessages[i][j].getPlainBody().slice(0, 200);
      strMessage += AutoLink(myMessages[i][j].getBody());
      Logger.log(strMessage);
      sendMail(strSubject,strMessage);

      //処理済みのメッセージをスターをつける
      myMessages[i][j].star(); 
    }
  }
}

// チケットのリンク抽出
function AutoLink(str) {
    var regexp_url = /((h?)(ttps?:\/\/[a-zA-Z0-9.\-_@:/~?%&;=+#',()*!]+))/g; // ']))/;
    var regexp_makeLink = function(all, url, h, href) {
        return '<a href="h' + href + '">' + url + '</a>';
    }
    link = '\n\n' + str.match(regexp_url)[0]
    // タグで埋め込む場合
    //link = link.replcace(regexp_url, regexp_makeLink)
    return link;
}

// メール送信
function sendMail(strSubject,strMessage){
  var to_address = '[email protected]';
  var mail_subject = strSubject;
  var mail_body = strMessage;

  MailApp.sendEmail(to_address,mail_subject,mail_body);

}

微妙に小一時間格闘した。

  • FindSubject でフィルタ条件がなかなかツラかった(なかなか原因に気が付かず。。)
    • 検索する対象はスレッドなわけだが、そうすると送信側も抽出対象になる→ label:inbox が無いと無限ループ

これをスケジュール実行を設定する。

  • メニューから「編集」「現在のプロジェクトのトリガー」
    • 途中SSL認証で怪しい画面が出る → 「表示する」でそのまま設定

最後に

10分でできるかなーが、GASのせいで1時間かかった。。
あと、昔は絶対顔文字使わなかったのに、最近めっちゃ使う自分に驚く。