Commit 9b9b2a5c authored by Andrew Robert Nicols's avatar Andrew Robert Nicols Committed by Richard Mansfield
Browse files

Email processor to handle incoming bounce email


Signed-off-by: default avatarAndrew Robert Nicols <andrew.nicols@luns.net.uk>
parent 10a1ed12
......@@ -1289,6 +1289,13 @@ function xmldb_core_upgrade($oldversion=0) {
add_field($table, $field);
}
if ($oldversion < 2009111201) {
$table = new XMLDBTable('artefact_internal_profile_email');
$field = new XMLDBField('mailsbounced');
$field->setAttributes(XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, null, null, 0);
add_field($table, $field);
}
return $status;
}
......
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
* http://wiki.mahara.org/Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package mahara
* @subpackage core
* @author Andrew Nicols <andrew.nicols@luns.net.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2009 Lancaster University Network Services Limited
* http://www.luns.net.uk
*/
define('INTERNAL', 1);
define('PUBLIC', 1);
define('TITLE', '');
require(dirname(dirname(__FILE__)).'/init.php');
$address = $_ENV['RECIPIENT'];
log_debug('---------- started processing email at ' . date('r', time()) . ' ----------');
log_debug('-- mail from ' . $address );
$email = process_email($address);
log_debug('---------- finished processing email at ' . date('r', time()) . ' ----------');
?>
......@@ -467,6 +467,60 @@ function generate_email_processing_address($userid, $userto, $type='B') {
return $mailprefix . $args . substr(md5($mailprefix . $userto->email . $installation_key), 0, 16) . '@' . $maildomain;
}
/**
* Check whether an email account is over the site-wide bounce threshold.
* If the user is over threshold, then e-mail is disabled for their
* account, and they are sent a notification to notify them of the change.
*
* @param object $mailinfo The row from artefact_internal_profile_email for
* the user being processed.
* @return boolean false if the user is not over threshold, true if they
* are.
*/
function check_overcount($mailinfo) {
// if we don't handle bounce e-mails, then we can't be over threshold
if (!get_config('bounces_handle')) {
return false;
}
if ((! $minbounces = get_config('bounces_min')) || (! $bounceratio = get_config('bounces_ratio'))) {
return false;
}
if ($mailinfo->mailssent == 0) {
return false;
}
// If the bouncecount is larger than the allowed amount
// and the bounce count ratio (bounces/total sent) is larger than the
// bounceratio, then disable email
$overlimit = ($mailinfo->mailsbounced >= $minbounces) && ($mailinfo->mailsbounced/$mailinfo->mailssent >= $bounceratio);
if ($overlimit) {
if (get_account_preference($mailinfo->owner,'maildisabled') != 1) {
// Disable the e-mail account
db_begin();
set_account_preference($mailinfo->owner, 'maildisabled', 1);
$lang = get_user_language($mailinfo->owner);
// Send a notification that e-mail has been disabled
$message = new StdClass;
$message->users = array($mailinfo->owner);
$message->subject = get_string_from_language($lang, 'maildisabled', 'account');
$message->message = get_string_from_language($lang, 'maildisabledbounce', 'account', get_config('wwwroot') . 'account/');
require_once('activity.php');
activity_occurred('maharamessage', $message);
db_commit();
}
return true;
}
return false;
}
/**
* Update the send count for the specified e-mail address
*
......@@ -485,6 +539,81 @@ function update_send_count($userto, $reset=false) {
}
}
/**
* Update the bounce count for the specified e-mail address
*
* @param object $userto object to update count for. Must contain email and
* user id
* @param boolean reset Reset the sent mail count to 0 (optional).
*/
function update_bounce_count($userto, $reset=false) {
if (!$userto->id) {
// We need a user id to update the bounce count.
return false;
}
if ($mailinfo = get_record_select('artefact_internal_profile_email', 'owner = ? AND email = ? AND principal = 1', array($userto->id, $userto->email))) {
$mailinfo->mailsbounced = (!empty($reset)) ? 0 : $mailinfo->mailsbounced+1;
update_record('artefact_internal_profile_email', $mailinfo, array('email' => $userto->email, 'owner' => $userto->id));
}
}
/**
* Process an incoming email
*
* @param string $address the email address to process
*/
function process_email($address) {
$email = new StdClass;
if (strlen($address) <= 30) {
log_debug ('-- Email address not long enough to contain valid data.');
return $email;
}
if (!strstr($address, '@')) {
log_debug ('-- Email address does not contain @.');
return $email;
}
list($email->localpart,$email->domain) = explode('@',$address);
// The prefix is stored in the first four characters
$email->prefix = substr($email->localpart,0,4);
// The type of message received is a one letter code
$email->type = substr($email->localpart,4,1);
// The userid should be available immediately afterwards
list(,$email->userid) = unpack('V',base64_decode(substr($email->localpart,5,8)));
// Any additional arguments
$email->args = substr($email->localpart,13,-16);
// And a hash of the intended recipient for authentication
$email->addresshash = substr($email->localpart,-16);
if (!$email->userid) {
log_debug('-- no userid associated with this email address');
return $email;
}
switch ($email->type) {
case 'B': // E-mail bounces
if ($user = get_record_select('artefact_internal_profile_email', 'owner = ? AND principal = 1', array($email->userid))) {
$mailprefix = get_config('bounceprefix');
$maildomain = get_config('bouncedomain');
$installation_key = get_config('installation_key');
// check the half md5 of their email
$md5check = substr(md5($mailprefix . $user->email . $installation_key), 0, 16);
$user->id = $user->owner;
if ($md5check == substr($email->addresshash, -16)) {
update_bounce_count($user);
check_overcount($user);
}
// else maybe they've already changed their email address
}
break;
// No more cases yet
}
return $email;
}
/**
* converts a user object to a string representation of the user suitable for
* the current user (or specified user) to see
......
......@@ -28,7 +28,7 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config->version = 2009111200;
$config->version = 2009111201;
$config->release = '1.2.0rc2dev';
$config->minupgradefrom = 2008040200;
$config->minupgraderelease = '1.0.0 (release tag 1.0.0_RELEASE)';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment