SendGridは私たちの友人ですが、真実はもっと高価です

SendGrid logo

すでに書いたように 、私たちはプロジェクト管理システムである人気のフリーミアムサービスのチームと協力し始めました。 このサービスは、1日に数千単位で計算される非常に多数の文字を生成します。これらは主に、発生した変更に関するユーザーへのさまざまな通知と、作業のアプローチ/期限切れに関する毎日の通知です。 ユーザーは、電子メールに応答してデータを更新することもできます。 ユーザー数の増加に伴い、 SendGridアカウントも増加していることに気付きました。これは、フリーミアムサービスとして、最小限に抑えたいと考えています。 また、メールをどれだけ効率的に使用しているか、またメールの一部をどこにも送信せず、SendGridの配信料金を支払うかどうかも理解したいと考えました。



誰かが何らかの通知を受け取っていない、またはサービスからの手紙に対する彼の応答が彼によって受け取られていない、という質問がますます発生し始めました。 したがって、2番目の問題は、自分のデータベースとSendGridインターフェイスの両方を常に参照しなければならなかったため、メール配信に関連するユーザーの問題のサポートを効果的に処理できないことでした。 多くの時間がかかったという事実にもかかわらず、多くの場合、結果が得られませんでした。 smtpを介してレターを送信した後、データベース内のレコードとSendGrid側の結果の間には接続がありませんでした。



状況は着信メールの場合と同様でした。 まだ出会っていない人のために、SendGridでこれがどのように機能するかを説明します:文字がSendGridによって受信され、解析され、受信されたデータがPOSTによって指定されたアドレスに送信されます。 あなたに。 そのため、サービスで誰かの手紙が公開されていないという状況が発生した場合、誰が責任を負うべきかは明確ではありません。SendGridはそれを解析できなかったか、スクリプトが機能しませんでした。 「まあ、わからない、それがどうして、手紙が来なかったのか」という真実の答えをユーザーに書くことができ、彼の質問にすぐに対処することを約束することができる場合、あなたは私たちを理解するでしょう。 私たちの約束が嘘にならないように、私は働き始めました。



だから-私たちは手紙の配達と受領のプロセスを完全に制御する必要があります。 現在の状況は、(smtpを介して)SendGridを介してメールを送受信し、SendGridデータと1日あたり数千文字の通信が完全に欠如しており、その数が増え続け、ユーザーの問題を解決するための効果的なメカニズムがないことです。 タスクは、コストを削減し、カスタマーサポートの品質と速度を向上させるために、データを可能な限りSendGridデータにリンクすることです。



まず第一に、私たちは私たちの質問への回答のために彼らの文書に目を向けました。 SendGridには2つのフックがあり、文字の状態に対して必要な制御を提供するだけであることがわかりました。 最初のフックはイベントです -SendGridは、システムで生成されたイベントに関する通知を指定されたURLに送信します。 特定の文字を識別するために、彼らはSMTPを介してメッセージを送信するときに特別なヘッダーとして送信できる一意の引数とカテゴリのメカニズムを使用することを提案しています。 さらに、イベントの通知にはこれらの引数とカテゴリが含まれるため、このイベントがどの文字に属しているかを正確に判断できます。 それは何を与えますか? まず、 「料理人が私たちに嘘をついていない場合」、私たちは常に手紙がユーザーに届けられたかどうかを確実に知っています。 第二に、「遅延」のステータスを受け取った、またはバウンスリストにある手紙を再送信するプロセスを完全または部分的に自動化することができます。 さらに、バウンスリストに新しいメールを入力する方法をすぐに確認し、すぐに対応できるようになりました。 文字のカテゴリの使用に関連する追加のボーナスがあります。



