tshのblog

tshのblog

Kindle OASISにPDFドキュメントを流し込む(その5)

前回は、Subject: が日本語の場合の動作確認を行い、EvernoteにPDFファイルを保存したり Trelloでカードを作成したりしてみました。

 

 

 

tsh.hatenablog.jp

 

今回は、今まで作成したものをまとめ、さらに便利になるようにコードを改造していきます。

evernote.comtrello.com

 

 

PDFが添付された時のみ送り込みたい

今までの例では、特にセキュリティ等を意識することなくSieveのコードを記述してきましたが、実際の運用に投入しようとするとまだまだ色々な部分が足りていません。

実際には様々なemailが届くことを想定して、まずはPDFが添付された場合にのみKindleに送り込むようにしてみます。

#test3-1
require ["copy", "fileinto", "imap4flags", "editheader", "variables", "mime", "foreverypart"];

if header :matches "Subject" "*"
{
  set "subject" "${1}";
}

if header :contains "From" "example.jp"
{
  foreverypart
  {
    if header :mime :subtype "Content-Type" "pdf"
    {
      setflag "\\Seen";
      fileinto :copy "Trash";

      deleteheader "Subject";
      addheader :last "Subject" "convert";
      redirect "example_to_kindle@kindle.com";
      break;
    }
  }
}

PDFが添付された時のみ(1)Kindleへ送り込み(Kindle形式)とゴミ箱に既読で保存、(2)それ以外のメールの場合には何もしない(受信トレイに保存)動作にしています。

 

今までの一連の動作をまとめてみる

それでは皆様お待ちかねの、一連の自動処理をまとめてみます。

念のためもう一度整理しておくと、

  1. PDFファイルが特定のFrom:アドレスから添付されてきたら、
  2. KindleKindle形式に変換して送り込み
  3. Evernoteの所定のノートブックへ保存
  4. Trelloのカードを自動作成、タイトル先頭に「【Kindle】」を追加、念のためPDFも添付

という感じで、今までのSieveのコードを整理してみます。

#test3-2
require ["copy", "fileinto", "imap4flags", "editheader", "variables", "mime", "foreverypart"];

if header :matches "Subject" "*"
{
  set "subject" "${1}";
}

if header :contains "From" "example.jp"
{
  foreverypart
  {
    if header :mime :subtype "Content-Type" "pdf"
    {
      setflag "\\Seen";
      fileinto :copy "Trash";

      # for kindle
      deleteheader "Subject";
      addheader :last "Subject" "convert";
      redirect :copy "example_to_kindle@kindle.com";

      #for evernote
      deleteheader "Subject";
      addheader :last "Subject" "${subject} @テスト";
      redirect :copy "example_to_evernote@m.evernote.com";
  
      #for trello
      deleteheader "Subject";
      addheader :last "Subject" "【Kindle】 ${subject} @exampleuser";
      redirect "example_to_trello@boards.trello.com";     
      break;
    }
  }
}

と、こんな感じになりました。

これでも十分動くといえば動くのですが、「Kindleには送り込みたいけれど、Evernoteへ保存しなくても良いメールもある」だとか「優先度が低いので、Trelloのカード起票は特に不要」だとか、要望が増えてくるたびにパターンごとに応じて似たようなことを何回も記述しなくてはいけません。というわけで、もう少し工夫してみます。

 

スクリプトを分割

先程のコードをよく見ると、処理単位ごとにコメントが書かれています。実際の処理には関係しないのですが人間が見て分かりやすいように、といった意図を感じます(大げさ)。こういった場合はリファクタリングの定番、まとまりごとに別ファイルに切り出してみます。

 

test3-3

#test3-3
require ["include", "variables", "fileinto", "imap4flags", "mime", "foreverypart"];
global "subject";

if header :matches "Subject" "*"
{
  set "subject" "${1}";
}

if header :contains "From" "example.jp"
{
  foreverypart
  {
    if header :mime :subtype "Content-Type" "pdf"
    {
      include "send-kindle";
      include "send-evernote";
      include "send-trello";

      setflag "\\Seen";
      fileinto "Trash";
      break;
    }
  }
}

 

send-kindle

# send-kindle
require ["include", "copy", "editheader"];

