2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【PHP】Amazon SESを使った添付ファイル付きメールを送信する

Last updated at Posted at 2019-08-16

はじめに

この記事ではAmazon SESを利用してPHPでメール送信する方法について説明します。
またAWSやSESについての説明や導入方法については様々な記事がありますので、本記事では省きます。

簡易メールの送信(SendEmail)

最も簡単なメール送信で、送信元アドレス・送信先アドレス(複数可)・件名・本文を設定することでメール送信できます。

Request Parameters

Destination
 ・ 送信先のメールアドレス(配列)
Message
 ・ メール本文
 ・ メール件名
Source
 ・ 送信元のメールアドレス

その他にもBCC送信などもあるようなので必要な方は公式サイトの確認をお願いします。

実装:テキストメールの場合

Textメール
use Aws\Ses\SesClient;

class MailUtil
{
    public static function sendMail() {
        // Amazon SES クライアントのインスタンス生成
        $client = new SesClient([
            'region' => env("AWS_SES_REGION"),   // SESのリージョン
            'version' => 'latest',
            'credentials' => [
                'key' => env("AWS_KEY"),
                'secret'=> env("AWS_SECRET")]
        ]);

     $fromAddress = "testFrom@test.com";
     $toAddressList[] = "testTo@test.com";
     $subject = "SESメールの送信";
     $text = "SESメールの実装方法について";

        // 送信元アドレス・送信先アドレス(Array)、件名、本文をリクエストパラメータに代入
        $request = [];
        $request['Source'] = $fromAddress;
        $request['Destination']['ToAddresses'] = $toAddressList;
        $request['Message']['Subject']['Data'] = $subject;
        $request['Message']['Body']['Text']['Data'] = $text;

        // 送信する
        $client->sendEmail($request);
    }
}

実装:HTMLメールの場合

リクエストパラメータを下記のように設定するだけで可能となります。

HTMLメール
        $request = [];
        $request['Source'] = $fromAddress;
        $request['Destination']['ToAddresses'] = $toAddressList;
        $request['Message']['Subject']['Data'] = $subject;
        $request['Message']['Body']['Html']['Data'] = $text;
        $request['Message']['Body']['Html']['Charset'] = 'iso-2022-jp';

AWS SDK for PHP を使用して E メールを送信する

添付ファイル付きメールの送信(SendRawEmail)

SendEmailに対してSendRawEmailは高度なメールカスタマイズをすることができます。

最終的なソースコード

use Aws\Ses\SesClient;
use Carbon;

class MailUtil
{
    public static function sendAttachedMail($toAddrList, $fromAddr, $subject, $body, $data)
    {
        // sendEmailと同様
        $client = new SesClient([
            'region' => env("AWS_SES_REGION"),
            'version' => 'latest',
            'credentials' => [
                'key' => env("AWS_KEY"),
                'secret' => env("AWS_SECRET")
            ]
        ]);
        
        # 添付ファイル(今回はwindowsをメインで想定していたのでSJIS-winにエンコードしてます)
        $attachFileData['data']     = mb_convert_encoding($data, 'SJIS-win', 'UTF-8');
        $attachFileData['filename'] = Carbon::now()->format('Ymd') . '.csv';
        $attachFileData['mimetype'] = 'text/csv';

        // RawMessageの作成
        $msg = self::createRawMessage($toAddrList, $fromAddr, $subject, $body, $attachFileData);

        $client->sendRawEmail([
            'Source'       => $fromAddress,
            'Destinations' => [$toAddressList],
            'RawMessage'   => [
                'Data' => $msg,
            ],
        ]);
    }

