EmailReminder plugin to send reminders about various things

* Needs some cleanup and testing
* Email templates need work
* More documentation

Squashed commit of the following:

commit 1c7b418dad5ec1b7713d61b6a42d6d7a394d500f
Author: Zach Copley <zach@status.net>
Date:   Fri Jun 17 02:17:31 2011 -0700

    * Set the reminder interval correctly

commit ae0ded8cf95210f54b4cd58dac0eeeedf2d99c67
Author: Zach Copley <zach@status.net>
Date:   Fri Jun 17 02:15:01 2011 -0700

    Send email reminders for invitations

commit 1b596d08f5dbe765a16fbdfbd21e2ad68e8b0058
Author: Zach Copley <zach@status.net>
Date:   Thu Jun 16 23:53:48 2011 -0700

    Handle multiple confirmation types

commit 25d83351d878f39498cd6a14fddde27f1afef2ca
Author: Zach Copley <zach@status.net>
Date:   Thu Jun 16 18:04:57 2011 -0700

    Actually send reminders and record a record of doing so

commit 9ffc2dbee15cacc7e7f9feab492185ee9964a17e
Author: Zach Copley <zach@status.net>
Date:   Thu Jun 16 14:20:16 2011 -0700

    Make the queue handling actually work

commit 2a6ce3c17c045bdb0a3ddf36f2c290c9c48eb003
Author: Zach Copley <zach@status.net>
Date:   Thu Jun 16 13:27:56 2011 -0700

    Fix syntax errors

commit 054b54847dfadc490aa7d7dff12d473af31c99bb
Author: Zach Copley <zach@status.net>
Date:   Thu Jun 16 00:36:37 2011 -0700

    Registration reminders should work now, but code is untested

commit b44117017b64635aae340c260167cf1efab9b2ae
Merge: 9d1441d f74de88
Author: Zach Copley <zach@status.net>
Date:   Tue Jun 14 09:43:19 2011 -0700

    Merge branch 'email-reminder' of gitorious.org:~zcopley/statusnet/zcopleys-clone into email-reminder

    * 'email-reminder' of gitorious.org:~zcopley/statusnet/zcopleys-clone:
      Stubby EmailReminderPlugin and data class
      Remove bogus data class

    Conflicts:
    	plugins/EmailReminder/EmailReminderPlugin.php
    	plugins/EmailReminder/classes/Email_reminder.php

commit 9d1441d7366df57e38cdfaf96e006f7d2f29d889
Author: Zach Copley <zach@status.net>
Date:   Tue Jun 14 09:23:23 2011 -0700

    Most of the other classes needed to send email reminders

commit 4e9bb11dbb23556bf5c1847e7a127084b5cc217c
Author: Zach Copley <zach@status.net>
Date:   Mon Jun 13 12:10:55 2011 -0700

    size -> length

commit a9ea80ef8abae1e64d5713091baedd931b7184e2
Author: Zach Copley <zach@status.net>
Date:   Fri Jun 10 16:38:06 2011 -0400

    Stubby EmailReminderPlugin and data class

commit 5d893f982209b245cb9113a59e49721dd6e191b6
Author: Zach Copley <zach@status.net>
Date:   Fri Jun 10 14:01:48 2011 -0400

    Remove bogus data class

commit f74de8841a98add73536fd8a4d3cee76035b491c
Author: Zach Copley <zach@status.net>
Date:   Fri Jun 10 16:38:06 2011 -0400

    Stubby EmailReminderPlugin and data class

commit 5b14370918233e5112a95da94567c4ed83429bc9
Author: Zach Copley <zach@status.net>
Date:   Fri Jun 10 14:01:48 2011 -0400

    Remove bogus data class
This commit is contained in:
Zach Copley 2011-06-17 02:24:34 -07:00
parent b24e4fd9fe
commit a35392da2f
14 changed files with 986 additions and 183 deletions

View File

