Thunderbirdのメール新規作成を利用する

前回、WindowsからiPhoneへテキストを送る方法としてまずはメールを使ってみようということにし、その第一弾としてPowerShellから新規メールを作成する方法を取り上げた。前回の成果物は、次の通りだ。

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' -compose
  • 実行結果

    実行結果

今回はこの処理をさらに作り込み、「後は送信ボタンを押すだけ」という状態へ持って行こう。

オプションで宛先やタイトル、本文を作る

Thunberbirdはコマンド引数で宛先やサブジェクトなどを指定することができる。この手軽さがThunderbirdの魅力の一つだ。例えば、次のような感じで実行すると、宛先(To:)が入力された状態でThunderbirdの新規メール作成ウインドウを起動することができる。

宛先(To:)を指定してThunderbirdを起動

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    to=iphoneaccount@example.com
  • 宛先(To:)が指定された状態で起動してくる

    宛先(To:)が指定された状態で起動してくる

なお、コマンドが長くなってくるので途中で改行してある。最終的にPowerShellスクリプトに落とし込んでいくので、適度に改行すると読みやすくなる。

今度は次のように実行してみよう。このような指定で宛先に加えてサブジェクトも指定できる。

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    "to=iphoneaccount@example.com,subject=タイトル"
  • 宛先(To:)とタイトル(Subject:)が指定された状態で起動してくる

    宛先(To:)とタイトル(Subject:)が指定された状態で起動する

PowerShellで指定する場合は、この「to=」や「subject=」の指定全体をダブルクォーテーションで囲っている点に注目しよう。こうしないと、意図したようにThunderbirdへ引数が渡ってくれない。

次はさらに本文を追加だ。次のように「body=」の指定も追加すると、宛先(To:)とタイトル(Subject:)に加えて本文も追加された状態でThunderbirdの新規メールが起動する。

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    "to=iphoneaccount@example.com,subject=タイトル,body=ここが[ 本文 ]"
  • 宛先(To:)とタイトル(Subject:)と本文が指定された状態で起動してくる

    宛先(To:)とタイトル(Subject:)と本文が指定された状態で起動する

指定する内容が長くなってきたので、引数として渡している内容をいったん変数に格納してから使うようにしてみよう。次のような感じだ。

$to="iphoneaccount@example.com"
$title="タイトル"
$body="ここが[ 本文 ]"

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    "to=$to,subject=$title,body=$body"

ここでもう一つ注目したい点は、本文に空白文字を含めてある点だ。それでも、うまく値が渡っていることがわかる。引数に値を渡す際は、正しく値を渡せるようにいくつかの文字についてはエスケープ記述をしなければならない。空白文字を含めたのは、そのままでも空白文字を含めることができるかどうかを試したかったからだ。こんな感じで、使えない文字を探して一つずつ解決していくことになる。

シェルスクリプトのプログラミングの経験や、Makefileを書いた経験があるなら、シェルのエスケープとコマンド自体が内部で処理するテキストのエスケープ処理に頭を悩ませたことがあるのではないだろうか。コマンドライン引数から値を渡せるのは便利ではあるのだが、常にこのエスケープ処理という手間が伴う。

PowerShellがどのような引数分解を行うかや、エスケープ処理の規則を持っているのかは文書化されているのだが、それだけで全てが理解できれば苦労はない。この部分は、どんなプログラミング言語でもトライ&エラーを繰り返して仕上げることになる。

エスケープ表記と取っ組み合う

さて、最も基本的な使い方は上記の通りだ。次はこれを現実的に使える内容まで落とし込んでいく。

先ほどの指定方法だと宛先、タイトル、本文は「to=宛先,subject=タイトル,body=本文」という指定になっていた。「,」で区切っているのだ。勘の鋭い方ならここですでに嫌な予感がしているかもしれないが、値に「,」が含まれている場合はどうなってしまうのだろうか。

そこで、次のようにタイトルと本文に「,」を含めて実行してみる。

$to="iphoneaccount@example.com"
$title="タイトル, title"
$body="本文, honbun"

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    "to=$to,subject=$title,body=$body"
  • 「、」以降が消えている

    「,」以降が消えている

実行すると上記のように「,」以降が消えていることがわかる。先ほどの指定は「to=iphoneaccount@example.com,subject=タイトル, title,body=本文, honbun」となるので、subjectの指定は「タイトル」だけ、本文は「本文」だけが指定されていることになってしまう。つまり、値に「,」を含めることができない。

エスケープ処理について説明するととても長くなるので、今回は回避する方法に焦点を当てて説明していく。まず、このケースについては変数をシングルクォートで囲むことで回避できる。次のように実行してみよう。

$to="iphoneaccount@example.com"
$title="タイトル, title"
$body="本文, honbun"

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    "to='$to',subject='$title',body='$body'"
  • 値として「、」が含まれていることを確認

    値として「,」が含まれていることを確認

タイトルと本文に値として「,」が含まれていることが確認できると思う。

