ちょっとしたこだわりの改良
ここ数回にわたり、システムクリップボードのテキストを本文に使って、新規メール作成のアプリケーションを起動するPowerShellスクリプト「clip2mail.ps1」の作成を進めている。前回は、さまざまなテキストをシステムクリップボードに貼り付け、“うまく動作しないケース”を探しては解消してスクリプトの精度を高めていった。その成果は、次の通りだ。
#!/usr/bin/env pwsh
#========================================================================
# システムクリップボードのテキストでメールを作成
#========================================================================
#========================================================================
# Thunderbirdアプリケーションパス
#========================================================================
$mailer='C:\Program Files\Mozilla Thunderbird\thunderbird.exe'
#========================================================================
# 本文の上限文字数
#========================================================================
# これ以上の値を指定するとThuderbirdがクラッシュすることがある
$bodycharlimit = 24000
#========================================================================
# 宛先とサブジェクト
#========================================================================
$to=$env:DEFAULT_EMAIL_TO
$subject="Windowsシステムクリップボード"
#========================================================================
# システムクリップボードのテキストをThunderbirdのコンポーザに貼り付け
# できるフォーマットへ変換
#========================================================================
$body=$(Get-Clipboard | Out-String)
$body=$body -replace " "," "
$body=$body -replace "<","<"
$body=$body -replace ">",">"
$body=$body -replace " ","<pre style='display:inline'>	</pre>"
$body=$body -replace ",",","
#========================================================================
# 引数で指定できる文字列長には上限がある。上限を超えている場合には、条件
# 未満まで文字数を減らして使用する。
#========================================================================
if ($body.Length -gt $bodycharlimit) {
$body = $body.Substring(0, $bodycharlimit)
$body += "<br>"
$body += "<br>"
$body += "(サイズオーバーでカットしました)"
}
#========================================================================
# メールを作成
#========================================================================
& $mailer `
-compose `
"to='$to',subject='$subject',body='$body'"
このスクリプトでは、貼り付けるテキストの文字数に上限を設けている。コマンドライン引数経由で本文を渡すという構造上、渡すことができる文字数に上限があるためだ。また、文字数が多すぎるとThunderbirdもクラッシュするため、ある程度の量に抑える必要があることがわかっている。
前回までのclip2mail.ps1では、文字数上限でバッサリと切り捨てるようにした。だが、このやり方だと本文の末尾に「本来は存在しない文字列」が表示されることがある。今回はこの部分を改良する方法を取り上げる。
問題が出るケース
次のテキストをシステムクリップボードにコピーしてから、clip2mail.ps1を実行してみる。
この状態で起動するThunderbirdメールコンポーザでは、貼り付けられている本文の最後の部分は次のようになっている。
本文の最後に「&」と表示されているが、これは元のテキストデータには存在しないものだ。なぜこのようなテキストが勝手に追加されているのか。これには、clip2mail.ps1の次の処理が関係している。
まず、clip2mail.ps1では次の処理でテキストの置換を行っている。
$body=$body -replace " "," "
$body=$body -replace "<","<"
$body=$body -replace ">",">"
$body=$body -replace " ","<pre style='display:inline'>	</pre>"
$body=$body -replace ",",","
このようなエスケープ処理を行わないと、文字が思ったようにThunderbirdのコンポーザに渡ってくれないからだ。エスケープ後、次の処理でテキストデータをサイズで切り捨てている。
$body = $body.Substring(0, $bodycharlimit)
この切り捨てで区切られた部分が、先の置換処理で置き換えられた文字列の途中だった場合、意味不明な文字列が末尾に付加されたような状態になる。
例えば、置換後テキストの末尾が「>」であり、切り捨てによってこの部分が「&g」となったとする。本来であれば「>」と表示されてほしいのだが、その部分が「&g」と表示されてしまうわけだ。これが先ほどの「意味不明な文字列が付加された」状況を生み出している。