tree-tips
カテゴリ
広告
bash
広告
シェルスクリプト
bashのmailコマンドでメールを送信
bashのmailコマンドでメール送信するサンプルです。シェルスクリプトでメール送信する際に誰もが一度は遭遇する文字化けも回避する事ができます。mailとmailxコマンドの両方を用意しました!
ブログも書いてます! 文系プログラマによるTIPSブログ:最新記事
- 2016-08-21:Embulkでtsvパース時にjava.lang.Character out of VALUE_STRING tokenが起きる場合の対策
- 2016-08-09:失敗への執着と成功への無頓着がもたらす停滞と安心感
- 2016-08-06:「なんで私がやらないといけないんですか?」をやめてストレスを減らそう
- 2016-07-30:docker for macでMySQLコンテナを生成してリモート接続する
- 2016-07-12:iCloudパスワードを変更したいのにセキュリティ質問が解らず困った時の対処法
- 2016-07-12:echo-sdとcowsayによる煽りのススメ
- 2016-06-23:ansibleを学ぶ:vol07:figletで動的にホスト名をmotdに書き込んでニヤニヤする
- 2016-06-18:twitterのアカウントBANの基準って何なんでしょうね
- 2016-06-16:リッチで無料な管理画面テンプレートはこれらを使っておけばOK!
- 2016-06-08:当ブログは只今firefoxで異常に負荷が上がる不具合が発生しています
- 2016-06-05:GAE/go+ginとGAE/java+servletでそれぞれスピンアップの速度差をゆる〜く確認する
- 2016-05-21:ついにtree-maps復旧!playを投げ捨てて素のservletに置き換えるまでの顛末
- 2016-05-18:現在tree-mapsは停止しています
- 2016-05-13:インターン生とメンターの間の埋まらない溝
- 2016-06-23:ansibleを学ぶ:vol06:mysql-serverのインストールからcreate databaseまでを自動化する
- 2016-06-23:ansibleを学ぶ:vol05:対象サーバのid_rsa.pubを対象サーバのauthorized_keysに登録する
- 2016-04-02:Spring batch, Flyway, Jooq code generatorからJooq DSLでSQLを発行する!
- 2016-03-17:dockerでローカルに複数バージョンのMySQLサーバを一括で生成する!
- 2016-03-13:歩行者と自転車と自動車の終わりなき戦い
- 2016-03-10:プログラマの私が今まで言われた困ったセリフ集
- 2016-03-06:郵便受けにスパムフィルターを適用したい
- 2016-03-06:ついにプリンタを捨ててやった
- 2016-04-23:redmineを使ったチケット管理の失敗のさせ方
- 2016-02-18:ImageMagickの最新版をソースからコンパイルしてインストールする
- 2016-02-15:docker上のhubotでslackのincoming webhookからhubotを反応させる
- 2016-02-13:プログラマはもっと些細な事に疑問をもっていい
- 2016-02-06:yumを翻訳すると・・・ΩΩΩ<な、なんだってー!?
- 2016-02-02:Spring bootでjsonpの先頭に謎の/**/が混入する問題とその対応:その2
- 2016-02-01:spring boot v1.3のdevtoolsのlive reloadとremote updateを試す
- 2016-02-01:MySQLのIllegal mix of collations (latin1_swedish_ci,IMPLICIT)のエラーについて
treeからのお知らせ
新サイト、tree-mapsを公開しました!!
tree-maps: 地図のWEB TOOLの事ならtree-mapsにお任せ!
地図に関するWEB TOOL専門サイトです!!
大画面で大量の緯度経度を一気にプロット、ジオコーディング、DMS<->DEGの相互変換等ができます!
bashのmailコマンドでメール送信
何故mailコマンドを使うのか
mailコマンドを使う理由は単純明快です。OSの標準コマンドだからです。
標準である事は非常に重要です。
プログラマであれば、普段使い慣れたjava・perl・ruby等、共通化や生産性の観点からそれらで実装したくなります。
それらで実装する事は簡単ですが、デプロイは?言語・モジュールはインストールされている?という問題があります。
必須ではないがちょっとメール送信したい、という小物的なスクリプトになりがちなメール送信ではそれらが問題になり易いです。
そんな時に頼りになるのがOS標準であるmailコマンドです。これなら安心できるので、関数化して簡単に扱えるよう実装しましょう。
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は半角スペース区切りで複数指定できます。
mailコマンドのメール送信でよく起きる文字化けについて
誰もが通る道、文字化けです。
何故文字化けするのか。
大抵原因はsubjectの書式を指定していないからです。
他にも、インプットとアウトプットのエンコーディングが間違っている事に起因する文字化けも多いです。
インプットにあたる部分はOSの文字コードで、アウトプットはメーラー側の文字コードです。
文字化けせずに日本語を含むメールを送信するには変換が必要です。具体的に以下の手順が必要です。
- 件名をutf-8からiso-2022-jp(JISコード)に変換する。
- 件名をBase64で暗号化する。
- 変換した件名文字列をメーラーが解釈できるsubjectの書式に整形する。
- 本文をiso-2022-jp(JISコード)に変換する。(本文はBase64への暗号化は不要)
- メール送信。
これらの手順を踏んでようやく文字化け無しにメール送信できます。
JISコードへの変換はiconvコマンドで簡単にできます。
subjectの書式についてはRFCによって標準仕様が決まっているので仕様通りの文字列に整形する必要があります。
このsubjectの書式は解りにくいので分解してみましょう。
= | ? | iso-2022-jp | ? | B | ? | 件名 | ? | = |
開始 | セパレータ | メーラーの文字コード | セパレータ | Base64暗号化されている事を示す | セパレータ | Base64暗号化必須 | セパレータ | 終了 |
解りにくい原因は?がセパレータになっているからですね。それに何故かイコールで囲まれています。
本文の改行について
サンプルではechoのオプションの「-e」を使って明示的に改行コードを記述しています。
-eを使わない場合はクォート内で改行する事で改行できますが、明示的に改行コードを入れたい方が多いでしょう。
サンプルではクォート内で改行していますが、本来不要です。可読性を考慮して改行しているだけです。
bashのmailxコマンドでメール送信
続いてmailxコマンド編です。mailではなくmailxコマンドです。
最近のCentOSではmailではなくmailxがプレインストールされている事が多いようですね。
mailxの場合、前述の送信方法だとmailのfromの書式が異なるので正常に送信できません。
その辺りに対応したメソッドに修正してみました。
mailコマンドでメール送信するサンプルコード
#!/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を指定すると文字化けしなくなりました。
しかし環境によって異なる可能性があるため、コメントアウトして残しておきます。