メール送信(Ver.10)

はじめに

INTER-Mediatorのメールを送る機能は、Ver.5までの仕組みと、Ver.6以降の仕組みが大きく異なっています。ここでは前者を「旧アーキテクチャ」、後者を「新アーキテクチャ」と呼びます。Ver.6を実装では、旧アーキテクチャの実装は残して新アーキテクチャも組み込み、相互に切り替えて運用できるようにしました。また、過去のアプリケーションとの互換性を考慮して、既定値では旧アーキテクチャでの稼働を規定値にしました。Ver.10では、既定値を新アーキテクチャとしましたが、旧アーキテクチャに切り替えることは可能です。しかしながら、今後は新アーキテクチャが使われることがメインになると想定して、新アーキテクチャのみをこの文書では紹介します。旧アーキテクチャでのメール機能の利用についてはメール送信(Ver.5)あるいはメール送信(Ver.6)をご覧ください。

メールはPHPのmail関数を使う方法と、メールサーバを利用する方法を使用できます。mail関数を使う場合UNIX系サーバならsendmailコマンドをたたく方法になります。SMTPサーバーを利用してメールを送信する場合、Ver.10まではswiftmailerを利用します。Ver.11で、symfony/mailerに切り替えています。

定義ファイルへの指定

[第1引数, コンテキスト定義]
メール送信

配列指定
キー インデックス 下位のキー
'send-mail'
あるいは
'messaging'
'driver' メールを送信する場合は、値は'mail'、あるいはこのエントリーごと省略する(send-mailキーの場合は記述してはいけない)
'read' コンテキストに対してレコードの取り出しを行った後にメールを送信する。
'from' 送信者名や送信者アドレスが含まれるフィールド名、あるいはアドレスの文字列。文字列内に「@@フィールド名@@」の記述があれば、フィールドのレコードに置き換わる
'to' 送信先が含まれるフィールド名、あるいはアドレスの文字列。文字列内に「@@フィールド名@@」の記述があれば、フィールドのレコードに置き換わる。複数の送信先はカンマで区切る
'cc' Cc先が含まれるフィールド名、あるいはアドレスの文字列。文字列内に「@@フィールド名@@」の記述があれば、フィールドのレコードに置き換わる。複数の送信先はカンマで区切る
'bcc' Bcc先が含まれるフィールド名、あるいはアドレスの文字列。文字列内に「@@フィールド名@@」の記述があれば、フィールドのレコードに置き換わる。複数の送信先はカンマで区切る
'subject' 件名が含まれるフィールド名、あるいは件名の文字列。文字列内に「@@フィールド名@@」の記述があれば、フィールドのレコードに置き換わる
'body' メール本文が含まれるフィールド名、あるいは本文の文字列。文字列内に「@@フィールド名@@」の記述があれば、フィールドのレコードに置き換わる
'template-context' メールの文面を得られるコンテキスト名と検索条件。テーブルに文面のテンプレートをセットしているものとする
'store' 送信したメールをここで指定したコンテキストに対して新規レコードを作成して保存する
'attachment' 添付するファイルへの相対パスの文字列、あるいはそれを含むフィールド名。文字列内に「@@フィールド名@@」の記述があれば、フィールドのレコードに置き換わる
'f-option' UNIXでSMTPサーバを経由しない場合にtrueを指定すると、fromの指定が有効
'body-wrap' 右端の折り返しのバイト数
'update' コンテキストに対してレコードの更新処理を行った後にメールを送信する。第3次元については、readと同様
'create' コンテキストに対して新たなレコードを作るアクションを起こした後にメールを送信する。第3次元については、readと同様

[第2引数, オプション設定]
メール送信サーバー

配列指定 params.phpで変数名
第1次元 第2次元
'smtp' 'server' メール送信時に使用するサーバのホスト $sendMailSMTP
'port' メール送信時に使用するサーバのポート
'protocol' メール送信時に使用するプロトコルで、省略すると'smtp'を選択する。こちらのDSNのProtocolの指定となる(Ver.11で追加)
'username' メール送信時に認証で使用するユーザー名
'password' メール送信時に認証で使用するパスワード
'encryption' 通信処理の暗号化をする場合にその方法を指定する。'ssl'、あるいは'tls'を指定する(Ver.11以降は無視される)

定義ファイルでの指定例を以下に示します。

IM_Entry(
        array(   // Contexts
            array(
                'name' => 'request',
                'send-mail' => array(
                    'create' => array(
                        'from' => 'info@msyk.net',
                        'to' => '@@email@@',
                        'cc' => 'msyk@me.com',
                        'subject' => 'ビジネスマッチング申し込み',
                        'body' => '受け付けました。\n本当です。',
                        'f-option' => true,
                        'body-wrap' => 76,
                    )
                )
             )
        ),
        array(   // Options
            'formatter' => array(...),
            'smtp' => array(
                'protocol' => 'smtp',
                'server' => 'mysmtp.msyk.net',
                'port' => 587,
                'username' => 'msyktest@msyk.net',
                'password' => 'oshienai',
            )
        ),
        array('db-class' => 'PDO'),
        false
    );