@ -1,183 +0,0 @@
<?php
/**
* Data class for counting greetings
*
* PHP version 5
*
* @category Data
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
/**
* Data class for counting greetings
*
* We use the DB_DataObject framework for data classes in StatusNet. Each
* table maps to a particular data class, making it easier to manipulate
* data.
*
* Data classes should extend Memcached_DataObject, the (slightly misnamed)
* extension of DB_DataObject that provides caching, internationalization,
* and other bits of good functionality to StatusNet-specific data classes.
*
* @category Action
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* @see DB_DataObject
*/
class User_greeting_count extends Memcached_DataObject
{
public $__table = 'user_greeting_count'; // table name
public $user_id; // int(4) primary_key not_null
public $greeting_count; // int(4)
/**
* Get an instance by key
*
* This is a utility method to get a single instance with a given key value.
*
* @param string $k Key to use to lookup (usually 'user_id' for this class)
* @param mixed $v Value to lookup
*
* @return User_greeting_count object found, or null for no hits
*
*/
function staticGet($k, $v=null)
{
return Memcached_DataObject::staticGet('User_greeting_count', $k, $v);
}
/**
* return table definition for DB_DataObject
*
* DB_DataObject needs to know something about the table to manipulate
* instances. This method provides all the DB_DataObject needs to know.
*
* @return array array of column definitions
*/
function table()
{
return array('user_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
'greeting_count' => DB_DATAOBJECT_INT);
}
/**
* return key definitions for DB_DataObject
*
* DB_DataObject needs to know about keys that the table has, since it
* won't appear in StatusNet's own keys list. In most cases, this will
* simply reference your keyTypes() function.
*
* @return array list of key field names
*/
function keys()
{
return array_keys($this->keyTypes());
}
/**
* return key definitions for Memcached_DataObject
*
* Our caching system uses the same key definitions, but uses a different
* method to get them. This key information is used to store and clear
* cached data, so be sure to list any key that will be used for static
* lookups.
*
* @return array associative array of key definitions, field name to type:
* 'K' for primary key: for compound keys, add an entry for each component;
* 'U' for unique keys: compound keys are not well supported here.
*/
function keyTypes()
{
return array('user_id' => 'K');
}
/**
* Magic formula for non-autoincrementing integer primary keys
*
* If a table has a single integer column as its primary key, DB_DataObject
* assumes that the column is auto-incrementing and makes a sequence table
* to do this incrementation. Since we don't need this for our class, we
* overload this method and return the magic formula that DB_DataObject needs.
*
* @return array magic three-false array that stops auto-incrementing.
*/
function sequenceKey()
{
return array(false, false, false);
}
/**
* Increment a user's greeting count and return instance
*
* This method handles the ins and outs of creating a new greeting_count for a
* user or fetching the existing greeting count and incrementing its value.
*
* @param integer $user_id ID of the user to get a count for
*
* @return User_greeting_count instance for this user, with count already incremented.
*/
static function inc($user_id)
{
$gc = User_greeting_count::staticGet('user_id', $user_id);
if (empty($gc)) {
$gc = new User_greeting_count();
$gc->user_id = $user_id;
$gc->greeting_count = 1;
$result = $gc->insert();
if (!$result) {
// TRANS: Exception thrown when the user greeting count could not be saved in the database.
// TRANS: %d is a user ID (number).
throw Exception(sprintf(_m("Could not save new greeting count for %d."),
$user_id));
}
} else {
$orig = clone($gc);
$gc->greeting_count++;
$result = $gc->update($orig);
if (!$result) {
// TRANS: Exception thrown when the user greeting count could not be saved in the database.
// TRANS: %d is a user ID (number).
throw Exception(sprintf(_m('Could not increment greeting count for %d.'),
$user_id));
}
}
return $gc;
}
}

View File

