詩と創作・思索のひろば

ドキドキギュンギュンダイアリーです!!!

Fork me on GitHub

コマンドラインでメールの内容に基づいた処理をするツールを書いた: letterknife

メールに対する jq みたいなやつ……というと強力すぎるけど、そういう感じにメールを入力に受け取って何かしらの処理をした上で出力してくれるツールです。ここでいうメールとは MIME 形式のメール全体。Gmail なら "Show original" で見られるようなもの。

結局ターミナルでメールを読むことにした に書いたとおり最近はターミナルでメールを読むようになりそこそこ快適なんだけど、メールとの接し方がプログラマブルになったからには楽をしたい。だいたい通知のメールのこの部分をクリックするだけ(そして承認したりコメントしたりする)、みたいなパターンが決まってるものには DWIM(do what I mean)的にキー入力一発で対応したいわけです。それをやるためのツールとして書いた。珍しく名前を気に入ってる。

GitHub - motemen/letterknife

使い方

$ cat <email> | letterknife [条件] [パートの選択] [アクション]

というふうに標準入力に MIME メッセージ全体を渡し、適当な出力を得る、という感じ。

たとえば、

  • @example.com からのメールの場合
  • HTML メールのパートを選択して
  • 表示する

ってことをしたければ

$ letterknife --match-address "From:*@example.com" --select-part text/html --print-content < eml

という感じ。省略形も用意していて

$ letterknife --from "*@exmaple.com" --html

だけでもいい。ちなみに From の条件がマッチしなかった場合や HTML なパートが存在しなかった場合は、コマンドは失敗する。

もう一つ例を用意すると

  • 件名に「請求」が含まれていたら
  • 添付の PDF を
  • ファイルとして保存する

であれば

$ letterknife --subject "*請求*" --select-attachment application/pdf --save-file

とする。標準出力には一時的に保存されたファイルへのパスが出力されるのでこれを mv するなどしたらよろしい。

オプションの全体はこんな感じ。まあやりたいことはだいたいできるんじゃないでしょうか。

% letterknife --help
Usage of letterknife:
      --from <pattern>                     Shortcut for --match-address 'From:<pattern>'
      --subject <pattern>                  Shortcut for --match-header 'Subject:<pattern>'
      --html                               Shortcut for --select-part text/html
      --plain                              Shortcut for --select-part text/plain
      --match-address <header>:<pattern>   Filter: address header <header>:<pattern> eg. "From:*@example.com"
      --match-header <header>:<pattern>    Filter: header <header>:<pattern> eg. "Subject:foobar"
      --select-part <content-type>         Select: non-attachment parts by <content-type>
      --select-attachment <content-type>   Select: attachments by <content-type>
      --print-content                      Action: print decoded content
      --print-header <header>              Action: print <header>
      --print-raw                          Action: print raw input as-is
      --save-file                          Action: save parts as files and print their paths
      --debug                              enable debug logging

letterknife でメールの定形処理をシェルスクリプト化する

あとはこれを使ってちょっとしたシェルスクリプトを書いて、neomutt からメールをパイプするキーを割り当てればキー一発で DWIM 的な処理を行える。

サンプルとして書くとこういう感じ:

#!/bin/bash

set -eo pipefail

mail=$(cat)

url=$(
  { letterknife --from '*@github.com' --html | pup 'a:contains("view it on GitHub") attr{href}'; } <<< "$mail" || \
  { letterknife --from '*@example.com' --plain <<< "$mail" | grep https://... | tail -1; } <<< "$mail" || \
  false
)

if [ -n "$url" ]; then
  if [ -n "$DEBUG" ]; then
    echo "$url"
  else
    open "$(echo "$url" | tr -d '\r\n')"
  fi
fi

letterknife を || でつなぎつつ、条件にマッチするまで何度も呼び出している。すでに手元だと10件以上の条件があってだんだん遅くなっていくんだろうなーと思うけどマウスでクリックするよりはだいぶマシ。HTML メールは pup で処理するとやりやすい。最終的にはメール中のひとつの URL を得て、ブラウザで開くだけ、というわけなのさ……。

はてなで一緒に働きませんか?