メールを送信するタイミングの指定

'send-mail'キーの配列の次のレベルのキーとして、'read' 'update' 'create'のいずれかを指定できます。それぞれ、データベースからの読み込み時、更新時、新規レコード作成時を意味し、コンテキストに対するそれぞれのタイミングでメールを送信します。いずれも、データベース処理が終了してからメールの送信にかかります。上記の例では、新規レコード作成時に、メールが送信されます。

メールの内容

メールの送信者はfromキー、宛先はto、cc、bccキー、件名はsubjectキー、本文はbodyキーで指定した文字列になります。一定の文字列で良い場合は単に記述するだけです。一方、全ての値でフィールドの値に置き換えるテンプレート処理が可能です。readの場合のメールだと、その時にviewキーのテーブルやビュー等で読み出した1つのレコードのフィールドを「@@フィールド名@@」の部分に置き換えてメールを作成することができます。create、updateの場合は対象レコードをviewキーのフィールドもしくはビューから取り出します。

基本的にはメールはUTF-8でエンコードして送られます。定義ファイルはUTF-8を利用するので、日本語の文字列は通常通り記述して、UTF-8で保存すればその文字がメールで利用されます。ヘッダについては、base64のインラインエンコードを、ASCIIコード以外の文字について行います。本文はそのままですが、ヘッダのContent-TypeのcharsetにUTF-8という文字を付けます。つまり、本文はbase64等でのエンコードは行いません。

本文は一定の長さで改行を入れます。既定値では72バイトですが、'body-wrap'キーで異なる値にできます。0に設定すると改行しません。ここで、バイト数ですが、実際のバイト数ではなく、日本語は2バイト、英語は1バイトと数えた結果で示しています。実際のエンコードはUTF-8なので、嘘と言えば嘘のカウントになりますが、おそらくこうして指定をすることに慣れている人が多いので、ここでは実態とは関係ない数値ではありますけども実用的という意味で「2バイトルール」でカウントしたものとします。

UNIXでSMTPサーバーを使わない場合、通常はメールソースのFrom:は無視されて、UNIXアカウントそのものをFrom:として設定してしまいます。ただし、サーバー側で許可されていれば「'f-option' => true」の指定を定義ファイル内に記述することで、sendmailコマンドの-fパラメータを指定して、送信者の指定が可能です。

SMTPサーバーの指定

定義ファイルのIM_Entry関数の第3引数のオプション領域に'smtp'キーで配列を指定します。その他のキーは、前記の例の通りで、キーを見れば意味は分かると思います。もし、SMTP認証をしない場合は、serverとportだけを指定します。認証する場合は、server, port, username, passwordを指定します。

SMTPサーバーの指定は、params.phpファイルでも指定が可能です。変数名として、$sendMailSMTPの定義し、値は'smtp'の右側の配列と同様に指定をします。params.phpファイルでの指定よりも、定義ファイルの指定が優先されます。どこにもSMTPサーバーの設定がない場合には、mail関数での送信になります。

Windowsの場合、mail関数はSMTP利用するので、php.iniにサーバー情報などを書くことで対処できます。従って、'smtp'の指定やparams.phpファイルでの指定は一般には不要ですが、もし設定すれば、mail関数ではなく、swiftmailによるメール送信ができます。

Gmailのアカウントでメール送信する場合(Ver.11以降)

Gmailへの送信は、symfony/mailerの機能を使って送信します。ライブラリの「symfony/google-mailer」は、INTER-Mediatorのcomposer.jsonファイルに記述済みなので、通常はすでにインストールされているはずです。設定としては、prtocol、username、passwordのみを指定してください。serverに相当する値は背後で自動的にdefaultになります。params.phpファイルに指定する場合の例を示します。なお、パスワードはログインのためのパスワードではなく、AppPasswordによって発行されたコードを指定します。

$sendMailSMTP = array(
    "protocol" => "gmail+smtp",
    "username" => "msyk.nii83@gmail.com",
    "password" => "himitsunopassword",
);

AWSのSESでメール送信する場合(Ver.11以降)

AWSのSES(Simple Email Service)での送信にはSMTPも利用できますが、APIを使った送信も可能です。送信処理は、symfony/mailerの機能を使って送信します。ライブラリの「symfony/amazon-mailer」は、INTER-Mediatorのcomposer.jsonファイルに記述済みなので、通常はすでにインストールされているはずです。設定としては、prtocol、username、passwordのみを指定してください。serverに相当する値は背後で自動的にdefaultになります。params.phpファイルに指定する場合の例を示します。なお、アクセスキーとシークレットキーは、AWSのIAMで作成したユーザに対して発行されたものを指定します。このユーザには、アクセス許可としてAmazonSesSendingAccessを指定します。

$sendMailSMTP = array(
    "protocol" => "ses+https",
    "username" => "yourACCESSKEY",
    "password" => "yourSECRETKEY",
);

AWS SESの利用にはいくつかポイントがあります。まず、Verified AddressというところにFromに指定するメールアドレスを登録します。ここに登録しないとエラーとなります。登録時、そのメールアドレスに対して確認メールが送信され、そこに記載されたリンクをクリックしないといけないので、メールの受信がができるアドレスである必要があります。そして、サービスを利用した段階では、SES自体がサンドボックスモードになっていて、Fromだけでなく送信先もVerified Addressである必要があります。原則として、サンドボックスモードでメール送信のテストをするので、必要なアドレスを全部登録しておきます。そして、実際に運用する段階で、プロダクションモードに変更しますが、設定だけではできず、Amazon側に申請する必要があります。メール送信の頻度や内容などを比較的詳しくレポートしないと追加情報を求められるので、そのつもりで申請に臨みます。また、申請は人間による処理をしているようで、即座に反映はされませんので注意が必要です。

symfony/mailerは既定値では、Irelandのリージョンつまり、eu-west-1を利用します。Verified Addressはリージョンごとに設定されるので、この設定とメーラが利用するリージョンを合わせないといけません。もし、東京リージョンをメール送信で利用したいのであれば、'server'キーの値に「default?region=ap-northeast-1」を指定します。そうすれば、東京リージョンに設定したVerified Addressでメール送信が可能です。

symfony/mailerがサポートするプロトコル(Ver.11以降)

symfony/mailerのドキュメントにあるUsing a 3rd Party Transportはもちろんサポートしていますが、追加のプロトコルを利用するためにはライブラをインストールしなければなりません。INTER-Mediatorは既定値ではGmailとAWS SESだけをインストールしてあります。

ファイルを添付する

ファイルを1つだけ追加できます。添付するには、media-root-dirキーの指定が必要です。そして、media-root-dirキーと、attachmentキーから得られるパスを繋いだ絶対パスのファイルを添付します。attachmentキーに「@@フィールド名@@」を用いてフィールド名を指定した場合、そのフィールドは、ファイルのアップロードコンポーネントを利用してアップロードした場合に自動的に設定されるパス名であることを想定しています。

送信結果をデータベースに残す

storeキーには、同じ定義ファイル内に定義した、レコード作成可能なコンテキストを指定します。メール送信を行うと、そのコンテキストに、新たにレコードを作って送信した結果を残せます。エラーがあって送れない場合でも結果を残します。なお、指定したコンテキストには、以下のフィールドがあるものとします。フィールド名は固定でカスタマイズはできません。フィールド名から、何が入力されるかは判別可能だと思います。

to_field、bcc_field、cc_field、from_field、subject、body、errors

あるテーブルの関連テーブルに送信結果を残す場合、relationキーを指定します。すると、上位のコンテキストの主キー値を自分自身の外部キーフィールドに設定できるので、作られたメール送信レコードに元のテーブルとの関連を残すことができます。ただし、operatorが=のものだけです。また、送信結果を残すコンテキストにqueryキーがあり、operatorが=のものがある場合、その値も初期値として設定されます。

データベースに入れたテンプレートにある文面でメールを作成する

メールの文面や送り先などをデータベースに入れておき、それを元にメールを作成して送付するには、template-contextキーを指定します。例えば、「mail_template@id=3」のように記述します。mail_templateは、同じ定義ファイルにある読み込み可能なコンテキストで、このコンテキストから読み出したデータについては、以下のようなフィールドがあるものとします。フィールド名は固定でカスタマイズはできません。フィールド名から、何が入力されているかは判別可能だと思います。

to_field、bcc_field、cc_field、from_field、subject、body

@以降は、コンテキストの中の検索条件を指定しますが、この記述は条件そのものではなく、=の前後で分離して、WHERE id = 3 のような検索条件で検索をします。実際には最初の1つのレコードだけを利用します。そのレコードからそれぞれのフィールドを取り出しますが、値そのままの場合もありますが、テンプレートのデータにある「@@フィールド@@」を、実際にメールを送るときのデータに置き換えることも可能です。

HTMLメールの送信

メールの文面の最初の文字列が <html> である場合、HTMLメールとして送信します。添付ファイルも1つまでは一緒に送れますが、添付ファイルをHTMLに埋め込みたい場合、本文の文面内で##image## と記述すればOKです。ただし、画像ファイルであるという前提で文面を作成してください。

メッセージングとしてメール送信

send-mailキーはVer.6でも利用できますが、メッセージ送信機能を拡張するにあたり、send-mailキーの代わりにmessagingキーを指定することもできます。その場合は、配列にdriverキーで値がmailのエントリーを入れるか、drivierキーを省略することでも構いません。