@ -0,0 +1,209 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Plugin for sending email reminders about various things
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category OnDemand
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* Email reminder plugin
*
* @category Plugin
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class EmailReminderPlugin extends Plugin
{
/**
* Set up email_reminder table
*
* @see Schema
* @see ColumnDef
*
* @return boolean hook value; true means continue processing, false means stop.
*/
function onCheckSchema()
{
$schema = Schema::get();
$schema->ensureTable('email_reminder', Email_reminder::schemaDef());
return true;
}
/**
* Load related modules when needed
*
* @param string $cls Name of the class to be loaded
*
* @return boolean hook value; true means continue processing, false
* means stop.
*/
function onAutoload($cls) {
$base = dirname(__FILE__);
$lower = strtolower($cls);
$files = array("$base/classes/$cls.php",
"$base/lib/$lower.php");
if (substr($lower, -6) == 'action') {
$files[] = "$base/actions/" . substr($lower, 0, -6) . ".php";
}
foreach ($files as $file) {
if (file_exists($file)) {
include_once $file;
return false;
}
}
return true;
}
/**
* Register our queue handlers
*
* @param QueueManager $qm Current queue manager
*
* @return boolean hook value
*/
function onEndInitializeQueueManager($qm)
{
$qm->connect('siterem', 'SiteConfirmReminderHandler');
$qm->connect('uregrem', 'UserConfirmRegReminderHandler');
$qm->connect('uinvrem', 'UserInviteReminderHandler');
return true;
}
function onEndDocFileForTitle($title, $paths, &$filename)
{
if (empty($filename)) {
$filename = dirname(__FILE__) . '/mail-src/' . $title;
return false;
}
return true;
}
/**
*
* @param type $object
* @param type $subject
* @param type $day
*/
static function sendReminder($type, $object, $subject, $day)
{
common_debug("QQQQQ sendReminder() enter ... ", __FILE__);
$title = "{$type}-{$day}";
common_debug("QQQQ title = {$title}", __FILE__);
// Record the fact that we sent a reminder
if (self::sendReminderEmail($type, $object, $subject, $title)) {
common_debug("Recording reminder record for {$object->address}", __FILE__);
try {
Email_reminder::recordReminder($type, $object, $day);
} catch (Exception $e) {
// oh noez
common_log(LOG_ERR, $e->getMessage(), __FILE__);
}
}
common_debug("QQQQQ sendReminder() exit ... ", __FILE__);
return true;
}
/**
*
* @param type $object
* @param type $subject
* @param type $title
* @return type
*/
static function sendReminderEmail($type, $object, $subject, $title=null) {
$sitename = common_config('site', 'name');
$recipients = array($object->address);
$inviter = null;
$inviterurl = null;
if ($type == UserInviteReminderHandler::INVITE_REMINDER) {
$user = User::staticGet($object->user_id);
if (!empty($user)) {
$profile = $user->getProfile();
$inviter = $profile->getBestName();
$inviterUrl = $profile->profileurl;
}
}
$headers['From'] = mail_notify_from();
$headers['To'] = trim($object->address);
// TRANS: Subject for confirmation e-mail.
// TRANS: %s is the StatusNet sitename.
$headers['Subject'] = $subject;
$headers['Content-Type'] = 'text/html; charset=UTF-8';
$confirmUrl = common_local_url('register', array('code' => $object->code));
$template = DocFile::forTitle($title, DocFile::mailPaths());
$body = $template->toHTML(
array(
'confirmurl' => $confirmUrl,
'inviter' => $inviter,
'inviterurl' => $inviterUrl
// @todo private invitation message
)
);
return mail_send($recipients, $headers, $body);
}
/**
*
* @param type $versions
* @return type
*/
function onPluginVersion(&$versions)
{
$versions[] = array(
'name' => 'EmailReminder',
'version' => STATUSNET_VERSION,
'author' => 'Zach Copley',
'homepage' => 'http://status.net/wiki/Plugin:EmailReminder',
'rawdescription' => _m('Send email reminders for various things.')
);
return true;
}
}

