Amazon – SES 設定 Email,讓使用者寄信/伺服器收信/轉寄給管理者

流程
提供 Email 做測試
還未提交審核前,收發 Email 只有在認證過的 Email 或 Domain 可以通訊。所以首先我們先認證 Domain 跟一組 Email 做測試。
打開 Amazon SES (Amazon Simple Email Service)
Domain > Verify a New Domain 建立一個網域並驗證
接著要驗證新的 Domain,這兩筆資料,會顯示在你的 Route 53
接著會跳出警告訊息說,MX 紀錄 (MX Type) 會覆蓋你原本有的設定。假如你有特殊設定過的話,請不要覆蓋。但因為我們沒有,所以打勾後點選 Create Record Sets。
因為剛剛我們加入了 『TXT 紀錄』『MX 紀錄』所以,可以到 Route 53 看看我們裡面出現了這兩筆
回到 Amazon SES 後可以看到 Domain 已經驗證成功 (Verified)
發信
因為目前在沙盒模式中,只能寄信給驗證過的 Email,所以在這裡加入 Email
接著我們打開自己的 Email 驗證
這時候我們可以發送測試信件,從 網域 寄送到剛剛認 證過的 Email,看看我們的網域能不能收到
From 的帳號名稱可以自訂,可以打 service 或 admin 之類,寫好後發送測試信件
再到我們自己的信箱中,就可以成功看到由 Amazon 寄來的信件了。
如果要使用 SMTP 給自己的程式語言發信的話,這邊有 Server 連接的名稱,第一次我們要點選左側的 SMTP Settings > Create My SMTP Credentials 來建立一個使用者。
這邊就能看到 SMTP 的 Username 與 Password ,把他儲存下來,因為 Password 日後忘記的話 Amazon 是無法找到的。
在 Amazon I Am 中就可以看到你目前有的使用者囉
收信
參考官方說明。在 SES 中設定收信規則
選擇 Create S3 bucket。這是在 S3 建立一個收信夾的概念。這裡提供官方說明『如果您選擇在 Amazon S3 儲存貯體中存放訊息,訊息的大小上限 (包含標頭) 為 30 MB。如果您選擇透過 Amazon SNS 通知接收訊息,訊息的大小上限 (包含標頭) 為 150 KB。』參考官方。
輸入自訂的貯體 Bucket 名稱後,點選 Create Bucket
點進去,會看到有預設的 AMAZON_SES_SETUP_NOTIFICATION,可以忽略。如果我們認證的網域收到信,都會在這邊顯示檔案 (Email 原始資料)
在 Amazon S3 的 Bucket 中就可以看到這封字串的檔案名稱,下載下來後打開,就能看到 Email 的原始碼。
基本上到這邊,發信最簡單,收信就比較麻煩。目前收信看到的是原始格式,如果要進一步解析可參考這篇 使用 SDK PHP 取得列表與內容。
轉寄
要怎麼將 Email 原始檔轉寄給其他管理人 (例如 Jason@gmail.com) 呢?那就透過 S3 的 API + EmailParser 來製作。下面這個完整範例,依序:
- API 取得 Bucket
- API 取得 Object
- 用 EmailParse 分析
- 用 PHPMailer 發送
- API 刪除已經發送過的 Object
為了方便說明流程,所以不使用 Class 封裝,轉換為自己的程式碼的時候記得寫漂亮一點喔!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
<?php require_once('vendor/autoload.php'); // 填入 key, secret 製作證書 $credentials = new Aws\Credentials\Credentials(Key, Secret); // 產生 S3 使用者端 $client = Aws\S3\S3Client::factory(array ( 'credentials' => $credentials, // 填入證書物件 'region' => 'eu-west-1', // S3 務必使用 eu-west-1 區域 'version' => 'latest', // 最後一個版本 )); try { // 取出貯體列表 $result = $client->listBuckets(); // 放置貯體與物件的盒子 $box = []; // 可以用 foreach 讀取每個列表,但因為這個範例用在 Email ,只有固定放在一個 Bucket,所以我們固定名稱 $my_email_bucket_name = 'my_email_bucket'; // 填入你存放 Email 的 Bucket 名稱 $iterator = $client->getIterator('ListObjects',array ( 'Bucket' => $my_email_bucket_name, )); // 讀取出每個檔案 foreach ($iterator as $object) { // 我們把 object 的 key 當作陣列的 key. 這等同 Object 的唯一鍵喔 $key = $object['Key']; // 預設檔案我們跳過 if ($object['Key'] == "AMAZON_SES_SETUP_NOTIFICATION") continue; // 取得物件內容 $result = $client->getObject(array ( 'Bucket' => $my_email_bucket_name, 'Key' => $object['Key'] )); // Email 原始格式,基本上是很複雜的 $content = $result['Body']; // 所以透過 EmailParser 解析原始格式,把標題、寄件人什麼的,放到盒子集中 $parser = new \MS\Email\Parser\Parser(); $message = $parser->parse($content); // 從哪裡寄來的 email $box[$key]['from'] = $message->getFrom()->getAddress(); // 發寄送時間 $box[$key]['date'] = $message->getDate(); // 標題: 因為被 RFC2047 編碼過,所以要轉碼 $subject = $message->getSubject(); $subary = imap_mime_header_decode($subject); $box[$key]['subject'] = $subary[0]->text; // HTML 格式的內文,有純文字與含 HTML $box[$key]['body']['text'] = $message->getTextBody(); $box[$key]['body']['html'] = $message->getHtmlBody(); // 夾帶檔案陣列 $mixatt = []; foreach ($message->getAttachments() as $attkey => $attachement) { $mixatt[$attkey]['filename'] = $attachement->getFilename(); // 文件名稱 $mixatt[$attkey]['mimetype'] = $attachement->getMimeType(); // 文件類型 $mixatt[$attkey]['content'] = $attachement->getContent(); // 文件內容 } $box[$key]['attachements'] = $mixatt; } // 批次發送 $send_result = []; // 用來記錄發送結果 foreach ($box as $data) { // 使用 PHPMailer 轉寄 $mail = new \PHPMailer; $mail->isSMTP(); // 啟用 SMTP $mail->Host = 'email-smtp.eu-west-1.amazonaws.com'; // 指定 SMTP Servers $mail->SMTPAuth = true; // 啟用 SMTP 認證 $mail->Username = 'Username'; // SMTP username $mail->Password = 'Password'; // SMTP password $mail->SMTPSecure = 'TLS'; // 啟用 TLS encryption $mail->Port = 25; // 連接的 TCP port $mail->setFrom('service@xxx.com', 'XXX'); // 從哪裡寄件,這裡填上發信人 $mail->addAddress($data['from'], ""); // 寄給誰,這個範例是寄給管理者。 // 因為我們的夾帶檔案室字串,所以我們要使用 addStringAttachment 而非 addAttachment foreach ($data['attachements'] as $attachment) { $mail->addStringAttachment($attachment['content'], $attachment['filename']); } $mail->isHTML(true); // 啟用 HTML 內文 $mail->CharSet = "utf-8"; $mail->Subject = $data['subject']; $mail->Body = $data['body']['html']; $send_result[] = $mail->send(); // 發送 } // 檢查發送結果 var_export($send_result); // 最後向 S3 刪除已經發送過的檔案 $result_delete = []; foreach ($box as $key => $object) { // print_r($object['Body']);die; $result_delete[] = $client->deleteObject( [ 'Bucket' => $my_email_bucket_name, 'Key' => $key ]); } // 檢查刪除結果 var_export($result_delete); } catch(Aws\S3\Exception\S3Exception $e) { echo $e->getMessage(); } |
這裡要注意發信人的部分,務必要是已經認證過的 Domains 或 Email 才可以喔。
假設你的 Domain 是 abc.com 那麼發信人應該如 service@abc.com。因為是交由 Amazon 轉寄的動作,所以如果你的發信者填上了別的地址如 (jason@gmail.com),而這個使用者名稱又沒有在 SES 中的 Identity Management 認證過,那麼 SMTP 就會發送失敗,出現錯誤訊息喔!
定時收信
若在 Linux 的話,可以使用 apt-get install curl 安裝 curl 套件,透過 CURL 去訪問你的 PHP 定時觸發。 PHP 定時觸發,網路上很多教學囉,大致上簡略介紹如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php // 關掉瀏覽器,PHP腳本也可以繼續 ignore_user_abort(true); // 讓程序無限制的執行下去 set_time_limit(0); whilte(true) { //設計一個可以讓你手動終止條件,例如判別某個 SQL 或是檔案,這樣要終止時才不用重新啟動 Server // function().... // 向 Amazon 觸發收信、寄信相關 // function()...... // 每隔 20 秒向 Amazon 收信 sleep(20); } |
繼續閱讀
Comments