Zend_Mailでメールをキューイングする簡単な方法

みなさんこんにちは。



Zend_Mailを使用して電子メールキューを整理する非常にシンプルで簡単な方法を共有したいと思います。 この記事の例は、意図的に可能な限り単純化されており、フレームワークに関連付けられていません。 この記事の目的は、特定の実装ではなくメソッドを示すことです。 さらに、このソリューションはZend Frameworkのフレームワーク内でのみ使用する必要はなく、あらゆるプロジェクトに簡単に適合できます。



ポイントに直行します。 必要なもの:

-データベース内のテーブル。

-輸送のクラス;

-メッセージの送信を実装するファイル(クラウンで実行)。



まず、データベーステーブルを定義します。

CREATE TABLE email_queue ( id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, recipients TEXT NOT NULL, subject CHAR(255) NOT NULL, message TEXT NOT NULL, header TEXT NOT NULL, parameters TEXT, max_attempts TINYINT UNSIGNED NOT NULL DEFAULT 3, attempts TINYINT UNSIGNED NOT NULL DEFAULT 0, is_false TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, in_process INT UNSIGNED DEFAULT NULL DEFAULT 0, time_last_attempt INT UNSIGNED DEFAULT NULL, create_time INT UNSIGNED NOT NULL );
      
      







次に、トランスポートクラスを作成します。

 class EmailQueueTransport extends Zend_Mail_Transport_Sendmail { /** * Send mail using EmailQueue * * @access public * @return void * @throws Zend_Mail_Transport_Exception If parameters is set but not a string * @throws Zend_Mail_Transport_Exception If failed to add a message in queue */ public function _sendMail() { if ($this->parameters !== null && !is_string($this->parameters)) { /** * Exception is thrown here because $parameters is a public property */ throw new Zend_Mail_Transport_Exception('Parameters were set but are not a string'); } $db = Zend_Db_Table_Abstract::getDefaultAdapter(); $statement = $db->prepare(' INSERT email_queue SET recipients = :recipients, subject = :subject, message = :message, header = :header, parameters = :parameters, create_time = :create_time '); $result = $statement->execute(array( 'recipients' => $this->recipients, 'subject' => $this->_mail->getSubject(), 'message' => $this->body, 'header' => $this->header, 'parameters' => $this->parameters, 'create_time' => time() )); if (!$result) { throw new Zend_Mail_Transport_Exception( 'Failed to add a message in queue.'); } } }
      
      





このクラスが行うことは、準備されたデータをZend_Mailから取得してデータベースに保存することだけです。 テーブルにレコードを作成できなかった場合、Zend_Mail_Transport_Exceptionをスローします。



さて、メッセージの送信を実装するファイルは、アプリケーションのルートにある別のフォルダーにあると仮定します。

 <?php /** * Add the messages in the log * * @param type $message * @return void */ function set_log($message) { $message = date('H:i dmY ', time()) . $message . "\r\n"; $logFile = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . basename(__FILE__, '.php') . '.log'; error_log($message, 3, $logFile); } try { $config = include realpath(dirname(__FILE__) . '/../') . '/application/config/config.php'; // Path to config file $configDb = $config['db']['params']; $db = new PDO( 'mysql:host=' . $configDb['host'] . ';dbname=' . $configDb['dbname'], $configDb['username'], $configDb['password'], array( PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'", 'profiler' => false, ) ); } catch (PDOException $e) { set_log('Connection error: ' . $e->getMessage()); } $limit = 100; // limit rows $processLimitTime = 600; // 10 minutes $statement = $db->query(' SELECT * FROM email_queue WHERE attempts < max_attempts AND in_process < ' . (time() - $processLimitTime) . ' ORDER BY id ASC LIMIT ' . $limit ); $rows = $statement->fetchAll(PDO::FETCH_ASSOC); foreach ($rows as $row) { $db->beginTransaction(); $result = $db->exec(' UPDATE email_queue SET in_process = ' . time() . ' WHERE id = ' . $row['id'] ); if (!$result) { set_log('Error when updating record from the table "email_queue". Id queue is ' . $row['id'] . '.'); continue; } $isSent = mail( $row['recipients'], $row['subject'], $row['message'], $row['header'], $row['parameters'] ); $db->commit(); if ($isSent) { $result = $db->exec('DELETE from email_queue WHERE id = ' . $row['id']); if (!$result) { set_log('Error when deleting record from the table "email_queue". Id queue is ' . $row['id'] . '.'); } } else { $result = $db->exec(' UPDATE email_queue SET is_false = 1, in_process = 0, attempts = ' . ($row['attempts'] + 1) . ' WHERE id = ' . $row['id'] ); if (!$result) { set_log('Error when updating record from the table "email_queue". Id queue is ' . $row['id'] . '.'); } set_log('Error when sending messages to e-mail. Id queue is ' . $row['id'] . ', e-mails is ' . $row['recipients'] . '.'); } }
      
      





キューの使用:

 $mail = new Zend_Mail(); $mail->setFrom($from); $mail->addTo($to); $mail->setBodyHtml($body); $mail->setSubject($subject); $transport = new \EmailQueueTransport(); $mail->send($transport);
      
      





したがって、メール()を介してキューなしでメッセージを送信する必要がある場合は、トランスポートを渡さないか、nullを渡してください。



PS誰かがZend_Queueを使用する方が正しいと考えているかもしれません。おそらく正しいでしょう。 記事に記載されている方法が唯一の正しい決定であると主張することはありません。 常に多くの解決策がありますが、そのうちの1つだけを説明しました。



PPS特別なmarkPnkgenユーザーへの有益なコメントに感謝します。



All Articles