    /**
     * 添付ファイル付きメール用のRawMessageを作成する
     */
    private static function createRawMessage($to, $from, $subject, $body, $filedata)
    {
        if (isset($filedata['filename']) && isset($filedata['data']) && isset($filedata['mimetype'])) {
            $boundaryStr = uniqid(rand());

            $message = "To: " . $to . "\n";
            $message .= "From: " . $from . "\n";
            $message .= "Subject: " . $subject = str_replace("\r", "", $subject) . "\n";
            $message .= "MIME-Version: 1.0\n";
            $message .= 'Content-Type: multipart/mixed; boundary="' . $boundaryStr . '"';
            $message .= "\n\n";
            $message .= "--" . $boundaryStr . "\n";
         $message .= "Content-Type: text/html; charset=iso-2022-jp";
            $message .= "\n";
            $message .= "Content-Transfer-Encoding: 7bit\n";
            $message .= "Content-Disposition: inline\n";
            $message .= "\n";
            $message .= $body;
            $message .= "\n";
            $message .= "\n";
            $message .= "--" . $boundaryStr . "\n";
            $message .= 'Content-Type: ' . $filedata['mimetype'] . '; name="' . $filedata['filename'] . '"';
            $message .= "\n";
            $message .= "Content-Transfer-Encoding: base64\n";
            $message .= 'Content-Disposition: attachment; filename="' . $filedata['filename'] . '"';
            $message .= "\n\n";
            $message .= base64_encode($filedata['data']);
            $message .= "\n";
        } else {
            Log::warning('添付ファイルデータが設定されていません');
        }
    }       
}

解説

boundary

メッセージヘッダやコンテンツといったメールの各パートは、boundary で分離されます。
boundary は、各パートの開始と終了を示す文字列で、これらを使ってメッセージ本文、または今回のような添付ファイルを分けて、設定を行なっていきます。

ヘッダー

ヘッダーには送信先、送信元、件名、MIME-Ver、コンテンツタイプを設定します。
今回はヘッダー・本文・添付ファイルを設定するため、メッセージのコンテンツタイプにmultipart/mixedを設定します。これを設定することで各パートを別々に扱う必要があることがわかります。

    $message = "To: " . $to . "\n";
    $message .= "From: " . $from . "\n";
    $message .= "Subject: " . $subject = str_replace("\r", "", $subject) . "\n";
    $message .= "MIME-Version: 1.0\n";
    $message .= 'Content-Type: multipart/mixed; boundary="' . $boundaryStr . '"';
    $message .= "\n\n";

メッセージ本文

文字コードに関しては、古いメーラーを使用したユーザーが想定されるためUTF-8ではなくiso-2022-jpを選択しましたが、最近はUTF-8でも問題ないかと思います。

    $message .= "Content-Type: text/html; charset=iso-2022-jp";
    $message .= "\n";
    $message .= "Content-Transfer-Encoding: 7bit\n";
    $message .= "Content-Disposition: inline\n";
    $message .= "\n";
    $message .= $body;

Content-Disposition
・ inline
 メール本文のようなWebページの一部またはWebページとして表示可能である場合はinlineを設定します。

・ attachment
 ダウンロード可能な添付ファイルの場合に、Content-Disposition: attachment; filename="hoge.xxx"といった形式で記述します。

添付ファイル

    // mimetype:'text/csv'
    $message .= "--" . $boundaryStr . "\n";
    $message .= 'Content-Type: ' . $filedata['mimetype'] . '; name="' . $filedata['filename'] . '"';
    $message .= "\n";
    $message .= "Content-Transfer-Encoding: base64\n";
    $message .= 'Content-Disposition: attachment; filename="' . $filedata['filename'] . '"';
    $message .= "\n\n";
    $message .= base64_encode($filedata['data']);
  • Content-Type

    添付ファイルの種類で今回はCSVファイルを指定
  • Content-Disposition

    添付ファイルのためattachmentをセットし、添付ファイル名を指定
  • Content-Transfer-Encoding

    添付ファイルのエンコードに使用されるスキーム。添付ファイルでは、ほとんどの場合この値は base64指定

補足説明

送信結果の判別

AWS SESではメール送信結果を受け取ることができます。
しかし受け取り可能なのは送信失敗(バウンス処理、迷惑メール)となった場合のみで成功通知は受け取ることができません。

種別 結果判別可否
送信成功
バウンス処理
迷惑メール

そのため送信後はしばらく待って失敗通知が来ていなければ、おそらく送信成功したのだと判断する必要があり注意が必要となります。

参考

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?