ryuchi's wiki pages

Shell scriptからメールを送る

mailを送信する方法はいくつかあります。ここでは、shell scriptから sendmailコマンドを使ってメールを 作成して、送信する方法について説明します。

メールの形式

まず、電子メールの形式についておさらいして、「どのように作成して送信すれば良いのか」という点に注目します。 電子メールは、テキスト形式であり、実際の電子メールを表示させてみると、下記のようなテキスト形式の電文になっていることがわかります。

以前は、コンソール上でほとんど生の状態で読み書きすることもありましたが、最近では、きれいに整形して表示される電子メール用 ソフトウェアを使うことが多くなりました。そのため、生でみる機会は少なくなりました。しかし、電子メールを送信する プログラムを作成するには、どのような形式になっているか知っておくことは、理解するための大きな手がかりなるので、知っている必要があります。

以下に電子メールのサンプルを示します。このようなテキスト形式になっています。

Return-Path: <ryuchi @ xxxxxxxxxxx>
Received: from mailhost-xxxxx.ryuchi.??? ([IPv6:2001:????????::1])
        by mailhost-yyyyyy.ryuchi.??? (8.14.4/8.14.4) with ESMTP id q6JD9N8s044050
        for <ryuchi @ xxxxxxxxx>; Thu, 19 Jul 2012 02:09:23 +0900 (JST)
        (envelope-from ryuchi @ yyyyyyyyyyy)
Received: <中略>
Date: Thu, 19 Jul 2012 02:09:23 +0900 (JST)
Message-Id: <201207191309.q6JD9N4t083517@xxxxxxxxxxxxxxxxx>
From: ryuchi @ xxxxxxxxxx
To: ryuchi @ yyyyyyyyyyyy
Subject: =?ISO-2022-JP?B?GyRCJUYlOSVIJWEhPCVrGyhC?=
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
X-UIDL: AP0!!GU*#!P*L"!^6L!!


これはテスト用として送信しています。
ちゃんと届くでしょうか。

※一部を伏字にしています。

電子メールのテキストにはいくつかお約束があります。その主なお約束は下記のようなものです。 これは、決まり事になっています。

  • 全体は ヘッダ(Header)と呼ばれる、宛先、送信者、タイトルや電子メールの送受信に関する部分と 本文が書かれているボディ(Body)と 呼ばれる部分で構成されています。
  • ヘッダとボディは 1行の空行で区切られています。この空行には空白等が含まれてもいけません。
  • 電子メールは ヘッダ、ボディともに 7bitのASCII文字のみで構成されています。 歴史的な理由により 8bitは使いません。
  • ヘッダは キーと値は : で区切られています。
  • ボディに ESC等の制御文字を入れることはできますが、ヘッダには改行文字以外の制御文字を入れることはできません。

英語のテキストのみを使った電子メールであれば、特に問題ありませんが、日本語などの多国語に対応したり、 画像や、プログラムファイルなどを添付したりするには、この制約だけでは、実現することが困難です。 そこで最初の約束ごとを守りながら、いくつかの約束ごとを追加して、対応できるように改良されています。 例えば、日本語のメールを実現するためには、主に下記の約束ごとを追加します。

  • 本文には ISO-2022-JP という文字コードを使います。 これはほぼ JIS漢字と同じになります。この場合、ESCコードと 7bitの文字で構成されていますので、そのまま本文に使えます。
  • ヘッダに ESCを含めることができませんので、MIMEエンコードして 7bit化したものを記述します。 MIMEエンコードに使う 方法は Base64 と printable Quoted が使われます。
    • MIMEエンコードした場合、 =?<文字コード>?<種別> という導入シーケンスと =? という終了シーケンスを付けます
      • 文字コード には ISO-2022-JP を使います
      • 種別には Base64の場合 B, printable Quoted の場合、Q を使います

※注) 日本語のテキストを送信するには UTF-8を使う方法もあります。ここでは、ISO-2022-JP の場合に限定します。 UTF-8 については別の機会にでも...

ここでは、日本語の文字を使うときには ISO-2022-JP という文字コードを指定する、と覚えるといいでしょう。 (JIS漢字を指定 しているのと同じです。) Base64 とか printable Quoted というのは 制御文字などの印刷不能なコードを 印刷可能文字に置き換える手順の名前です。 それぞれの形式に変換することを「エンコード」(符号化)、もとの形式に戻すことを「デコード」(復号化)と言います。 それぞれに、利点と欠点がありますので、状況に応じて使い分けるのがベストですが、日本語のテキストをエンコードするときは Base64 を使われることが多いようです。

最後の約束として、これら拡張されたメールは MIME形式のメールと呼ばれています。そして MIME形式になったことを 示すヘッダが定義されていますので、これらのヘッダを追加します。追加されているのは 3行のヘッダです。

 Mime-Version: 1.0
 Content-Type: text/plain; charset=iso-2022-jp
 Content-Transfer-Encoding: 7bit

最初の Mime-Version: は MIME形式であることと、その Version を示しています。現在は 1.0 なので、このヘッダは そのまま使います。

Content-Type: は、メールの形式を示しています。添付ファイルがある形式なのか、同じ内容を複数の形式で記述されているのか などを示しています。 text/plain というのは、従来からある テキスト形式であることを示しています。そして ボディの 言語が charset= という追加パラメータで指定しています。 この例では iso-2022-jp という文字コードを使っていることが 示されています。メールソフトは この指定を参照して 本文が日本語であることを知ることができます。

Content-Transfer-Encoding: は、ボディの転送形式を示しています。 7bit というのは、エンコードが 7bit モードであり、 テキストがそのまま送られていることを示しています。

長くなりましたが、これらの約束ごとを覚えて、再度メールのサンプルをみてみましょう。

