Powered by Google App Engine

シェルスクリプト

 

bashのmailコマンドでメールを送信

bashのmailコマンドでメール送信するサンプルです。シェルスクリプトでメール送信する際に誰もが一度は遭遇する文字化けも回避する事ができます。mailとmailxコマンドの両方を用意しました!

新サイト、tree-mapsを公開しました!!

tree-maps: 地図のWEB TOOLの事ならtree-mapsにお任せ!

地図に関するWEB TOOL専門サイトです!!

大画面で大量の緯度経度を一気にプロット、ジオコーディング、DMS<->DEGの相互変換等ができます!

◯ 広告

mailコマンドを使う理由は単純明快です。OSの標準コマンドだからです。

標準である事は非常に重要です。

プログラマであれば、普段使い慣れたjava・perl・ruby等、共通化や生産性の観点からそれらで実装したくなります。

それらで実装する事は簡単ですが、デプロイは?言語・モジュールはインストールされている?という問題があります。

必須ではないがちょっとメール送信したい、という小物的なスクリプトになりがちなメール送信ではそれらが問題になり易いです。

そんな時に頼りになるのがOS標準であるmailコマンドです。これなら安心できるので、関数化して簡単に扱えるよう実装しましょう。

#!/bin/sh

#==============================================
# mailコマンドメール送信します
#==============================================
sendMail() {
    from="$1"
    to="$2"
    cc="$3"
    bcc="$4"
    subject="$5"
    contents="$6"

    inputEncoding="utf-8"
    outputEncoding="iso-2022-jp"
    subjectHead="=?$outputEncoding?B?"
    subjectBody="`echo "$subject" | iconv -f $inputEncoding -t $outputEncoding | base64 | tr -d '\n'`"
    subjectTail="?="
    fullSubject="$subjectHead$subjectBody$subjectTail"
    mailContents="`echo -e $contents | iconv -f $inputEncoding -t $outputEncoding`"

    echo "$mailContents" | mail -s "$fullSubject" -c "$cc" -b "$bcc" "$to" -- -f "$from"
    return $?
}

# メール送信テスト
from="from@from.com"
to="to@to.com"
cc=""
bcc=""
subject="mailコマンドでメール送信テスト"
contents="日本語も使えて\n
改行コードで改行できて\n
文字化けしないサンプルです"
sendMail "$from" "$to" "$cc" "$bcc" "$subject" "$contents"
if [ $? -eq 1 ]; then
    echo "send mail failure"
    exit 1
fi
echo "send mail success"

to,cc,bccは半角スペース区切りで複数指定できます。

誰もが通る道、文字化けです。

何故文字化けするのか。

大抵原因はsubjectの書式を指定していないからです。

他にも、インプットとアウトプットのエンコーディングが間違っている事に起因する文字化けも多いです。

インプットにあたる部分はOSの文字コードで、アウトプットはメーラー側の文字コードです。

文字化けせずに日本語を含むメールを送信するには変換が必要です。具体的に以下の手順が必要です。

  1. 件名をutf-8からiso-2022-jp(JISコード)に変換する。
  2. 件名をBase64で暗号化する。
  3. 変換した件名文字列をメーラーが解釈できるsubjectの書式に整形する。
  4. 本文をiso-2022-jp(JISコード)に変換する。(本文はBase64への暗号化は不要)
  5. メール送信。

これらの手順を踏んでようやく文字化け無しにメール送信できます。

JISコードへの変換はiconvコマンドで簡単にできます。

subjectの書式についてはRFCによって標準仕様が決まっているので仕様通りの文字列に整形する必要があります。

このsubjectの書式は解りにくいので分解してみましょう。

= ? iso-2022-jp ? B ? 件名 ? =
開始 セパレータ メーラーの文字コード セパレータ Base64暗号化されている事を示す セパレータ Base64暗号化必須 セパレータ 終了

解りにくい原因は?がセパレータになっているからですね。それに何故かイコールで囲まれています。

サンプルではechoのオプションの「-e」を使って明示的に改行コードを記述しています。

-eを使わない場合はクォート内で改行する事で改行できますが、明示的に改行コードを入れたい方が多いでしょう。

サンプルではクォート内で改行していますが、本来不要です。可読性を考慮して改行しているだけです。

続いてmailxコマンド編です。mailではなくmailxコマンドです。

最近のCentOSではmailではなくmailxがプレインストールされている事が多いようですね。

mailxの場合、前述の送信方法だとmailのfromの書式が異なるので正常に送信できません。

その辺りに対応したメソッドに修正してみました。

#!/bin/sh

#==============================================
# mailxコマンドでメール送信します
#==============================================
sendMailx() {
    from="$1"
    to="$2"
    cc="$3"
    bcc="$4"
    subject="$5"
    contents="$6"

    inputEncoding="utf-8"
#    outputEncoding="iso-2022-jp"
    outputEncoding="utf-8"
    subjectHead="=?$outputEncoding?B?"
    subjectBody="`echo "$subject" | iconv -f $inputEncoding -t $outputEncoding | base64 | tr -d '\n'`"
    subjectTail="?="
    fullSubject="$subjectHead$subjectBody$subjectTail"
    mailContents="`echo -e $contents | iconv -f $inputEncoding -t $outputEncoding`"
    echo "$mailContents" | mailx -s "$fullSubject" -c "$cc" -b "$bcc" -r "$from" "$to"
    return $?
}

# メール送信テスト
from="from@from.com"
to="to@to.com"
cc=""
bcc=""
subject="mailxコマンドでメール送信テスト"
contents="日本語も使えて\n
改行コードで改行できて\n
文字化けしないサンプルです"
sendMailx "$from" "$to" "$cc" "$bcc" "$subject" "$contents"
if [ $? -eq 1 ]; then
    echo "send mail failure"
    exit 1
fi
echo "send mail success"

変更点は以下の3点です。

  • mailのfrom部分の書式の変更。-- -fから-rになりました。
  • outputEncodingをiso-2022-jpからutf-8に変更。
  • mailをmailxに変更。

どうもmailxでsubjectにiso-2022-jpを指定すると文字化けしました。

iso-2022-jpではなくUTF-8を指定すると文字化けしなくなりました。

しかし環境によって異なる可能性があるため、コメントアウトして残しておきます。

◯ 広告