deleteheader "Subject";
addheader :last "Subject" "convert";
redirect :copy "example_to_kindle@kindle.com";

 

send-evernote

# send-evernote
require ["include", "copy", "editheader", "variables"];
global ["subject"];

deleteheader "Subject";
addheader :last "Subject" "${subject} @テスト";
redirect "example_to_evernote@m.evernote.com";

 

send-trello

# send-trello
require ["include", "copy", "editheader", "variables"];
global ["subject"];

deleteheader "Subject";
addheader :last "Subject" "【Kindle】 ${subject} @tshtsh";
redirect :copy "example_to_trello@boards.trello.com";

と、かなり分かりやすくなりました。

何がうれしいかというと、(1)似たような処理をあちこち書かずに一元管理できる、(2)単純な処理のまとまり毎にデバッグできるので、問題発生時にも対処しやすい、(3)実際に送信したい場所でincludeしてしまえばいいので、見た目も単純化され理解しやすい、とメリットだらけです。

 

複数の From: に対応する

PDFが添付されたら自動処理したい送信元アドレスは一つだけとは限りませんよね。むしろ複数ある方が自然だとも言えます。 それでは複数の送信元に対応してみましょう。

#test3-4
require ["include", "variables", "fileinto", "imap4flags", "mime", "foreverypart"];
global "subject";

if header :matches "Subject" "*"
{
  set "subject" "${1}";
}

if anyof
  (
    header :contains "From" "example1.jp",
    header :contains "From" "exmaple2.jp"
  )
{
  foreverypart
  {
    if header :mime :subtype "Content-Type" "pdf"
    {
      include "send-kindle";
      include "send-evernote";
      include "send-trello";

      setflag "\\Seen";
      fileinto "Trash";
      break;
    }
  }
}

 はい、こんな感じになります、、。送信元が増えるとコードのチェック部分を増やしていく事になリます。

 

送信元毎にEvernoteの保存先を変更する

よく考えると、送信元毎にEvernoteの保存先も変えたいものですよね。

というわけで、もう少し工夫してみます。

まずは、Evernoteの保存先を変えられるようにしてみます。

 

send-evernote

# send-evernote
require ["include", "copy", "editheader", "variables"];
global ["evernote_notebook"];

deleteheader "Subject";
addheader :last "Subject" "${subject} @${evernote_notebook}";
redirect "example_to_evernote@m.evernote.com";

 test3-5-1

#test3-5-1
require ["include", "variables", "fileinto", "imap4flags", "mime", "foreverypart"];
global "subject";
global "evernote_notebook";

if header :matches "Subject" "*"
{
  set "subject" "${1}";
}

if anyof
  (
    header :contains "From" "example1.jp",
    header :contains "From" "example2.jp"
  )
{
  foreverypart
  {
    if header :mime :subtype "Content-Type" "pdf"
    {
      include "send-kindle";
      
      set "evernote_notebook" "テスト";
      include "send-evernote";

      include "send-trello";

      setflag "\\Seen";
      fileinto "Trash";
      break;
    }
  }
}

次に、送信元毎にEvernoteの保存先を変えてみます。

 

#test3-5-2
require ["include", "variables", "fileinto", "imap4flags", "mime", "foreverypart"];
global "subject";
global "evernote_notebook";

if header :matches "Subject" "*"
{
  set "subject" "${1}";
}

if header :contains "From" "exmaple1.jp"
{
  set "evernote_notebook" "テスト1";
}
elsif header :contains "From" "example2.jp"
{
  set "evernote_notebook" "テスト2";
}

if anyof
  (
    header :contains "From" "example1.jp",
    header :contains "From" "example2.jp"
  )
{
  foreverypart
  {
    if header :mime :subtype "Content-Type" "pdf"
    {
      include "send-kindle";
      include "send-evernote";
      include "send-trello";

      setflag "\\Seen";
      fileinto "Trash";
      break;
    }
  }
}

 はい、これで動作するようにはなりました。が、送信元アドレスを増やす毎に複数箇所を修正しなくてはいけないので、もう少しまとめてみます。

 

#test3-5-3
require ["include", "variables", "fileinto", "imap4flags", "mime", "foreverypart", "relational"];
global "subject";
global "evernote_notebook";