本文の文字について 実際には JIS漢字コードで書かれています。 表示の都合で、文字コードが直接にはわかりませんが、 JIS漢字コード (ISO-2022-JP) になっていると理解してください。

ヘッダについてみていきます。 Subject: は、 =?ISO-2022-JP で始まり、=? で終わっています。直接みただけでは、 わかりませんが、これは先に記述した約束に従って エンコードした結果なのです。メールソフトはユーザが 読めるようにデコードして表示しています。 これが、どんな日本語の文字になるのか、試してみたいときには、 下記のように入力してみてください。(nkf コマンドをインストールしてください。 インストール方法は 各OS, ディストリビューションでの インストール方法を確認してください)

 > echo 'Subject: =?ISO-2022-JP?B?GyRCJUYlOSVIJWEhPCVrGyhC?=' | nkf -mBj

JIS漢字をサポートした端末であれば、メールの Subject: の内容が 日本語で表示されるはずです。 逆に 日本語を エンコードしたときに どのようになるか、下記のようにして確かめることができます。

 > cat sample.txt; echo ''
 日本語のメールを送る方法
 > cat sample.txt | nkf -MB; echo ''
 xvzL3LjspM6l4aG8peuk8sH3pOvK/cuh

さらに、下記のように、出力された文字を nkf コマンドで デコードするともとの文字が出てきます。

 > echo 'xvzL3LjspM6l4aG8peuk8sH3pOvK/cuh' | nkf -mB; echo ''
 日本語のメールを送る方法

=?ISO-2022-JP?B? と ?= は、メールのヘッダで、MIMEエンコードされている部分を囲み、示すためのものです。 nkf で全体をデコードするときにはなくても問題ありません。

Mime-Veriosn: Content-Type: Content-Transfer-Encoding: というヘッダも存在することがわかります。それぞれの意味は 先に記述した通りです。

ほかにも、解説していないヘッダが存在していますが、メールのサンプルをみて、どのような形式でメールを送るのか、理解して おきましょう。

sendmail の使い方

sendmail を使ってメールを送るときには、メールの送信先などは、コマンドラインで指定し、ヘッダと本文はパイプを通して 渡すことができます。例えば、mail.txt に入っているメールを 送信するには、コマンドラインから下記のように指定します。

  cat  mail.txt | /sbin/sendmail -- 送信先メールアドレス

mail.txt は、サンプルと同じようにヘッダと本文を含んだテキストになります。このテキストに入っている To: は、実際の 送信先とは基本的に関係ありません。(このアドレスを参照させるオプションもあります) 送信先は コマンドラインで指定されたアドレスになります。例えば メーリングリストからきたメールでは To: がメーリングリストの アドレスのままですが、ユーザのアドレスにちゃんと配信されてくるのは、ヘッダの To: とは関係なく送信先アドレスを 指定する方法があるからです。

sendmail にはたくさんのコマンドラインオプションがあります。今回は、送信先をコマンドラインから指定する方法だけ、 解説します。 送信先を指定するときは、メールアドレスが sendmail のオプションと間違えられないよう、 -- という 特別なオプションを指定したあとに、メールアドレスを指定します。 -- のあとのパラメータは 必ずメールアドレスである ことを sendmail に指示しています。

実際に送信する方法

それでは、実際に送信するサンプルを示します。 送信に使うデータは、Windows PCなどで編集したテキストをベースにすることを 配慮して、Shift-JISでデータを用意して、メールを送信する前に ISO-2022-JP に変換します。

Subject: の指定

Subject: に日本語を指定するには ISO-2022-JPにしたのち Base64 に変換します。これに =?ISO-2022-JP?B? と =? を追加して ヘッダにそのまま使えるようにするスプリクトを用意します。 標準入力から、Shift-JIS漢字を読み込み エンコードした結果を 標準出力に出力します。 このスプリクトは encode_line という名前を付けて保存しておきます。

#!/bin/sh

nkf=/usr/local/bin/nkf

read line
echo -n '=?ISO-2022-JP?B?'
echo -n $line | $nkf -jMB
echo -n '?='

ヘッダとボディを出力するスプリクト

実際に送信するテキストファイルを 下記の形式で準備します。このファイルは、Shift-JIS形式で保存しておきます。 最初の3行は、ヘッダに使う 送信元、送信先、サブジェクトです。 そのあとは メールの本文になります。

 メールの送信元
 メールの送信先
 サブジェクト

 メールの本体
   :
   :

このファイルを 下記のスプリクトに渡して、メールのヘッダとボディの形式にします。必要なヘッダは、追加してスプリクトから 出力します。このスプリクトは、標準入力から読み込み、標準出力へ出力します。この出力結果を sendmail にパイプで渡します。

このスプリクトは prepare_mail という名前を付けて保存しておきます。

#!/bin/sh

nkf=/usr/local/bin/nkf

read mail_from
read recpt_to
read subject
subject=`echo -n $subject | ./encode_line`

cat << __MAIL_HEADER__
From: $mail_from
To: $recpt_to
Subject: $subject
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit

__MAIL_HEADER__

while  read line
do
       echo `echo $line | $nkf -jS`
done

コマンドラインからの指定

コマンドラインから下記のように指定すると、メールを送信することができます。shell script等の中で、下記のように記述 します。

  cat mail.txt | ./prepare_mail | /sbin/sendmail -- 送信先アドレス

mail.txt は 送信したいメール内容で、送信先アドレスに送信されます。 sendmail のパスはそれぞれ実行される環境にあわせて変更してください。

補足

メールの From: や To: に漢字の名前が記入されていることがあります。今回は解説しませんでしたが、基本的には Subject: の場合と同じです。

sendmail は必要となるヘッダが足りない場合、自動的に補足してくれます。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-07-27 (金) 23:42:02 (2986d)