上記のように、カテゴリは送信されたレターに割り当てることができ、ドキュメントによると最大10まであります。これらのカテゴリは、SendGridインターフェイスでレポートを準備するときに使用され、見栄えの良いグラフで互いに比較できます。 残念ながら、何らかの理由でカテゴリの単一レベルシステムしかないため、2レベルのアプローチを使用する方が便利です。 なぜなら、私たちの最初のレベルは手紙を送ったアプリケーションによって決定され、2番目のレベルはその手紙を送った原因となったアクションだからです。 たとえば、Todoアプリケーションは、記録の終了日を作成、編集、および変更するときに文字を送信します。 2番目のカテゴリを使用すると、1つのアプリケーション内でだれが文字を生成し、いくつ生成されるかをより完全に把握できます。 ただし、他のアプリケーションにも同様のアクションが存在するため、追加カテゴリ自体は、特定のアプリケーションへのバインドほど統計にとって興味深いものではありません。 ただし、誰かとそのような統計のスライスが役立つ可能性があります。



実装に関するいくつかの言葉:プロジェクトはCodeIgniterを使用して記述され、手紙は標準の電子メールライブラリによって送信されます。 ただし、SMTP経由でメッセージを送信するときに独自のヘッダーを作成することはできないため、独自のクラスでヘッダーを拡張する必要があります。 github.com/leonbarrett/CodeIgniter-Sendgrid-API/blob/master/system/libraries/Email.phpライブラリを例にとると、独自のライブラリを作成し、不要なものをすべて破棄し、残りを1つの方法に単純化しました。 実際、_set_header()メソッドはCI_Emailクラスでprivateとして宣言されており、派生クラスで使用できないため、2つのメソッドが出てきました。

完全なライブラリコードを次に示します。
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * CodeIgniter * * An open source application development framework for PHP 5.1.6 or newer * * @package CodeIgniter * @author Deep Shift Labs Dev Team * @copyright Copyright (c) 2013, Deep Shift Labs * @license http://codeigniter.com/user_guide/license.html * @link http://codeigniter.com * @since Version 1.0 * @filesource */ // ------------------------------------------------------------------------ /** * CodeIgniter Email Class * * Permits email to be sent using Mail, Sendmail, or SMTP. * * @package CodeIgniter * @subpackage Libraries * @category Libraries * @author Deep Shift Labs Dev Team * @link http://deepshiftlabs.com */ class MY_Email extends CI_Email { /** * Add a Header Item * * @access private * @param string * @param string * @return void */ private function _set_header($header, $value) { $this->_headers[$header] = $value; } /** * Add a Sendgrid header * * @access public * @param array * @return void */ public function addSendGridHeader($data) { $xsmtpapi = json_encode($data); // Add spaces so that the field can be foldd $xsmtpapi = preg_replace('/(["\]}])([,:])(["\[{])/', '$1$2 $3', $xsmtpapi); $this->_set_header('X-SMTPAPI', $xsmtpapi); } }
      
      







したがって、レターへの一意の引数とカテゴリの追加は、たとえば次のようにaddSendGridHeader()メソッドを1回呼び出すだけで行われます。



 $this->email->addSendGridHeader(array('unique_args'=>array('email_id'=>1), 'category'=>array('help', 'question')));
      
      







しかし、フックに戻ると、2番目のフックInbound Parseを使用すると、ユーザーからの応答を取得できます。 ドメインまたはサブドメインのMXレコードを適切に設定した後、Sendgridは指定されたアドレスに処理済みの応答レターの送信を開始します。 驚いたことに、入ってくる手紙のイベントはないことがわかりました。 処理のどの段階に関する情報を取得するかは現在不可能です。 このプロセスがそれらでデバッグされ、失敗しないことを望むことしかできません。 受け取ったものはすべて私たちに転送されますが、確認することはまだ不可能です。 これに基づいて、私たちの側で発生する文字の処理段階のみを修正できます。 受信レターのステータスは、「received」、「hash_checked」、「duplicate」、「processed」です。 確かにあなたは 'hash_checked'の2番目のステータスに興味があります。とにかくこれが起こることを望みます。 SendGridからの着信文字に関するイベントを受信しないという事実に加えて、最初の文字を識別するのに役立つ、何も受信しません。 一意の引数、カテゴリ、まったく何もありません。 つまり 私たちが答えを受け取った手紙を理解することは、単に不可能です。 しかし、SendGridが送受信されたレターを自分自身にリンクするタスクを引き受けた場合は素晴らしいことです。送信されたレターで一意のヘッダーを送信し、それらは応答とともに返されます。 これは、以前の投稿で書いたのと同じ未耕作分野の一部です。 しかし、これはそうではないので、自分で出なければなりません。



