--- /dev/null
+#!/usr/bin/php -f
+<?
+define('FULLME','cron'); // prevent warnings
+//error_reporting(0);
+//ini_set('display_errors',0);
+require_once(dirname(dirname(__FILE__)).'/config.php');
+$tmp = explode('@',$_ENV['RECIPIENT']);
+$address = $tmp[0];
+
+// BOUNCE EMAILS TO NOREPLY
+if ($_ENV['RECIPIENT'] == $CFG->noreplyaddress) {
+ $user->email = $_ENV['SENDER'];
+
+ if (!validate_email($user->email)) {
+ die();
+ }
+
+ $site = get_site();
+ $subject = get_string('noreplybouncesubject','moodle',$site->fullname);
+ $body = get_string('noreplybouncemessage','moodle',$site->fullname)."\n\n";
+
+ $fd = fopen('php://stdin','r');
+ if ($fd) {
+ while(!feof($fd)) {
+ $body .= fgets($fd);
+ }
+ fclose($fd);
+ }
+
+ $user->id = 0; // to prevent anything annoying happening
+
+ $from->firstname = null;
+ $from->lastname = null;
+ $from->email = '<>';
+ $from->maildisplay = true;
+
+ email_to_user($user,$from,$subject,$body);
+ die ();
+}
+/// ALL OTHER PROCESSING
+// we need to split up the address
+$prefix = substr($address,0,4);
+$mod = substr($address,4,2);
+$modargs = substr($address,6,-16);
+$hash = substr($address,-16);
+
+if (substr(md5($prefix.$mod.$modargs.$CFG->sitesecret),0,16) != $hash) {
+ die("HASH DIDN'T MATCH!\n");
+}
+list(,$modid) = unpack('C',base64_decode($mod.'=='));
+
+if ($modid == '0') { // special
+ $modname = 'moodle';
+}
+else {
+ $modname = get_field("modules","name","id",$modid);
+ require_once('mod/'.$modname.'/lib.php');
+}
+$function = $modname.'_process_email';
+
+if (!function_exists($function)) {
+ die();
+}
+$fd = fopen('php://stdin','r');
+if (!$fd) {
+ exit();
+}
+
+while(!feof($fd)) {
+ $body .= fgets($fd);
+}
+
+$function($modargs,$body);
+
+fclose($handle);
+
+
+
+?>
\ No newline at end of file
Please contact your Moodle Administrator.');
}
}
-
// Check that the user account is properly set up
if (user_not_fully_set_up($USER)) {
redirect($CFG->wwwroot .'/user/edit.php?id='. $USER->id .'&course='. SITEID);
* @return boolean
*/
function user_not_fully_set_up($user) {
- return ($user->username != 'guest' and (empty($user->firstname) or empty($user->lastname) or empty($user->email)));
+ return ($user->username != 'guest' and (empty($user->firstname) or empty($user->lastname) or empty($user->email) or over_bounce_threshold($user)));
+}
+
+function over_bounce_threshold($user) {
+
+ global $CFG;
+
+ if (empty($CFG->handlebounces)) {
+ return false;
+ }
+ // set sensible defaults
+ if (empty($CFG->minbounces)) {
+ $CFG->minbounces = 10;
+ }
+ if (empty($CFG->bounceratio)) {
+ $CFG->bounceratio = .20;
+ }
+ $bouncecount = 0;
+ $sendcount = 0;
+ if ($bounce = get_record('user_preferences','userid',$user->id,'name','email_bounce_count')) {
+ $bouncecount = $bounce->value;
+ }
+ if ($send = get_record('user_preferences','userid',$user->id,'name','email_send_count')) {
+ $sendcount = $send->value;
+ }
+ return ($bouncecount >= $CFG->minbounces && $bouncecount/$sendcount >= $CFG->bounceratio);
+}
+
+/**
+ * @param $user - object containing an id
+ * @param $reset - will reset the count to 0
+ */
+function set_send_count($user,$reset=false) {
+ if ($pref = get_record('user_preferences','userid',$user->id,'name','email_send_count')) {
+ $pref->value = (!empty($reset)) ? 0 : $pref->value+1;
+ update_record('user_preferences',$pref);
+ }
+ else if (!empty($reset)) { // if it's not there and we're resetting, don't bother.
+ // make a new one
+ $pref->name = 'email_send_count';
+ $pref->value = 1;
+ $pref->userid = $user->id;
+ insert_record('user_preferences',$pref);
+ }
+}
+
+/**
+* @param $user - object containing an id
+ * @param $reset - will reset the count to 0
+ */
+function set_bounce_count($user,$reset=false) {
+ if ($pref = get_record('user_preferences','userid',$user->id,'name','email_bounce_count')) {
+ $pref->value = (!empty($reset)) ? 0 : $pref->value+1;
+ update_record('user_preferences',$pref);
+ }
+ else if (!empty($reset)) { // if it's not there and we're resetting, don't bother.
+ // make a new one
+ $pref->name = 'email_bounce_count';
+ $pref->value = 1;
+ $pref->userid = $user->id;
+ insert_record('user_preferences',$pref);
+ }
}
/**
return $currentgroup;
}
+function generate_email_processing_address($modid,$modargs) {
+ global $CFG;
+
+ if (empty($CFG->sitesecret)) {
+ set_config('sitesecret',random_string(10));
+ }
+
+ $header = $CFG->mailprefix . substr(base64_encode(pack('C',$modid)),0,2).$modargs;
+ return $header . substr(md5($header.$CFG->sitesecret),0,16).'@'.$CFG->maildomain;
+}
+
+function moodle_process_email($modargs,$body) {
+ // the first char should be an unencoded letter. We'll take this as an action
+ switch ($modargs{0}) {
+ case 'B': { // bounce
+ list(,$userid) = unpack('V',base64_decode(substr($modargs,1,8)));
+ if ($user = get_record_select("user","id=$userid","id,email")) {
+ // check the half md5 of their email
+ $md5check = substr(md5($user->email),0,16);
+ if ($md5check = substr($modargs, -16)) {
+ set_bounce_count($user);
+ }
+ // else maybe they've already changed it?
+ }
+ }
+ break;
+ // maybe more later?
+ }
+}
/// CORRESPONDENCE ////////////////////////////////////////////////
* @return boolean|string Returns "true" if mail was sent OK, "emailstop" if email
* was blocked by user and "false" if there was another sort of error.
*/
-function email_to_user($user, $from, $subject, $messagetext, $messagehtml='', $attachment='', $attachname='', $usetrueaddress=true) {
+function email_to_user($user, $from, $subject, $messagetext, $messagehtml='', $attachment='', $attachname='', $usetrueaddress=true, $repyto='', $replytoname='') {
global $CFG, $FULLME;
if (!empty($user->emailstop)) {
return 'emailstop';
}
+
+ if (over_bounce_threshold($user)) {
+ error_log("User $user->id (".fullname($user).") is over bounce threshold! Not sending.");
+ return false;
+ }
$mail = new phpmailer;
$adminuser = get_admin();
- $mail->Sender = $adminuser->email;
+ // make up an email address for handling bounces
+ if (!empty($CFG->handlebounces)) {
+ $modargs = 'B'.base64_encode(pack('V',$user->id)).substr(md5($user->email),0,16);
+ $mail->Sender = generate_email_processing_address(0,$modargs);
+ }
+ else {
+ $mail->Sender = $adminuser->email;
+ }
if (is_string($from)) { // So we can pass whatever we want if there is need
$mail->From = $CFG->noreplyaddress;
} else {
$mail->From = $CFG->noreplyaddress;
$mail->FromName = fullname($from);
+ if (empty($replyto)) {
+ $mail->AddReplyTo($CFG->noreplyaddress,get_string('noreplyname'));
+ }
}
+
+ if (!empty($replyto)) {
+ $mail->AddReplyTo($replyto,$replytoname);
+ }
+
$mail->Subject = stripslashes($subject);
$mail->AddAddress($user->email, fullname($user) );
}
if ($mail->Send()) {
+ set_send_count($user);
return true;
} else {
mtrace('ERROR: '. $mail->ErrorInfo);
auth_user_update($userold, $usernew);
};
+ if ($userold->email != $usernew->email) {
+ set_bounce_count($usernew,true);
+ set_send_count($usernew,true);
+ }
+
add_to_log($course->id, "user", "update", "view.php?id=$user->id&course=$course->id", "");
if ($user->id == $USER->id) {
$strparticipants = get_string("participants");
$strnewuser = get_string("newuser");
+ if (over_bounce_threshold($user) && empty($err['email'])) {
+ $err['email'] = get_string('toomanybounces');
+ }
+
if (($user->firstname and $user->lastname) or $newaccount) {
if ($newaccount) {
$userfullname = $strnewuser;
if (empty($usernew->email))
$err["email"] = get_string("missingemail");
+ if (over_bounce_threshold($user) && $user->email == $usernew->email)
+ $err['email'] = get_string('toomanybounces');
+
if (empty($usernew->description) and !isadmin())
$err["description"] = get_string("missingdescription");