function send($recipients, $headers, $body) { $this->_sanitizeHeaders($headers); list($from, $textHeaders) = $this->prepareHeaders($headers); $priority = 0; if (isset($headers['X-Priority'])) { $priority = $headers['X-Priority']; } $category = ''; if (isset($headers['X-Msg-Category'])) { $category = $headers['X-Msg-Category']; } global $wgCityId, $wgWikiaMailerDB; $wgCityId = $wgCityId == null ? 0 : $wgCityId; // fake city-id for contractor/staff. // FB:4431 Write mail to archive database now $dbw = wfGetDb(DB_MASTER, array(), $wgWikiaMailerDB); $dbw->begin(__METHOD__); foreach ($recipients as $recipient) { // TODO: SHOULD WE FILTER BASED ON BLOCKS / SPAMS HERE? FOR NOW WE WILL LET SENDGRID HANDLE THAT. $dbw->insert(self::$MAIL_TABLE_NAME, array('src' => $from, 'subj' => $headers['Subject'], 'dst' => $recipient, 'hdr' => $textHeaders, 'msg' => $body, 'city_id' => $wgCityId, 'priority' => $priority, 'category' => $category), __METHOD__); // Add postback token so that we can verify that any postback actually comes from SendGrid. $emailId = $dbw->insertId(); $postbackToken = wfGetEmailPostbackToken($emailId, $recipient); $textHeaders .= $this->sep . "X-CallbackToken: " . $postbackToken; $dbw->update(self::$MAIL_TABLE_NAME, array('hdr' => $textHeaders), array('id' => $emailId), __METHOD__); wfDebugLog("enotif", __METHOD__ . ": email added to database with data: {$recipient} {$from} {$headers['Subject']}", true); } $dbw->commit(__METHOD__); }
/** * @param $par Mixed: string if any subpage provided, else null */ function execute($par) { global $wgOut, $_POST, $wgRequest, $IP; wfProfileIn(__METHOD__); require "{$IP}/lib/Mail.php"; require "{$IP}/lib/Mail/wikiadb.php"; $this->outputHeader(); $this->setHeaders(); $emailId = $wgRequest->getVal('wikia-email-id'); $emailAddr = $wgRequest->getVal('email'); $cityId = $wgRequest->getVal('wikia-email-city-id'); // cityId of the wiki which sent the email $senderDbName = $wgRequest->getVal('wikia-db'); // Verify the token so that we know this POST probably came from SendGrid. $postedToken = $wgRequest->getVal('wikia-token'); $generatedToken = wfGetEmailPostbackToken($emailId, $emailAddr); if ($postedToken == $generatedToken) { // Add the token-validated postback to the database. $this->logPostbackForLater(); // Take action on the eventType. $eventType = $wgRequest->getVal('event'); switch ($eventType) { case 'click': $this->handleClick($emailId, $emailAddr, $wgRequest->getVal('url'), $wgRequest->getVal('category')); break; case 'open': $this->handleOpen($emailId, $emailAddr); break; case 'unsubscribe': $this->handleUnsubscribe($emailId, $emailAddr); break; case 'bounce': $this->handleBounce($emailId, $emailAddr, $wgRequest->getVal('status'), $wgRequest->getVal('reason')); break; case 'spamreport': $this->handleSpam($emailId, $emailAddr); break; default: Wikia::log(__METHOD__, false, "Unrecognized type: <postback>" . print_r($_POST, true) . "</postback>\n", true); } $wgOut->addHtml("Postback processed."); } else { // Log the token-validation problem. Wikia::log(__METHOD__, false, "INVALID TOKEN DURING THIS POSTBACK: <postback>" . print_r($_POST, true) . "</postback>\n", true); $wgOut->addHtml("Postback token did not match expected value. Ignoring."); } wfProfileOut(__METHOD__); }
public function log() { wfProfileIn(__METHOD__); // Sendgrid uses raw JSON POST format, this is how PHP ingests it $data = file_get_contents("php://input"); $events = json_decode($data, true); // true = return value is array if (empty($events)) { \Wikia\Logger\WikiaLogger::instance()->debug(__CLASS__ . ": No data to process"); wfProfileOut(__METHOD__); return; } if (!is_array($events)) { \Wikia\Logger\WikiaLogger::instance()->debug(__CLASS__ . ": Supplied data is not an array", ['data_first_100_chars' => is_string($data) ? substr($data, 0, 100) : '[type: ' . gettype($data) . ']']); wfProfileOut(__METHOD__); return; } foreach ($events as $event) { $email_addr = $this->safe_get($event, 'email', ''); $email_id = $this->safe_get($event, 'wikia-email-id'); $city_id = $this->safe_get($event, 'wikia-email-city-id'); $sender_db = $this->safe_get($event, 'wikia-db'); $token = $this->safe_get($event, 'wikia-token'); $event_type = $this->safe_get($event, 'event'); $url = $this->safe_get($event, 'url', ''); $status = $this->safe_get($event, 'status', ''); $reason = $this->safe_get($event, 'reason', ''); $generatedToken = wfGetEmailPostbackToken($email_id, $email_addr); if ($this->wg->Request->wasPosted() && $token == $generatedToken) { Wikia::log(__METHOD__, false, "<postback>" . $email_addr . ", " . $status . ", " . $reason . "</postback>\n", true); // Add the token-validated postback to the database. $dbw = wfGetDb(DB_MASTER, array(), $this->wg->WikiaMailerDB); // log postback data $insert_data = array("mail_id" => $email_id, "emailAddr" => $email_addr, "cityId" => $city_id, "eventType" => $event_type, "senderDbName" => $sender_db, "url" => $url, "status" => $status, "reason" => $reason); $dbw->insert(self::POSTBACK_LOG_TABLE_NAME, $insert_data, __METHOD__); // Take action on the eventType. $update_data = array(); switch ($event_type) { case 'click': $update_data = array('clicked' => date('Y-m-d H:i:s')); break; case 'open': $update_data = array('opened' => date('Y-m-d H:i:s')); break; case 'unsubscribe': /* not used now */ break; case 'bounce': $update_data = array('is_bounce' => 1, 'error_status' => $status, 'error_msg' => $reason); break; case 'spamreport': $update_data = array('is_spam' => 1); break; default: Wikia::log(__METHOD__, false, "Unrecognized type: " . json_encode($_POST), true); } if (!empty($email_id) && !empty($update_data)) { $dbw->update(self::MAIL_SEND_TABLE, $update_data, array('id' => intval($email_id)), __METHOD__); } // Invalidate the users email to force them to reverify it if ($event_type == 'bounce') { if (isset($this->wg->SharedDB)) { $dbr = wfGetDB(DB_SLAVE, array(), $this->wg->ExternalSharedDB); } else { $dbr = wfGetDB(DB_SLAVE); } $res = $dbr->select(array('`user`'), array('user_id'), array('user_email' => $email_addr), __METHOD__); while ($row = $dbr->fetchObject($res)) { $user = User::newFromId($row->user_id); if (!$user) { continue; } $user->invalidateEmail(); $user->saveSettings(); } } $this->response->setVal('response', 'Postback processed.'); } else { // Log the token-validation problem. Wikia::log(__METHOD__, false, "INVALID TOKEN DURING THIS POSTBACK: " . json_encode($_POST), true); $this->response->setVal('response', 'Postback token did not match expected value. Ignoring.'); } wfProfileOut(__METHOD__); } }
public function log() { wfProfileIn(__METHOD__); $email_id = $this->wg->Request->getInt('wikia-email-id'); $email_addr = $this->wg->Request->getVal('email', ''); // cityId of the wiki which sent the email $city_id = $this->wg->Request->getInt('wikia-email-city-id'); $sender_db = $this->wg->Request->getVal('wikia-db', null); // Verify the token so that we know this POST probably came from SendGrid. $token = $this->wg->Request->getVal('wikia-token'); $event_type = $this->wg->Request->getVal('event', null); $url = $this->wg->Request->getVal('url', ''); $status = $this->wg->Request->getVal('status', ''); $reason = $this->wg->Request->getVal('reason', ''); $generatedToken = wfGetEmailPostbackToken($email_id, $email_addr); if ($this->wg->Request->wasPosted() && $token == $generatedToken) { Wikia::log(__METHOD__, false, "<postback>" . $email_addr . ", " . $status . ", " . $reason . "</postback>\n", true); // Add the token-validated postback to the database. $dbw = wfGetDb(DB_MASTER, array(), $this->wg->WikiaMailerDB); // log postback data $insert_data = array("mail_id" => $email_id, "emailAddr" => $email_addr, "cityId" => $city_id, "eventType" => $event_type, "senderDbName" => $sender_db, "url" => $url, "status" => $status, "reason" => $reason); $dbw->insert(self::POSTBACK_LOG_TABLE_NAME, $insert_data, __METHOD__); // Take action on the eventType. $update_data = array(); switch ($event_type) { case 'click': $update_data = array('clicked' => date('Y-m-d H:i:s')); break; case 'open': $update_data = array('opened' => date('Y-m-d H:i:s')); break; case 'unsubscribe': /* not used now */ break; case 'bounce': $update_data = array('is_bounce' => 1, 'error_status' => $status, 'error_msg' => $reason); break; case 'spamreport': $update_data = array('is_spam' => 1); break; default: Wikia::log(__METHOD__, false, "Unrecognized type: " . json_encode($_POST), true); } if (!empty($email_id) && !empty($update_data)) { $dbw->update(self::MAIL_SEND_TABLE, $update_data, array('id' => intval($email_id)), __METHOD__); } // Invalidate the users email to force them to reverify it if ($event_type == 'bounce') { if (isset($this->wg->SharedDB)) { $dbr = wfGetDB(DB_SLAVE, array(), $this->wg->ExternalSharedDB); } else { $dbr = wfGetDB(DB_SLAVE); } $res = $dbr->select(array('`user`'), array('user_id'), array('user_email' => $email_addr), __METHOD__); while ($row = $dbr->fetchObject($res)) { $user = User::newFromId($row->user_id); if (!$user) { continue; } $user->invalidateEmail(); $user->saveSettings(); } } $this->response->setVal('response', 'Postback processed.'); } else { // Log the token-validation problem. Wikia::log(__METHOD__, false, "INVALID TOKEN DURING THIS POSTBACK: " . json_encode($_POST), true); $this->response->setVal('response', 'Postback token did not match expected value. Ignoring.'); } wfProfileOut(__METHOD__); }