43
51

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

メールが届いたらその内容をslack/mattermostに投稿する

Last updated at Posted at 2019-05-19

TL;DR

メールが届いたらこんな感じのメッセージをslack/mattermostにpostする仕組みを作りました.
qiita3.png

はじめに

slack / mattermostを始めとするチャットツールは普及してきていますが,様々な事情により,完全にメールを使わないで仕事をすることは難しいと思います.とはいえ定期的にメーラをチェックするのもめんどくさいですね.なので,メールが届いたらその内容をslack / mattermostに通知し,通知内容を見て必要があれば返信すればよいのではと考えました.

何らかの事情によりメールを見る環境と普段作業をする環境が分断されている方にもおすすめです.1

前提

  • メーラとしてThunderBirdを利用していること

具体的な手順

incoming webhookの取得

今回は届いたメールの内容をpostするため,incoming webhookを取得します.具体的な手順は既に解説記事がたくさんあるので省略します.
slackの場合はこちら,mattermostの場合はこちらをご参照ください.

FiltaQuillaの導入

ThunderBirdのアドオン,FiltaQuillaをインストールします.
FiltaQuillaは,メール受信時のフィルタやそれに対するアクションを拡張するアドオンです.フィルタ条件として正規表現が使えるため,その用途で利用されることが多いですが,今回はアクションとして任意のスクリプトを実行できる機能を主に利用します.

上記のアクション機能は,デフォルトではオフになっています.そのため, ハンバーガーメニュー > アドオン > FiltaQuilla から,JavaScript Action with Body にチェックを入れ,Thunderbirdを再起動します.
qiita1.png

ハンバーガーメニュー > メッセージフィルター > メッセージフィルター より,新しくフィルタを作り,以下の動作を実行する の選択肢の中に Javascript Action with Body があればOKです.アクション選択の右側にあるアイコンをクリックするとウインドウが開き,任意のjavascriptを書くことができます.
image.png

例えば,以下のようなプログラムを書くと,受信したメールのタイトルの前に [Hello, World] とprefixをつけることができます.

for (let index = 0; index < msgHdrs.length; index++){
  let hdr = msgHdrs.queryElementAt(index, Ci.nsIMsgDBHdr);
  hdr.subject = "[Hello, World] " + hdr.subject;
}

ちなみに,アクションの選択肢の中には Run Program というものがあり,ローカルにある任意の実行ファイルを実行することができます.しかしこの動作は,メールのヘッダを受信した段階で起動するようで,プログラムに対してヘッダに関する情報を渡すことができますが,本文等のヘッダに含まれない情報は渡すことができません 参考
一方, JavaScript Action with Body に関しては,公式サイトに以下のような記述があります.

The “Javascript Action with Body” delays the application of the filter until the body has been downloaded.

つまり,メールの受信が完了してからJavascriptが起動するようなので,こちらのアクションを使えばメール本文を取得することができます.

実行するjavascriptを書く

ここからは上記のアクションに指定するjavascriptを書いていきます.とりあえず動かしたい方は最終的なjavascriptコードまで読み飛ばしてください.
コードを実行して動かなくなった場合には,開発ツールボックス (Ctrl + Shift + I) の コンソール タブを開くとデバッグしやすいかと思います.

postする要素の取得

まずhdrオブジェクトを取得します.

let hdr = msgHdrs.queryElementAt(index, Ci.nsIMsgDBHdr);

hdrオブジェクトにはメールヘッダに関する情報が含まれており,簡単にSubjectやAuthor, Cc, Bcc情報を取得することができます.これらの他に取得できる項目については公式ドキュメントを参照してください.

subject = hdr.mime2DecodedSubject
author = hdr.mime2DecodedAuthor
cc = hdr.ccList
bcc = hdr.bccList

hdrオブジェクトの要素として,hdr.subjecthdr.author がありますが,これらの要素にはMIMEエンコードされた文字列が格納されています.そのため,日本語が含まれる件名や長い件名を扱う場合には hdr.mime2DecodedSubject, hdr.mime2DecodedAuthor を使う点に注意してください.
何かの事情でMIMEデコードをする場合にはこちらこちら を利用するのが良いと思います.

bodyについては,このサイトを参考に,以下のようにして取得しました.

let messenger = Components
    .classes["@mozilla.org/messenger;1"]
    .createInstance(Components.interfaces.nsIMessenger);
let listener = Components
    .classes["@mozilla.org/network/sync-stream-listener;1"]
    .createInstance(Components.interfaces
        .nsISyncStreamListener);