View File

@ -0,0 +1,154 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* Data class for email reminders
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Data
* @package EmailReminder
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class Email_reminder extends Managed_DataObject
{
const INVITE_REMINDER = 'invite'; // @todo Move this to the invite reminder handler
public $__table = 'email_reminder';
public $type; // type of reminder
public $code; // confirmation code
public $days; // number of days after code was created
public $sent; // timestamp
public $created; // timestamp
public $modified; // timestamp
/**
* Get an instance by key
*
* This is a utility method to get a single instance with a given key value.
*
* @param string $k Key to use to lookup
* @param mixed $v Value to lookup
*
* @return QnA_Answer object found, or null for no hits
*
*/
function staticGet($k, $v=null)
{
return Memcached_DataObject::staticGet('email_reminder', $k, $v);
}
/**
*
* @param type $type
* @param type $confirm
* @param type $day
* @return type
*/
static function needsReminder($type, $confirm, $days) {
$reminder = new Email_reminder();
$reminder->type = $type;
$reminder->code = $confirm->code;
$reminder->days = $days;
$result = $reminder->find(true);
if (empty($result)) {
return true;
}
return false;
}
/**
*
* @param type $type
* @param type $confirm
* @param type $day
* @return type
*/
static function recordReminder($type, $confirm, $days) {
$reminder = new Email_reminder();
$reminder->type = $type;
$reminder->code = $confirm->code;
$reminder->days = $days;
$reminder->sent = $reminder->created = common_sql_now();
$result = $reminder->insert();
if (empty($result)) {
common_log_db_error($reminder, 'INSERT', __FILE__);
throw new ServerException(
_m('Database error inserting reminder record.')
);
}
return $result;
}
/**
* Data definition for email reminders
*/
public static function schemaDef()
{
return array(
'description' => 'Record of email reminders that have been sent',
'fields' => array(
'type' => array(
'type' => 'varchar',
'length' => 255,
'not null' => true,
'description' => 'type of reminder'
),
'code' => array(
'type' => 'varchar',
'not null' => 'true',
'length' => 255,
'description' => 'confirmation code'
),
'days' => array(
'type' => 'int',
'not null' => 'true',
'description' => 'number of days since code creation'
),
'sent' => array(
'type' => 'datetime',
'not null' => true,
'description' => 'Date and time the reminder was sent'
),
'created' => array(
'type' => 'datetime',
'not null' => true,
'description' => 'Date and time the record was created'
),
'modified' => array(
'type' => 'timestamp',
'not null' => true,
'description' => 'Date and time the record was last modified'
),
),
'primary key' => array('type', 'code', 'days'),
'indexes' => array(
'sent_idx' => array('sent'),
),
);
}
}

View File

@ -0,0 +1,112 @@
<?php
/*
* StatusNet - the distributed open-source microblogging tool
*
* Handler for reminder queue items which send reminder emails to all users
* we would like to complete a given process (e.g.: registration).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Email
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
/**
* Handler for reminder queue items which send reminder emails to all users
* we would like to complete a given process (e.g.: registration)
*
* @category Email
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class SiteConfirmReminderHandler extends QueueHandler
{
/**
* Return transport keyword which identifies items this queue handler
* services; must be defined for all subclasses.
*
* Must be 8 characters or less to fit in the queue_item database.
* ex "email", "jabber", "sms", "irc", ...
*
* @return string
*/
function transport()
{
return 'siterem';
}
/**
* Handle the site
*
* @param string $reminderType type of reminder to send
* @return boolean true on success, false on failure
*/
function handle($reminderType)
{
$qm = QueueManager::get();
try {
switch($reminderType) {
case UserConfirmRegReminderHandler::REGISTER_REMINDER:
$confirm = new Confirm_address();
$confirm->address_type = $object;
$confirm->find();
while ($confirm->fetch()) {
try {
$qm->enqueue($confirm, 'uregrem');
} catch (Exception $e) {
common_log(LOG_WARNING, $e->getMessage());
continue;
}
}
break;
case UserInviteReminderHandler::INVITE_REMINDER:
$invitation = new Invitation();
$invitation->find();
while ($invitation->fetch()) {
try {
$qm->enqueue($invitation, 'uinvrem');
} catch (Exception $e) {
common_log(LOG_WARNING, $e->getMessage());
continue;
}
}
break;
default:
// WTF?
common_log(
LOG_ERR,
"Received unknown confirmation address type",
__FILE__
);
}
} catch (Exception $e) {
common_log(LOG_ERR, $e->getMessage());
return false;
}
return true;
}
}