ここで危機回避能力が高い方なら、エスケープさせるために「'」を使ったことで、今度は値としての「'」が問題を引き起こすのではないか、と考えるだろう。実に鋭い。エスケープすることで、さらに別のエスケープが必要になるのはよくあることだ。

では実際に試してみよう。次のように値にシングルクォートを含めて実行してみる。

$to="iphoneaccount@example.com"
$title="タイトル, 'title'"
$body="本文, 'honbun'"

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    "to='$to',subject='$title',body='$body'"
  • 「、」も「'」も値として含まれた状態で起動してくる

    「,」も「'」も値として含まれた状態で起動してくる

PowerShellは、上記のようにこの場合のシングルクォートは値として扱ってくれる。PowerShellはUNIX系のシェルのようだが、実際にはオブジェクト指向のプログラミング言語であり、PowerShellでは比較的、人間が求めているような展開が行われるのだ。

システムクリップボードからテキストを持ってくる

ではさらに目的とするかたちに近づけていこう。ここではシステムクリップボードのテキストをiPhoneで扱いたいので、システムクリップボードから直接値を持ってきて、メールの本文に使うように書き換える。Get-Clipboardコマンドレットを使えば、システムクリップボードからテキストを取得できる。タイトルもわかりやすいように整えて、次のような感じにする。

$to="iphoneaccount@example.com"
$title="from Windowsシステムクリップボード"
$body=$(Get-Clipboard)

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    "to='$to',subject='$title',body='$body'"

では動作を試してみよう。まず、次のようにコマンドレット(プロセス一覧を表示するGet-Processコマンドレット)の出力をシステムクリップボードへコピーする。

Get-Process | tail -20 | clip.exe

そのあとで上記PowerShellスクリプトを実行すると、次のようになる。

  • 改行が消えている

    改行が消えている

改行が消えていることがわかる。先ほどのエスケース記述では足りないのだ。

改行と空白のエスケープと取っ組み合う

PowerShellを扱っているとついつい忘れがちになるが、PowerShellでやり取りされるのはテキストではなくオブジェクトである。UNIX系のシェルと同じ要領で考えるとうまくいかない。$bodyに入っているのはオブジェクトなので、まずはこれを文字列に変換する必要がある。オブジェクトのままだとコマンドライン引数で使われる段階で自動的にテキストに変換され、その際に改行コードが消えてしまうのだ。

そんなわけで、まず次のようにシステムクリップボードから持ってきたデータ(オブジェクト)を文字列へ変換して使うように書き換える。

$to="iphoneaccount@example.com"
$title="from Windowsシステムクリップボード"
$body=$(Get-Clipboard | Out-String)

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    "to='$to',subject='$title',body='$body'"

実行すると次のようになる。

  • 改行が改行として使われていることが確認できる

    改行が改行として使われていることが確認できる

改行を改行のまま渡すことができた。しかし、今度は空白が消えている。行頭の空白は消えているし、連続した空白は1つの空白へ圧縮されてしまっている。

これはなかなか回避が難しい。ここではトライ&エラーの結果、次のように空白をいったん「 」に変換することで課題を克服できることがわかった。

$to="iphoneaccount@example.com"
$title="from Windowsシステムクリップボード"
$body=$(Get-Clipboard | Out-String)

$body=$body -replace " "," "

& 'C:\Program Files\Mozilla Thunderbird\thunderbird.exe' `
    -compose `
    "to='$to',subject='$title',body='$body'"

実行すると次のようになる。

  • 今回の成果物ー「、」「'」「改行」「空白」のすべてを本文へ渡すことに成功

    今回の成果物ー「,」「'」「改行」「空白」の全てを本文へ渡すことに成功

これはPowerShellだけではなく、Thunderbirdのメールコンポーザの動作を利用している。Thunderbirdのメールコンポーザは文字列として「 」といった特殊文字が送られてきた場合にそれを本来の文字に置き換えて表示する。その機能を使って空白文字を「 」という文字列に変換してThunderbirdのメールコンポーザへ渡し、その後Thunderbirdのメールコンポーザが元の文字に戻した、というわけである。

実はこれだけではまだエスケープがやや足りないのだが、基本的な部分としてはほぼ事足りるので、今回はここまでとする。

トライ&エラーで頑張る

引数で値を渡す方法は便利で簡単な半面、エスケープ処理に常に頭を悩ませることになる。エスケープ処理はシェルやプログラミング言語ごとにやり方が微妙に異なることもあり、厄介だ。

しかし、一度整理できれば同じ要領で対応できるので、ある程度汎用的なエスケープ方法を模索しておくのは悪くない。最初は結構な時間の試行錯誤を要するのでストレスが溜まり、疲れると思うが、うまく利用できるようになるとその効果は大きい。

今回のケースで言えば、今回の方法が明らかになったことで新規メール作成の多くをPowerShellスクリプトで自動化できることになる。これまで手動で編集していた部分をデータに基づいてPowerShellスクリプトで処理させ、本人は最後にメールを一読して確認し、ボタンを押すだけになる。人によっては、時間をかけた以上の恩恵を得られる方も多いのではないだろうか。