let uri = hdr.folder.getUriForMsg(hdr);
messenger.messageServiceFromURI(uri)
    .streamMessage(uri, listener, null, null, false, "");
let body = hdr.folder.getMsgTextFromStream(listener.inputStream,
    hdr.Charset, 65536, 32768, false, true, {});

postするjsonの作成

取得した要素を並べてpostするjsonを作成します.mattermostの場合だとmarkdown記法を利用することもできます.

const data = {
    "text": "件名:" + subject + "\n"
            + "送信元: " + author + "\n"
            + "Cc: " + cc + "\n"
            + "Bcc: " + bcc + "\n"
            + "本文\n"
            + body
};

postする

XMLHTTPRequestを用いてデータをpostします.mattermostでうまく動かない場合は,HTTPヘッダの content-typeapplication/json を指定していないのが原因かもしれません.

const xml = new XMLHttpRequest();
xml.open("POST", url, false);
xml.setRequestHeader("content-type", "application/json");
xml.send(`${JSON.stringify(data)}`)

最終的なjavascriptコード

最終的には下記のようなjavascriptコードになります.デバッグをしやすくするため,consoleへ出力するコードも残してあります. 利用される際は,1-2行目の url を取得したwebhook urlに置き換えてください.

const url = "https://your.mattermost.url/hooks/xxxxxxxxxxx"; // mattermost
const url = "https://hooks.slack.com/services/xxxxxxxxxxx";  // slack

for (let index = 0; index < msgHdrs.length; index++) {
    let hdr = msgHdrs.queryElementAt(index, Ci.nsIMsgDBHdr);

    // subject
    subject = hdr.mime2DecodedSubject
    Cu.reportError(" flt log1: " + subject);

    // message body
    let messenger = Components
        .classes["@mozilla.org/messenger;1"]
        .createInstance(Components.interfaces.nsIMessenger);
    let listener = Components
        .classes["@mozilla.org/network/sync-stream-listener;1"]
        .createInstance(Components.interfaces
            .nsISyncStreamListener);
    let uri = hdr.folder.getUriForMsg(hdr);
    messenger.messageServiceFromURI(uri)
        .streamMessage(uri, listener, null, null, false, "");
    let body = hdr.folder.getMsgTextFromStream(listener.inputStream,
        hdr.Charset, 65536, 32768, false, true, {});
    Cu.reportError(" flt log2: " + body.length + " " + body);

    // author
    author = hdr.mime2DecodedAuthor
    Cu.reportError(" flt log3: " + author);

    // Cc, Bcc
    cc = hdr.ccList
    bcc = hdr.bccList

    // formatting data
    const data = {
        "text": "## 件名:" + subject + "\n"
                + "## 送信元: " + author + "\n"
                + "## Cc: " + cc + "\n"
                + "## Bcc: " + bcc + "\n"
                + "## 本文\n"
                + body
    };

    // POST
    const xml = new XMLHttpRequest();
    xml.open("POST", url, false);
    xml.setRequestHeader("content-type", "application/json");
    xml.send(`${JSON.stringify(data)}`)
}

動かしてみる

プロジェクトA が件名に含まれる場合にアクションを起こすよう設定して,メールを送ってみます.すると…
image.png

通知が届きました!
qiita3.png

さらに,mattermostではmarkdown記法が使えるので,もうちょっとリッチな表現にすることができます.例えばpostするjsonを書き換えて,緊急 という文字列がタイトルに含まれているときにこのようなデータをpostする,という新しいルールを加えると...

const data = {
    "attachments": [{
        "color": "#FF8000",
        "text": "件名: " + subject + "\n"
            + "送信元: " + author + "\n"
            + "Cc: " + cc + "\n"
            + "Bcc: " + bcc + "\n"
            + "本文\n"
            + body
    }]
};

緊急性の高いものだけを目立たせることができます.
image.png

まとめ

ThunderbirdのプラグインFiltaQuillaを使って,slack/mattermostに新着メールの情報をpostする方法について説明しました.本記事では説明しませんでしたが,postするチャンネルを条件によって変えて,そのチャンネルへのpostだけスマホに通知するようにすれば,重要なメールが来たときにだけスマホを鳴らすようにすることもできます.また,今回はslack/mattermostへの通知でしたが,FiltaQuillaを使えば任意のjavascriptを動かすことができるため,もっと面白い使い方があるかもしれません.

参考サイト

  1. 自己責任でお願いします.

43
51
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
51

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?