Reply-Toヘッダーのアドレスに特別なハッシュを使用して、次のようになりました。
 "db051171af45b683c50eb3d66017ecf2+@incoming.servicedomain.com"
      
      



このハッシュは、システム内のどのレコードが一致するかを正確に知る方法で生成されます。 これは、Todoの投稿、ディスカッション、または他の何かである可能性があります。 手紙を受け取ったら、その手紙が属する記録を特定し、特定できた場合、その手紙には「hash_checked」のステータスが割り当てられます。 次に、複数の同一のコメントを作成しないように、文字が重複しているかどうかを確認します。 次に、新しいコメントが実際に作成され、メッセージに「処理済み」のステータスが割り当てられます。



解決したかったタスクの1つは、ユーザーに配信されなかった手紙を再送信する機能でした。 これを行うには、必要なすべてのデータがデータベースに保存されます。 プロジェクトはCodeIgniterで記述されているため、そのようなデータは、件名、受信者、独自のパラメーターなどを含む、送信前に形成されるレターの本文とヘッダーです。 文字の保存は、標準の電子メールライブラリのsend()メソッドをオーバーライドするときに、文字通り数行のコードで実現されました。 だから、手紙は保存されますが、安全に届けられた手紙の元のデータを保存するのはほとんど意味がありませんか? いずれにせよ、それは私たちのためではないため、SendGridaからイベントを受信するスクリプトに小さな変更を加えました。「配信済み」イベントに関する通知を受信した場合、この文字に対応するすべてのエントリをテーブルから削除します。 ここで使用される乗数は偶然ではありません。データベースに文字を保存するプロセスを高速化するために、これが最初の送信試行であるかどうかを確認しません。 同じ手紙を何度か送信しようとした場合、その手紙のいくつかのコピーがデータベースに保存されます。 論理的な結論は、データベースから手紙を再送信するアクションを追加したことでした。これには問題はありませんでしたが、手紙を操作するために上記のライブラリを少し変更する必要がありました。 おもしろい場合は、コメントを書いてください。コメントをお聞かせください。



ここでは、一般的な用語、および送受信メールの管理方法について説明します。 この新しいサブシステムを起動し、データを蓄積することで、ソリューションが私たちに理解されプログラムされている場合の最適化と自動化を開始します。 すでに同様の問題を解決し、コメントで経験を共有している場合、私はそれを大いに感謝します。



PS上記の自動化システムをリリースしたとき、不快な状況に遭遇しました。 システムの実稼働バージョンと実稼働前バージョンは、SendGridで異なるアカウントを使用するため、テストメールは実際のシステムの統計に影響を与えません。 9月15日、実稼働サーバーで変更を開始しようとしましたが、何らかの理由で、送信されたイベント通知からデータを取得できなかったことが判明しました。 簡単な調査によりその理由が明らかになりました-9月6日、SendGridはEvent webhookの3番目のバージョンを開始しました。このバージョンでは、送信されるデータの形式が根本的に変更されました。 バージョン1および2では、これらは通常のPOST変数でしたが、JSON構造がレコードの配列とともに送信されるようになりました。 奇妙なことに、SendGridはそのような重要な変更について有料顧客に警告しませんでした。 意地悪の法則に従って、プリプロダクションのアカウントのイベント通知アプリケーションは9月6日までアクティブ化されたため、バージョン2のフックでテストしました。 15日のリリース前に、ライブシステムで使用されているアカウントで通知をアクティブにし、すでにバージョン3のフックに静かに接続していました。 したがって、通知パーサーを変更してテストするために、リリースを延期せざるを得ませんでした。



All Articles