View File

@ -0,0 +1,126 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
*
* Handler for queue items of type 'uregem' - sends email registration
* confirmation reminders to a particular user.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Email
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
/**
* Handler for queue items of type 'uregrem'
*
* @category Email
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class UserConfirmRegReminderHandler extends UserReminderHandler {
const REGISTER_REMINDER = 'register';
/**
* Return transport keyword which identifies items this queue handler
* services; must be defined for all subclasses.
*
* Must be 8 characters or less to fit in the queue_item database.
* ex "email", "jabber", "sms", "irc", ...
*
* @return string
*/
function transport() {
return 'uregrem';
}
/**
* Send an email registration confirmation reminder until the user
* confirms her registration. We'll send a reminder after one day,
* three days, and a full week.
*
* @todo abstract this bit further
*
* @param Confirm_address $confirm
* @return boolean success value
*/
function sendNextReminder($confirm)
{
$regDate = strtotime($confirm->modified); // Seems like my best bet
$now = strtotime('now');
// Days since registration
$days = ($now - $regDate) / 86499; // 60*60*24 = 86499
// Welcome to one of the ugliest switch statement I've ever written
switch($days) {
case ($days > 1 && $days < 2):
if (Email_reminder::needsReminder(self::REGISTER_REMINDER, $confirm, 1)) {
common_log(LOG_INFO, "Sending one day registration confirmation reminder to {$confirm->address}", __FILE__);
$subject = _m("Reminder - please confirm your registration!");
return EmailReminderPlugin::sendReminder(
self::REGISTER_REMINDER,
$confirm,
$subject,
1);
} else {
return true;
}
break;
case ($days > 3 && $days < 4):
if (Email_reminder::needsReminder(self::REGISTER_REMINDER, $confirm, 3)) {
common_log(LOG_INFO, "Sending three day registration confirmation reminder to {$confirm->address}", __FILE__);
$subject = _m("Second reminder - please confirm your registration!");
return EmailReminderPlugin::sendReminder(
self::REGISTER_REMINDER,
$confirm,
$subject,
3
);
} else {
return true;
}
break;
case ($days > 7 && $days < 8):
if (Email_reminder::needsReminder(self::REGISTER_REMINDER, $confirm, 7)) {
common_log(LOG_INFO, "Sending one week registration confirmation reminder to {$confirm->address}", __FILE__);
$subject = _m("Final reminder - please confirm your registration!");
return EmailReminderPlugin::sendReminder(
self::REGISTER_REMINDER,
$confirm,
$subject,
7
);
} else {
return true;
}
break;
}
return true;
}
}

View File

