Menu

BLOG ベアメールブログ

シェルスクリプト+msmtpでメールを送信する方法

メルマガ送信システムや、申し込みフォームからの自動返信メール、ECサイトであれば購入確認や発送を知らせるトランザクションメールなど、さまざまな環境からメールは送られています。そのシステムのバックグラウンドで動いているのはメールサーバと、メールサーバに指示を出すためのプログラムです。

メールを送信するにはインターネット上にある他サーバと通信することになるため、メール送信にはSMTPサーバ(メールサーバ)が必要となり、プログラム言語単体でメールを送信できる言語はありません。しかし、多くのプログラム言語では、バッグエンドにあるメールサーバと接続しやすくするためのライブラリやモジュールといった仕組みが提供されています。

このシリーズでは、色々なプログラムでメールを送ってみたいと思います。 今回は第1回として、シェルスクリプトとmsmtpでメールを送る方法を紹介します。

環境情報

本記事では、メールサーバとは別のサーバでプログラムを実行します。
メールサーバに接続可能でプログラムが実行できる環境であれば、クライアントPCやメールサーバと同一環境でも問題ありません。

プログラムを実行可能なサーバやクライアントPC

実行環境のOSは「AlmaLinux 8.10」を使用しています。

# cat /etc/redhat-release
AlmaLinux release 8.10 (Cerulean Leopard)

メールサーバ

OSは「AlmaLinux 8.9」、SMTPサーバとして「postfix 3.5.8」を使用しています。

# cat /etc/redhat-release
AlmaLinux release 8.9 (Midnight Oncilla)

# postconf | grep mail_version
mail_version = 3.5.8
milter_macro_v = $mail_name $mail_version

プログラムの実行環境とメールサーバ間は587ポートで接続し、SMTP AUTHで認証します。

シンプルですが今回の構成を図にするとこんな感じです。

今回の構成図。クライアントPCから、587番ポートでメールサーバに接続する

シェルでメールを送ってみる

最初はLinuxでおなじみのUnixシェルを使ってメールを送信したいと思います。

シェルとはユーザとコンピュータを繋ぐプログラムです。Linux系であれば標準で導入されていますので、一番試しやすいのではないでしょうか。
シェルにはzshやtcshなど様々な種類がありますが、今回使うのはAlmaLinux標準の「bash」を使用します。

bashでメールを送信する場合の選択肢

「bash」には他言語でいうところのモジュールシステムが組み込まれていません。また、一般的に公開されているライブラリにもメールに関するものでメジャーなものはありません。(私が把握している限り)
しかし、シェルスクリプトはコマンド等をインストールすることで機能を拡張することが可能です。

シェルを使ってメールを送る方法としては、telnetコマンドやopensshコマンドを利用してメールサーバと対話しながら送信する方法がメジャーですが、telnetやopensshはコンソールから操作がしやすい反面、スクリプト内で使用するとなると、対話中にどうやって文字を入力させるのか、という課題があります。

そこで、以下のようなコマンドが候補となります。

mailコマンド

mail コマンドは、簡単なメール送信に適しています。

  • メリット:簡単で軽量、広くサポート、スクリプトとの連携が容易
  • デメリット:外部SMTP認証のサポートが不十分

sendmailコマンド

通常デフォルトでインストールされている postfix パッケージに同梱されている Sendmail 互換インターフェースの sendmail コマンドを使用します。より高度なメール送信が可能。

  • メリット:強力で柔軟なMTA、Postfixが入っていれば使える
  • デメリット:設定が複雑、軽量なツールと比べて重い

muttコマンド

mutt はCLIベースのメールクライアントで、SMTPサーバーを使ったメール送信が可能です。

  • メリット:豊富な機能、外部SMTPに対応
  • デメリット:設定がやや難しい

msmtpコマンド

msmtp は外部のSMTPサーバーを利用してメールを送信するためのシンプルなツールです。

  • メリット:軽量でシンプル、外部SMTPに対応、ロギングも簡単。プラグインシステムにより、機能を拡張することが可能

  • デメリット:キュー管理がない、高度な機能は少ない