if header :matches "Subject" "*"
{
  set "subject" "${1}";
}

if header :contains "From" "example1.jp"
{
  set "evernote_notebook" "テスト1";
}
elsif header :contains "From" "example2.jp"
{
  set "evernote_notebook" "テスト2";
}

if string :count "eq" "${evernote_notebook}" "1"
{
  foreverypart
  {
    if header :mime :subtype "Content-Type" "pdf"
    {
      include "send-kindle";
      include "send-evernote";
      include "send-trello";

      setflag "\\Seen";
      fileinto "Trash";
      break;
    }
  }
}

 これで、送信元アドレスによってEvernoteの保存先を自由に選べるようになりました。

 

送信元毎にKindle形式に変換するかどうかを決める

 これもありがちですよね。テキスト中心のドキュメントならKindle形式、表とかグラフとかが多いのならPDF形式にしたいのですが、今のところ送信元のアドレスによって決めることにします。

 

#test3-5-4
require ["include", "variables", "fileinto", "imap4flags", "mime", "foreverypart", "relational"];
global "subject";
global "kindle_convert";
global "evernote_notebook";

if header :matches "Subject" "*"
{
  set "subject" "${1}";
}

if header :contains "From" "example1.jp"
{
  set "kindle_convert" "true";
  set "evernote_notebook" "テスト1";
}
elsif header :contains "From" "example2.jp"
{
  set "evernote_notebook" "テスト2";
}

if string :count "eq" "${evernote_notebook}" "1"
{
  foreverypart
  {
    if header :mime :subtype "Content-Type" "pdf"
    {
      include "send-kindle";
      include "send-evernote";
      include "send-trello";

      setflag "\\Seen";
      fileinto "Trash";
      break;
    }
  }
}

 

# send-kindle
require ["include", "copy", "editheader", "variables", "relational"];
global ["subject"];
global ["kindle_convert"];

if string :count "eq" "${kindle_convert}" "1"
{
  deleteheader "Subject";
  addheader :last "Subject" "convert";
}
else
{
  deleteheader "Subject";
  addheader :last "Subject" "${subject}";
}
redirect :copy "exmaple_to_kindle@kindle.com";

 念のため、Kindle形式へ変換しない場合にはSubject: を元の状態へ戻してあります。

 

送信元毎にTrelloのアサインユーザーを変える

Trelloのカードにアサインするユーザーを送信元によって変えます。Trelloの仕様上複数人アサインできますが、今回は1人のみとします。

もうここまで来れば、似たようなパターンでできることに気づかれたと思います。

 

#test3-5-5
require ["include", "variables", "fileinto", "imap4flags", "mime", "foreverypart", "relational"];
global "subject";
global "kindle_convert";
global "evernote_notebook";
global "trello_assign";

if header :matches "Subject" "*"
{
  set "subject" "${1}";
}

if header :contains "From" "exmaple1.jp"
{
  set "kindle_convert" "true";
  set "evernote_notebook" "テスト1";
  set "trello_assign" "exampleuser1";
}
elsif header :contains "From" "example2.jp"
{
  set "evernote_notebook" "テスト2";
  set "trello_assign" "exampleuser2";
}

if string :count "eq" "${evernote_notebook}" "1"
{
  foreverypart
  {
    if header :mime :subtype "Content-Type" "pdf"
    {
      include "send-kindle";
      include "send-evernote";
      include "send-trello";

      setflag "\\Seen";
      fileinto "Trash";
      break;
    }
  }
}

 

# send-trello
require ["include", "copy", "editheader", "variables"];
global ["subject"];

deleteheader "Subject";
addheader :last "Subject" "【Kindle】 ${subject} @${trello_assign}";
redirect :copy "exmaple_to_trello@boards.trello.com";

まとめ

今回は、PDFが添付されていたら実行するようにしたり、1通のメールで複数のサービスが動作するようにしたり、複数の送信元に対応したりしました。

次回は、今回のコードをさらに改造し使いやすくする予定です。お楽しみに。

 

evernote.com

trello.com

 

前回までの記事はこちらです。

tsh.hatenablog.jp

tsh.hatenablog.jp

tsh.hatenablog.jptsh.hatenablog.jp