@ -0,0 +1,110 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
*
* Handler for queue items of type 'uinvrem' - sends an email reminder to
* an email address of someone who has been invited to the site
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Email
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
/**
* Handler for queue items of type 'uinvrem' (user invite reminder)
*
* @category Email
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class UserInviteReminderHandler extends UserReminderHandler {
const INVITE_REMINDER = 'invite';
/**
* Return transport keyword which identifies items this queue handler
* services; must be defined for all subclasses.
*
* Must be 8 characters or less to fit in the queue_item database.
* ex "email", "jabber", "sms", "irc", ...
*
* @return string
*/
function transport() {
return 'uinvrem';
}
/**
* Send an invitation reminder. We'll send one after one day, and then
* one after three days.
*
* @todo Abstract this stuff further
*
* @param Invitation $invitation
* @return boolean success value
*/
function sendNextReminder($invitation)
{
$invDate = strtotime($invitation->created);
$now = strtotime('now');
// Days since first invitation was sent
$days = ($now - $invDate) / 86499; // 60*60*24 = 86499
$siteName = common_config('site', 'name');
switch($days) {
case ($days > 1 && $days < 2):
if (Email_reminder::needsReminder(self::INVITE_REMINDER, $invitation, 1)) {
common_log(LOG_INFO, "Sending one day invitation reminder to {$invitation->address}", __FILE__);
$subject = _m("Reminder - You have been invited to join {$siteName}!");
return EmailReminderPlugin::sendReminder(
self::INVITE_REMINDER,
$invitation,
$subject,
1);
} else {
return true;
}
break;
case ($days > 3 && $days < 4):
if (Email_reminder::needsReminder(self::INVITE_REMINDER, $invitation, 3)) {
common_log(LOG_INFO, "Sending three day invitation reminder to {$invitation->address}", __FILE__);
$subject = _m("Final reminder - you have been invited to join {$siteName}!");
return EmailReminderPlugin::sendReminder(
self::INVITE_REMINDER,
$invitation,
$subject,
3
);
} else {
return true;
}
break;
}
return true;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
*
* Base handler for email reminders
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Email
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
/**
* Handler for email reminder queue items
*
* @category Email
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class UserReminderHandler extends QueueHandler {
/**
* Send the next email reminder to the confirm address
*
* @param Confirm_address $confirm the confirmation email/code
* @return boolean true on success, false on failure
*/
function handle($confirm) {
return $this->sendNextReminder($confirm);
}
/**
* Send the next reminder if one needs sending.
* Subclasses must override
*
* @param Confirm_address $confirm the confirmation email/code
*/
function sendNextReminder($confirm)
{
}
}

View File

@ -0,0 +1,26 @@
First reminder...
%%arg.inviter%% has invited you to join them on %%site.name%%.
%%site.name%% is a micro-blogging service that lets you keep
up-to-date with people you know and people who interest you.
You can also share news about yourself, your thoughts, or your life
online with people who know about you.
It's great for meeting new people who share your interests.
You can see %%arg.inviter%%'s profile page on %%site.name%% here:
> [%%arg.inviterurl%%](%%arg.inviterurl%%)
If you'd like to try the service, click on the link below to accept
the invitation.
> [%%arg.confirmurl%%](%%arg.confirmurl%%)
If not, you can ignore this message. Thanks for your patience and your time.
Sincerely,
%%site.name%%

View File

@ -0,0 +1,26 @@
Second and final reminder...
%%arg.inviter%% has invited you to join them on %%site.name%%.
%%site.name%% is a micro-blogging service that lets you keep
up-to-date with people you know and people who interest you.
You can also share news about yourself, your thoughts, or your life
online with people who know about you.
It's great for meeting new people who share your interests.
You can see %%arg.inviter%%'s profile page on %%site.name%% here:
> [%%arg.inviterurl%%](%%arg.inviterurl%%)
If you'd like to try the service, click on the link below to accept
the invitation.
> [%%arg.confirmurl%%](%%arg.confirmurl%%)
If not, you can ignore this message. Thanks for your patience and your time.
Sincerely,
%%site.name%%

View File

@ -0,0 +1,9 @@
Hey, it's been a whole day!
Someone (probably you) has requested an account on %%site.name%% using this email address.
To confirm the address, click the following URL or copy it into the address bar of your browser.
> [%%arg.confirmurl%%](%%arg.confirmurl%%)
If it was not you, you can safely ignore this message.

View File