シェルスクリプト+msmtpコマンドで送信する方法

今回は「メールサーバにSMTP接続してメールを送る」というスクリプトをbashで作成し、メール送信にmsmtpコマンドを使用します。

msmtpは前述の通り高度な機能はないものの、シンプルで軽量、柔軟性が高いという特徴を持つSMTPクライアントなので、簡単な設定で使い始めることができます。しかし、MTA(Mail Transfer Agent)としての機能はないため、MTA機能が必要であればsendmail等のMTA機能を持つソフトウェアの導入を検討する必要があります。

本スクリプトを作成するにあたり、必要なものは下記のとおりです。

bash

bashのバージョンは「4.4.20」になります。

# bash --version
GNU bash, バージョン 4.4.20(1)-release (x86_64-redhat-linux-gnu)

msmtpコマンド

msmtpコマンドがインストールされていない場合は、EPELレポジトリからインストール可能です。

msmtpの設定

まずは、接続先のSMTPサーバの接続情報をmsmtpの設定ファイルに記載します。

本記事ではホームディレクトリ配下に「.msmtprc」というファイルを作成しました。
例えば、rootユーザの場合は下記のようになります。

# vi  /root/.msmtprc

設定ファイルにSMTPサーバへの接続情報を追加します。               

※実際の環境に合わせて値を置き換えて下さい。

defaults
auth login                               #smtp auth で認証
tls off                               # TLS使用有無設定。使用する場合はon
account smtp                      #設定ファイル内の識別子(任意の文字)
host "SMTP_HOST"                          #SMTPホスト名
port 587                           #接続するポート番号
user "FROM_ADDRESS"            #認証ユーザ
password "YOUR_PASSWORD"     #パスワード
account default : smtp                  #デフォルトで使用するaccount識別子

シェルスクリプトの作成

次に任意のディレクトリでスクリプトを作成します。

本記事ではシェルスクリプトを「send_mail.sh」という名前で作成します。

# vi send_mail.sh

「send_mail.sh」に下記の内容を貼り付け、保存します。

#!/bin/bash
TO=$1
SUBJECT=$2
BODY=$3
ENVELOPE_FROM="ENVELOPE_FROM_ADD"    #エンベロープFROMアドレス
HEADER_FROM="HeaderFrom Name <HEADER_FROM_ADD>"  #ヘッダFROMアドレス

# Send mail using msmtp
(
  echo "From: $HEADER_FROM"
  echo "To: $TO"
  echo "Subject: $SUBJECT"
  echo "Content-Type: text/plain; charset=UTF-8"
  echo ""
  echo "$BODY"
) | msmtp --from="$ENVELOPE_FROM" -t

デバッグモードで実行

保存ができたら実行してみましょう

このスクリプトでは引数を3つ使うので、下記のような形でスクリプト名の後ろに「Toアドレス」、「件名」、「メール本文」の順番に任意の値を追加します。

send_mail.sh "xxxxxxx@xxx.xxx" "Test Mail from Shell Script" " Message From Shell Script"

スクリプト本体を直接実行する方法もありますが、今回は動きを確認するために「bash」コマンドに「-x」オプションを付けてデバッグモードで実行します。これにより変数の代入など、スクリプトの動きが分かりやすくなります。

bash –x send_mail.sh "xxxxxxx@xxx.xxx" "Test Mail from Shell Script" "Message From Shell Script"

※実際に実行されることに注意して下さい。

正常に実行されると以下のようなメッセージが出力されます。

+ TO=TO_ADDRESS
+ SUBJECT='Test Mail from Shell Script'
+ BODY='Message From Shell Script'
+ ENVELOPE_FROM=ENVELOPE_FROM_ADDRESS
+ HEADER_FROM='headerfrom Name <headerfrom@xxxxxx.com>'
+ echo 'From: headerfrom Name <headerfrom@xxxxxx.com>'
+ echo 'To: TO_ADDRESS'
+ echo 'Subject: Test Mail from Shell Script'
+ echo 'Content-Type: text/plain; charset=UTF-8'
+ echo ''
+ echo 'Message From Shell Script'
+ msmtp --from=ENVELOPE_FROM_ADDRESS –t

