メールに対する jq みたいなやつ……というと強力すぎるけど、そういう感じにメールを入力に受け取って何かしらの処理をした上で出力してくれるツールです。ここでいうメールとは MIME 形式のメール全体。Gmail なら "Show original" で見られるようなもの。
結局ターミナルでメールを読むことにした に書いたとおり最近はターミナルでメールを読むようになりそこそこ快適なんだけど、メールとの接し方がプログラマブルになったからには楽をしたい。だいたい通知のメールのこの部分をクリックするだけ(そして承認したりコメントしたりする)、みたいなパターンが決まってるものには DWIM(do what I mean)的にキー入力一発で対応したいわけです。それをやるためのツールとして書いた。珍しく名前を気に入ってる。
使い方
$ 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 を得て、ブラウザで開くだけ、というわけなのさ……。