@ -0,0 +1,9 @@
Hey, it's been three days!!
Someone (probably you) has requested an account on %%site.name%% using this email address.
To confirm the address, click the following URL or copy it into the address bar of your browser.
> [%%arg.confirmurl%%](%%arg.confirmurl%%)
If it was not you, you can safely ignore this message.

View File

@ -0,0 +1,9 @@
IT'S BEEN A WHOLE WEEK! Final reminder...
Someone (probably you) has requested an account on %%site.name%% using this email address.
To confirm the address, click the following URL or copy it into the address bar of your browser.
> [%%arg.confirmurl%%](%%arg.confirmurl%%)
If it was not you, you can safely ignore this message.

View File

@ -0,0 +1 @@
* * * * * /opt/local/bin/php /path/to/statusnet/plugins/EmailReminder/scripts/sendemailreminder.php -t all -a -q > /tmp/cron.log

View File

@ -0,0 +1,132 @@
#!/usr/bin/env php
<?php
/*
* StatusNet - a distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
$shortoptions = 't:e:au';
$longoptions = array('type=', 'email=', 'all', 'universe');
$helptext = <<<END_OF_SENDEMAILREMINDER_HELP
sendemailreminder.php [options]
Send an email summary of the inbox to users
-t --type type of reminder to send (register | invite | all)
-e --email email address to send reminder to
-a --all send reminder to all addresses
-u --universe send reminder to all addresses on all sites
END_OF_SENDEMAILREMINDER_HELP;
require_once INSTALLDIR . '/scripts/commandline.inc';
$quiet = have_option('q', 'quiet');
$types = array(
// registration confirmation reminder
'register' => array(
'type' => 'register',
'className' => 'Confirm_address',
'utransport' => 'uregrem'
),
// invitation confirmation reminder
'invite' => array(
'type' => 'invite',
'className' => 'Invitation',
'utransport' => 'uinvrem'
)
// ... add more here
);
$type = null;
if (have_option('t', 'type')) {
$type = trim(get_option_value('t', 'type'));
if (!in_array($type, array_keys($types)) && $type !== 'all') {
print _m("Unknown reminder type: {$type}.\n");
exit(1);
}
} else {
show_help();
exit(1);
}
$reminders = array();
switch($type) {
case 'register':
$reminders[] = $types['register'];
break;
case 'invite':
$reminders[] = $types['invite'];
break;
case 'all':
$reminders = $types;
break;
}
if (have_option('u', 'universe')) {
$sn = new Status_network();
if ($sn->find()) {
while ($sn->fetch()) {
$server = $sn->getServerName();
StatusNet::init($server);
// Different queue manager, maybe!
$qm = QueueManager::get();
foreach ($reminders as $reminder) {
extract($reminder);
$qm->enqueue($type, 'siterem');
if (!$quiet) { print "Sent pending {$type} reminders to all unconfirmed addresses in the known universe.\n"; }
}
}
}
} else {
$qm = QueueManager::get();
try {
// enqueue reminder for specific email address or all unconfirmed addresses
if (have_option('e', 'email')) {
$address = trim(get_option_value('e', 'email'));
foreach ($reminders as $reminder) {
// real bad voodoo here
extract($reminder);
$confirm = new $className;
$confirm->address = $address;
$result = $confirm->find(true);
if (empty($result)) {
throw new Exception("No confirmation code found for {$address}.");
}
$qm->enqueue($confirm, $utransport);
if (!$quiet) { print "Sent all pending {$type} reminder to {$address}.\n"; }
}
} else if (have_option('a', 'all')) {
foreach ($reminders as $reminder) {
extract($reminder);
$qm->enqueue($type, 'siterem');
if (!$quiet) { print "Sent pending {$type} reminders to all unconfirmed addresses on the site.\n"; }
}
} else {
show_help();
exit(1);
}
} catch (Exception $e) {
if (!$quiet) { print $e->getMessage() . "\n"; }
common_log(LOG_ERR, $e->getMessage(), __FILE__);
exit(1);
}
}