エラーは出ていないようですね。

メールボックスを確認すると、テストメールが届いていました。
From欄に指定したヘッダFROMが記載されていることが確認できます。

Gmailで受信できたことを確認

注意事項

今回作成したプログラムではSMTP接続に失敗した場合でもリトライされません。

また、エラー処理も最低限となっておりますので、実際に業務やサービスとして使用される場合は、SMTP接続に失敗した場合のリトライ処理、プログラムの再実行処理、エラー処理やログの生成などのカスタマイズが必要になります。

具体的な利用例

最後に、作成したスクリプトの活用例についていくつか紹介します。

サーバーの監視

簡易的なサーバー監視として、CPU使用率、メモリ消費量、ディスク容量などを定期的にチェックし、問題が発生した場合にメールで通知するために使用できます。

例:CPU使用率が高すぎる場合にアラートを送信

#!/bin/bash

THRESHOLD=80

MAIL_TO="admin@example.com"
MAIL_SUBJECT="CPU使用率警告"

SEND_MAIL_SCRIPT="./send_mail.sh"

CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')

if (( $(echo "$CPU_USAGE > $THRESHOLD" | bc -l) )); then
    MAIL_BODY="CPU使用率が$THRESHOLD%を超えています: $CPU_USAGE%"
    "$SEND_MAIL_SCRIPT" "$MAIL_TO" "$MAIL_SUBJECT" "$MAIL_BODY"fi

アプリケーションのログ監視:

システムやアプリケーションのログを解析し、特定のエラーメッセージや異常な動作が検出された場合に、その内容を管理者にメールで通知します。

例:ログファイルに「ERROR」が含まれているかチェックして通知

#!/bin/bash

LOG_FILE="/path/to/logfile"

SEND_MAIL_SCRIPT="./send_mail.sh"

MAIL_TO="admin@example.com"
MAIL_SUBJECT="ログエラー通知"

if grep -q "ERROR" "$LOG_FILE"; then
    MAIL_BODY=$(cat "$LOG_FILE")
    "$SEND_MAIL_SCRIPT" "$MAIL_TO" "$MAIL_SUBJECT" "$MAIL_BODY"
fi

APIや外部サービスの応答チェック:

Webサービスの応答時間やステータスコードを定期的にチェックし、異常な場合には管理者に通知することもできます。

例:Webサービスのステータスコードをチェックして通知

#!/bin/bash

URL="https://example.com"

SUCCESS_STATUS=200

MAIL_TO="admin@example.com"
MAIL_SUBJECT="サービス異常通知"

SEND_MAIL_SCRIPT="./send_mail.sh"

STATUS=$(curl -o /dev/null -s -w "%{http_code}" "$URL")

if [ "$STATUS" -ne "$SUCCESS_STATUS" ]; then
    MAIL_BODY="サービスに異常があります。ステータスコード: $STATUS"
    "$SEND_MAIL_SCRIPT" "$MAIL_TO" "$MAIL_SUBJECT" "$MAIL_BODY"
fi

まとめ

今回は、シェルスクリプトを用いて簡単なメール送信プログラムを作成しました。シェルスクリプトは、Linux環境において非常に汎用性が高く、システム管理や自動化の分野で広く利用されています。

本記事で紹介したスクリプトは、メール送信の基礎的な部分を紹介していますが、より複雑な機能が必要な場合は、必要に応じてカスタマイズしてください。例えば、複数の宛先への送信、添付ファイルの追加、HTML形式のメール作成など、様々な拡張が可能です。

メール送信の自動化は、システム管理や業務効率化に大きく貢献しますので、その第一歩として、本記事が役立てば幸いです。