1
0
mirror of https://github.com/e107inc/e107.git synced 2025-08-08 15:46:44 +02:00

More mailer stuff - bug fixes, cron-driven bounce handling, timed send, notify on run complete

This commit is contained in:
e107steved
2009-11-27 21:42:46 +00:00
parent fb01599b92
commit 5d3aaaa541
14 changed files with 886 additions and 258 deletions

View File

@@ -11,9 +11,9 @@
| GNU General Public License (http://gnu.org/). | GNU General Public License (http://gnu.org/).
| |
| $Source: /cvs_backup/e107_0.8/e107_admin/cron.php,v $ | $Source: /cvs_backup/e107_0.8/e107_admin/cron.php,v $
| $Revision: 1.23 $ | $Revision: 1.24 $
| $Date: 2009-11-22 14:10:05 $ | $Date: 2009-11-27 21:42:46 $
| $Author: e107coders $ | $Author: e107steved $
+----------------------------------------------------------------------------+ +----------------------------------------------------------------------------+
*/ */
@@ -49,9 +49,11 @@ class cron
$mes = $mes = e107::getMessage(); $mes = $mes = e107::getMessage();
$this->cronAction = e_QUERY; $this->cronAction = e_QUERY;
// The 'available' flag only gives the option to configure the cron if the underlying feature is enabled
$this->coreCrons['_system_cron'] = array( $this->coreCrons['_system_cron'] = array(
0 => array('name' => 'Test Email', 'function' => 'sendEmail', 'description' => 'Send a test email to '.$pref['siteadminemail'].'<br />Recommended to test the scheduling system.'), 0 => array('name' => 'Test Email', 'function' => 'sendEmail', 'description' => 'Send a test email to '.$pref['siteadminemail'].'<br />Recommended to test the scheduling system.'),
1 => array('name' => 'Mail Queue', 'function' => 'procEmailQueue', 'description' => 'Process mail queue'), 1 => array('name' => 'Mail Queue', 'function' => 'procEmailQueue', 'description' => 'Process mail queue'),
2 => array('name' => 'Mail Bounce Check', 'function' => 'procEmailBounce', 'description' => 'Check for bounced emails', 'available' => vartrue($pref['mail_bounce_auto'])),
// 1 => array('name'=>'User Purge', 'function' => 'userPurge', 'description'=>'Purge Unactivated Users'), // 1 => array('name'=>'User Purge', 'function' => 'userPurge', 'description'=>'Purge Unactivated Users'),
// 2 => array('name'=>'User UnActivated', 'function' => 'userUnactivated', 'description'=>'Resend activation email to unactivated users.'), // 2 => array('name'=>'User UnActivated', 'function' => 'userUnactivated', 'description'=>'Resend activation email to unactivated users.'),
// 3 => array('name'=>'News Sticky', 'function' => 'newsPurge', 'description'=>'Remove Sticky News Items') // 3 => array('name'=>'News Sticky', 'function' => 'newsPurge', 'description'=>'Remove Sticky News Items')
@@ -314,7 +316,7 @@ function setCronPwd()
{ {
global $pref; global $pref;
$core_cron = $this->coreCrons; $core_cron = $this->coreCrons; // May need to check 'available' flag here
$new_cron = e107::getAddonConfig('e_cron'); $new_cron = e107::getAddonConfig('e_cron');
$this->e_cron = array_merge($core_cron,$new_cron); $this->e_cron = array_merge($core_cron,$new_cron);
return; return;
@@ -369,6 +371,8 @@ function setCronPwd()
foreach($e_cron as $plug=>$cfg) foreach($e_cron as $plug=>$cfg)
{ {
foreach($cfg as $class=>$cron) foreach($cfg as $class=>$cron)
{
if (!isset($cron['available']) || $cron['available']) // Only display cron functions which are available
{ {
$c = $plug.'__'. $cron['function']; // class and function. $c = $plug.'__'. $cron['function']; // class and function.
$sep = array(); $sep = array();
@@ -509,6 +513,7 @@ function setCronPwd()
</tr>"; </tr>";
} }
} }
}
$text .= " $text .= "
<tr > <tr >

View File

@@ -9,8 +9,8 @@
* Administration - Site Maintenance * Administration - Site Maintenance
* *
* $Source: /cvs_backup/e107_0.8/e107_admin/mailout.php,v $ * $Source: /cvs_backup/e107_0.8/e107_admin/mailout.php,v $
* $Revision: 1.29 $ * $Revision: 1.30 $
* $Date: 2009-11-24 20:40:34 $ * $Date: 2009-11-27 21:42:46 $
* $Author: e107steved $ * $Author: e107steved $
* *
*/ */
@@ -18,7 +18,7 @@
/* /*
TODO: TODO:
1. Improve maintenance page 1. Improve maintenance page
2. Bounce handling 2. Option to copy completed email to saved email page
*/ */
/* /*
@@ -89,8 +89,6 @@ if (!getperms('W'))
$e_sub_cat = 'mail'; $e_sub_cat = 'mail';
require_once(e_ADMIN.'auth.php');
require_once(e_HANDLER.'ren_help.php'); require_once(e_HANDLER.'ren_help.php');
include_lan(e_LANGUAGEDIR.e_LANGUAGE.'/admin/lan_users.php'); include_lan(e_LANGUAGEDIR.e_LANGUAGE.'/admin/lan_users.php');
include_lan(e_LANGUAGEDIR.e_LANGUAGE.'/admin/lan_mailout.php'); include_lan(e_LANGUAGEDIR.e_LANGUAGE.'/admin/lan_mailout.php');
@@ -101,13 +99,6 @@ require_once(e_HANDLER.'mail_manager_class.php'); // Mail DB API
require_once (e_HANDLER.'message_handler.php'); require_once (e_HANDLER.'message_handler.php');
$emessage = &eMessage :: getInstance(); $emessage = &eMessage :: getInstance();
$action = $e107->tp->toDB(varset($_GET['mode'],'makemail'));
$pageMode = varset($_GET['savepage'], $action); // Sometimes we need to know what brought us here - $action gets changed
$mailId = intval(varset($_GET['m'],0));
$targetId = intval(varset($_GET['t'],0));
// Create mail admin object, load all mail handlers // Create mail admin object, load all mail handlers
$mailAdmin = new mailoutAdminClass($action); // This decodes parts of the query using $_GET syntax $mailAdmin = new mailoutAdminClass($action); // This decodes parts of the query using $_GET syntax
if ($mailAdmin->loadMailHandlers() == 0) if ($mailAdmin->loadMailHandlers() == 0)
@@ -115,6 +106,16 @@ if ($mailAdmin->loadMailHandlers() == 0)
echo 'No mail handlers loaded!!'; echo 'No mail handlers loaded!!';
exit; exit;
} }
e107::setRegistry('_mailout_admin', $mailAdmin);
require_once(e_ADMIN.'auth.php');
$action = $e107->tp->toDB(varset($_GET['mode'],'makemail'));
$pageMode = varset($_GET['savepage'], $action); // Sometimes we need to know what brought us here - $action gets changed
$mailId = intval(varset($_GET['m'],0));
$targetId = intval(varset($_GET['t'],0));
$errors = array(); $errors = array();
@@ -418,7 +419,19 @@ switch ($midAction)
} }
break; break;
case 'midMoveToSend' : case 'midMoveToSend' :
if ($mailAdmin->activateEmail($mailId, FALSE)) $notify = isset($_POST['mail_notify_complete']) ? 3 : 2;
$first = 0;
$last = 0; // Set defaults for earliest and latest send times.
// TODO: Save these fields
if (isset($_POST['mail_earliest_time']))
{
$first = e107::getDateConvert()->decodeDateTime($_POST['mail_earliest_time'], 'datetime', 'dmy', FALSE);
}
if (isset($_POST['mail_latest_time']))
{
$last = e107::getDateConvert()->decodeDateTime($_POST['mail_earliest_time'], 'datetime', 'dmy', TRUE);
}
if ($mailAdmin->activateEmail($mailId, FALSE, $notify, $first, $last))
{ {
$emessage->add(LAN_MAILOUT_185, E_MESSAGE_SUCCESS); $emessage->add(LAN_MAILOUT_185, E_MESSAGE_SUCCESS);
$admin_log->log_event('MAIL_06','ID: '.$mailId,E_LOG_INFORMATIVE,''); $admin_log->log_event('MAIL_06','ID: '.$mailId,E_LOG_INFORMATIVE,'');
@@ -561,6 +574,7 @@ function saveMailPrefs(&$emessage)
break; break;
case 'mail' : case 'mail' :
$temp['mail_bounce_email'] = $e107->tp->toDB($_POST['mail_bounce_email']); $temp['mail_bounce_email'] = $e107->tp->toDB($_POST['mail_bounce_email']);
$temp['mail_bounce_auto'] = intval($_POST['mail_bounce_auto']);
break; break;
} }
$temp['mail_bounce_pop3'] = $e107->tp->toDB($_POST['mail_bounce_pop3']); $temp['mail_bounce_pop3'] = $e107->tp->toDB($_POST['mail_bounce_pop3']);
@@ -838,7 +852,10 @@ function show_prefs($mailAdmin)
"; ";
$check = ($pref['mail_bounce_delete']==1) ? " checked='checked'" : ""; $check = ($pref['mail_bounce_delete']==1) ? " checked='checked'" : "";
$text .= "<tr><td>".LAN_MAILOUT_36."</td><td><input type='checkbox' name='mail_bounce_delete' value='1' {$check} /></td></tr> $text .= "<tr><td>".LAN_MAILOUT_36."</td><td><input type='checkbox' name='mail_bounce_delete' value='1' {$check} /></td></tr>";
$check = ($pref['mail_bounce_auto']==1) ? " checked='checked'" : "";
$text .= "<tr><td>".LAN_MAILOUT_245."</td><td><input type='checkbox' name='mail_bounce_auto' value='1' {$check} /><span class='field-help'>&nbsp;".LAN_MAILOUT_246."</span></td></tr>
</tbody> </tbody>
</table></fieldset> </table></fieldset>
@@ -975,6 +992,9 @@ function headerjs()
} }
</script>"; </script>";
$mailAdmin = e107::getRegistry('_mailout_admin');
$text .= $mailAdmin->_cal->load_files();
return $text; return $text;
} }

View File

@@ -9,9 +9,9 @@
* *
* *
* $Source: /cvs_backup/e107_0.8/e107_admin/notify.php,v $ * $Source: /cvs_backup/e107_0.8/e107_admin/notify.php,v $
* $Revision: 1.11 $ * $Revision: 1.12 $
* $Date: 2009-11-18 01:04:26 $ * $Date: 2009-11-27 21:42:46 $
* $Author: e107coders $ * $Author: e107steved $
*/ */
require_once('../class2.php'); require_once('../class2.php');
@@ -149,6 +149,18 @@ class notify_config
$text .= "</table></fieldset> $text .= "</table></fieldset>
<fieldset id='core-notify-4'> <fieldset id='core-notify-4'>
<legend>".NM_LAN_1."</legend>
<table cellpadding='0' cellspacing='0' class='adminform'>
<colgroup span='2'>
<col class='col-label' />
<col class='col-control' />
</colgroup>";
$text .= $this -> render_event('maildone', NM_LAN_2);
$text .= "</table></fieldset>
<fieldset id='core-notify-5'>
<legend>".NF_LAN_1."</legend> <legend>".NF_LAN_1."</legend>
<table cellpadding='0' cellspacing='0' class='adminform'> <table cellpadding='0' cellspacing='0' class='adminform'>
<colgroup span='2'> <colgroup span='2'>

View File

@@ -9,9 +9,9 @@
* Core SQL * Core SQL
* *
* $Source: /cvs_backup/e107_0.8/e107_admin/sql/core_sql.php,v $ * $Source: /cvs_backup/e107_0.8/e107_admin/sql/core_sql.php,v $
* $Revision: 1.42 $ * $Revision: 1.43 $
* $Date: 2009-11-26 09:02:32 $ * $Date: 2009-11-27 21:42:46 $
* $Author: e107coders $ * $Author: e107steved $
*/ */
header("location:../index.php"); header("location:../index.php");
@@ -244,8 +244,9 @@ CREATE TABLE mail_content (
mail_end_send int(10) unsigned NOT NULL default '0', mail_end_send int(10) unsigned NOT NULL default '0',
mail_create_date int(10) unsigned NOT NULL default '0', mail_create_date int(10) unsigned NOT NULL default '0',
mail_creator int(10) unsigned NOT NULL default '0', mail_creator int(10) unsigned NOT NULL default '0',
mail_create_app varchar(10) NOT NULL default '', mail_create_app varchar(20) NOT NULL default '',
mail_e107_priority tinyint(1) unsigned NOT NULL default '0', mail_e107_priority tinyint(1) unsigned NOT NULL default '0',
mail_notify_complete tinyint(1) unsigned NOT NULL default '0',
mail_last_date int(10) unsigned NOT NULL default '0', mail_last_date int(10) unsigned NOT NULL default '0',
mail_title varchar(100) NOT NULL default '', mail_title varchar(100) NOT NULL default '',
mail_subject varchar(100) NOT NULL default '', mail_subject varchar(100) NOT NULL default '',

View File

@@ -10,8 +10,8 @@
| GNU General Public License (http://gnu.org). | GNU General Public License (http://gnu.org).
| |
| $Source: /cvs_backup/e107_0.8/e107_handlers/cron_class.php,v $ | $Source: /cvs_backup/e107_0.8/e107_handlers/cron_class.php,v $
| $Revision: 1.4 $ | $Revision: 1.5 $
| $Date: 2009-11-15 17:38:04 $ | $Date: 2009-11-27 21:42:46 $
| $Author: e107steved $ | $Author: e107steved $
+----------------------------------------------------------------------------+ +----------------------------------------------------------------------------+
*/ */
@@ -56,6 +56,23 @@ class _system_cron
} }
} }
function procEmailBounce()
{
global $pref;
if (CRON_MAIL_DEBUG)
{
$e107 = e107::getInstance();
$e107->admin_log->e_log_event(10,debug_backtrace(),'DEBUG','CRON Bounce','Bounce processing started',FALSE,LOG_TO_ROLLING);
}
require_once(e_HANDLER.'pop_bounce_handler.php');
$mailBounce = new pop3BounceHandler();
$mailBounce->processBounces();
if (CRON_MAIL_DEBUG)
{
$e107->admin_log->e_log_event(10,debug_backtrace(),'DEBUG','CRON Bounce','Bounce processing completed',FALSE,LOG_TO_ROLLING);
}
}
} }
@@ -63,7 +80,7 @@ class _system_cron
/* $Id: cron_class.php,v 1.4 2009-11-15 17:38:04 e107steved Exp $ */ /* $Id: cron_class.php,v 1.5 2009-11-27 21:42:46 e107steved Exp $ */
/**####################################################################################################**\ /**####################################################################################################**\
Version: V1.01 Version: V1.01

View File

@@ -7,9 +7,9 @@
* GNU General Public License (http://gnu.org). * GNU General Public License (http://gnu.org).
* *
* $Source: /cvs_backup/e107_0.8/e107_handlers/date_handler.php,v $ * $Source: /cvs_backup/e107_0.8/e107_handlers/date_handler.php,v $
* $Revision: 1.12 $ * $Revision: 1.13 $
* $Date: 2009-11-18 01:49:18 $ * $Date: 2009-11-27 21:42:46 $
* $Author: marj_nl_fr $ * $Author: e107steved $
* *
*/ */
if (!defined('e107_INIT')) { exit; } if (!defined('e107_INIT')) { exit; }
@@ -61,6 +61,9 @@ class convert
return strftime($mask, $datestamp); return strftime($mask, $datestamp);
} }
/** /**
* Convert date string back to integer (unix timestamp) * Convert date string back to integer (unix timestamp)
* NOTE: after some tests, strptime (compat mode) is adding +1 sec. after parsing to time, investigate! * NOTE: after some tests, strptime (compat mode) is adding +1 sec. after parsing to time, investigate!
@@ -105,6 +108,150 @@ class convert
return $unxTimestamp; return $unxTimestamp;
} }
/**
* Tolerant date/time input routine - doesn't force use of specific delimiters, and can sometimes allow no delimiters at all
* The format string defines the critical day/month/year order.
* As examples, with suitable format specifiers all of the following will be interpreted into valid (and sensible) dates/times:
* 09122003 153045 -> 9-12-03 at 15:30:45 (requires dmy or mdy format specifier)
* 20031209 12:30:32 -> 9-12-03 at 12:30:32 (requires ymd specifier)
* 091203 1530 -> 9-12-09 at 15:30:00
* 9/12/3 12 -> 9-12-09 at 12:00:00
* 6-3/4 15-45:27 -> 6-3-04 at 15:45:27
*
* @param string $input - usually date/time string with numeric values for relevant fields, and almost any separator. e.g. dd-mm-yy hh:mm
* Date and time must be separated by one or more spaces. In times, minutes and seconds are optional, and default to zero
* One special value is allowed - 'now'
* @param string $decode - one of 'date', 'time', 'datetime'
* @param string $format - sets field order for dates. Valid strings are dmy, mdy, ymd. Add suffix 'z' to return UTC/GMT
* @param boolean $endDay - if TRUE, and no time entered, includes a time of 23:59:59 in the entered date
*
* @return integer time stamp. returns zero on any error
*/
public function decodeDateTime($input, $decode = 'date', $format = 'dmy', $endDay = FALSE)
{
if ($input == 'now') return time();
$useLocale = TRUE;
if (substr($format,-1,1) == 'z')
{
$useLocale = FALSE;
$format = substr($format,0,-1); // Remove local disable string
}
switch ($decode)
{
case 'date' :
$timeString = '';
$dateString = trim($input);
break;
case 'time' :
$timeString = trim($input);
$dateString = '';
break;
case 'datetime' :
$input = str_replace(' ',' ', $input);
list($dateString, $timeString) = explode(' ',$input,2);
$timeString = trim($timeString);
$dateString = trim($dateString);
break;
default :
return 0;
}
$dateVals = array (1 => 0, 2 => 0, 3 => 0); // Preset date in case
$timeVals = array (1 => 0, 2 => 0, 3 => 0); // Preset time in case
if ($dateString)
{
if (is_numeric($dateString))
{
if (strlen($dateString) == 6)
{ // Probably fixed format numeric without separators
$dateVals = array(1 => substr($dateString,0,2), 2 => substr($dateString,2,2), 3 => substr($dateString,-2));
}
elseif (strlen($dateString) == 8)
{ // Trickier - year may be first or last!
if ($format == 'ymd')
{
$dateVals = array(1 => substr($dateString,0,4), 2 => substr($dateString,4,2), 3 => substr($dateString,-2));
}
else
{
$dateVals = array(1 => substr($dateString,0,2), 2 => substr($dateString,2,2), 3 => substr($dateString,-4));
}
}
}
else
{ // Assume standard 'nn-nn-nn', 'nnnn-nn-nn' or 'nn-nn-nnnn' type format
if (!preg_match('#(\d{1,4})\D(\d{1,2})\D(\d{1,4})#', $dateString, $dateVals))
{
return 0; // Can't decode date
}
}
}
if ($timeString)
{
if (is_numeric($timeString))
{
if (strlen($timeString) == 6)
{ // Assume hhmmss
$timeVals = array(1 => substr($timeString,0,2), 2 => substr($timeString,2,2), 3 => substr($timeString,-2));
}
elseif (strlen($timeString) == 4)
{ // Assume hhmm
$timeVals = array(1 => substr($timeString,0,2), 2 => substr($timeString,-2), 3 => 0);
}
else
{ // Hope its just hours!
if ($timeString < 24)
{
$timeVals[1] = $timeString;
}
}
}
else
{
preg_match('#(\d{1,2})(?:\D(\d{1,2})){0,1}(?:\D(\d{1,2})){0,1}#', $timeString, $timeVals);
}
//print_a($timeVals);
}
elseif ($endDay)
{
$timeVals = array (1 => 23, 2 => 59, 3 => 59); // Last second of day
}
// Got all the values now - the rest is simple!
switch ($format)
{
case 'dmy' :
$month = $dateVals[2]; $day = $dateVals[1]; $year = $dateVals[3]; break;
case 'mdy' :
$month = $dateVals[1]; $day = $dateVals[2]; $year = $dateVals[3]; break;
case 'ymd' :
$month = $dateVals[2]; $day = $dateVals[3]; $year = $dateVals[1]; break;
default :
echo "Unsupported format string: {$format}<br />";
return 0;
}
if ($useLocale)
{
return mktime($timeVals[1], $timeVals[2], $timeVals[3], $month, $day, $year);
}
return gmmktime($timeVals[1], $timeVals[2], $timeVals[3], $month, $day, $year);
}
/**
* Calculate difference between two dates for display in terms of years/months/weeks....
*
* @param integer $older_date - time stamp
* @param integer|boolean $newer_date - time stamp. Defaults to current time if FALSE
* @param boolean $mode -if TRUE, return value is an array. Otherwise return value is a string
* @param boolean $show_secs
* @param string $format - controls display format. 'short' misses off year. 'long' includes everything
* @return array|string according to $mode, array or string detailing the time difference
*/
function computeLapse($older_date, $newer_date = FALSE, $mode = FALSE, $show_secs = TRUE, $format = 'long') function computeLapse($older_date, $newer_date = FALSE, $mode = FALSE, $show_secs = TRUE, $format = 'long')
{ /* { /*
$mode = TRUE :: return array $mode = TRUE :: return array
@@ -130,7 +277,7 @@ class convert
If we go over a month boundary, then we need to add days to end of start month, plus days in 'end' month If we go over a month boundary, then we need to add days to end of start month, plus days in 'end' month
If start day > end day, we cross a month boundary. Calculate last day of start date. Otherwise we can just do a simple difference. If start day > end day, we cross a month boundary. Calculate last day of start date. Otherwise we can just do a simple difference.
*/ */
$newer_date = ($newer_date == FALSE ? (time()) : $newer_date); $newer_date = ($newer_date === FALSE ? (time()) : $newer_date);
if($older_date>$newer_date) if($older_date>$newer_date)
{ // Just in case the wrong way round { // Just in case the wrong way round
$tmp=$newer_date; $tmp=$newer_date;

View File

@@ -9,8 +9,8 @@
* e107 Main * e107 Main
* *
* $Source: /cvs_backup/e107_0.8/e107_handlers/mail_manager_class.php,v $ * $Source: /cvs_backup/e107_0.8/e107_handlers/mail_manager_class.php,v $
* $Revision: 1.7 $ * $Revision: 1.8 $
* $Date: 2009-11-24 20:40:34 $ * $Date: 2009-11-27 21:42:46 $
* $Author: e107steved $ * $Author: e107steved $
*/ */
@@ -30,29 +30,32 @@ will be included in preference to the current theme style.
TODO: TODO:
- optional notify flag
- Consider whether to extract links in text-only emails - Consider whether to extract links in text-only emails
- Better check on e107 ID - add encoded value
- makeEmailBody - could use regex to modify links - makeEmailBody - could use regex to modify links
- call user API to set ban
Event Triggers generated
------------------------
mailbounce - when an email bounce is received
maildone - when the sending of a complete bulk email is complete (also does 'Notify' event)
Database tables Database tables
--------------- ---------------
mail_recipients - Details of individual recipients (targets) of an email mail_recipients - Details of individual recipients (targets) of an email
mail_target_id Unique ID for this target/email combination mail_target_id Unique ID for this target/email combination
mail_recipient_id User ID (if registered user), else zero mail_recipient_id User ID (if registered user), else zero
mail_recipient_email Email address of recipient mail_recipient_email Email address of recipient
mail_recipient_name Name of recipient mail_recipient_name Name of recipient
mail_status 0 = sent, 1 = failed, > 1 = retries to go (i.e. pending) mail_status Status of this entry - see define() statements below
mail_detail_id Email body link mail_detail_id Email body link
mail_e107_priority Our internal priority - generally high for single emails, low for bulk emails
mail_send_date Earliest date/time when email may be sent. Once mail sent, actual time/date of sending (or time of failure to send) mail_send_date Earliest date/time when email may be sent. Once mail sent, actual time/date of sending (or time of failure to send)
mail_target_info Array of target-specific info for substitution into email mail_target_info Array of target-specific info for substitution into email. Key is the code in the email body, value is the substitution
mail_content - Details of the email to be sent to a number of people mail_content - Details of the email to be sent to a number of people
mail_source_id mail_source_id
mail_content_status 0 = sent, 2 = pending, 9 = saved? mail_content_status Overall status of mailshot record - See define() statements below
mail_togo_count Number of recipients to go mail_togo_count Number of recipients to go
mail_sent_count Number of successful sends (including bounces) mail_sent_count Number of successful sends (including bounces)
mail_fail_count Number of unsuccessful sends mail_fail_count Number of unsuccessful sends
@@ -62,10 +65,12 @@ mail_content - Details of the email to be sent to a number of people
mail_create_date mail_create_date
mail_creator User ID mail_creator User ID
mail_create_app ID string for application/plugin creating mail mail_create_app ID string for application/plugin creating mail
mail_e107_priority Our internal priority - generally high for single emails, low for bulk emails
mail_notify_complete Notify options when email complete
mail_last_date Don't send after this date/time mail_last_date Don't send after this date/time
mail_title A description of the mailout - not sent mail_title A description of the mailout - not sent
mail_subject mail_subject Subject line
mail_body mail_body Body text
mail_other Evaluates to an array of misc info - cc, bcc, attachments etc mail_other Evaluates to an array of misc info - cc, bcc, attachments etc
@@ -137,6 +142,7 @@ class e107MailManager
'mail_creator' => 'int', 'mail_creator' => 'int',
'mail_create_app' => 'todb', 'mail_create_app' => 'todb',
'mail_e107_priority' => 'int', 'mail_e107_priority' => 'int',
'mail_notify_complete' => 'int',
'mail_last_date' => 'int', 'mail_last_date' => 'int',
'mail_title' => 'todb', 'mail_title' => 'todb',
'mail_subject' => 'todb', 'mail_subject' => 'todb',
@@ -168,6 +174,14 @@ class e107MailManager
'mail_include_images' => 1 // Used to determine whether to embed images, or link to them 'mail_include_images' => 1 // Used to determine whether to embed images, or link to them
); );
// List of fields which are the status counts of an email, and their titles
protected $mailCountFields = array(
'mail_togo_count' => LAN_MAILOUT_83,
'mail_sent_count' => LAN_MAILOUT_82,
'mail_fail_count' => LAN_MAILOUT_128,
'mail_bounce_count' => LAN_MAILOUT_144,
);
/** /**
* Constructor * Constructor
* *
@@ -445,6 +459,40 @@ class e107MailManager
/**
* Convert numeric represntation of mail status to a text string
*
* @param integer $status - numeric value of status
* @return string text value
*/
public function statusToText($status)
{
switch (intval($status))
{
case MAIL_STATUS_SENT :
return LAN_MAILOUT_211;
case MAIL_STATUS_BOUNCED :
return LAN_MAILOUT_213;
case MAIL_STATUS_CANCELLED :
return LAN_MAILOUT_218;
case MAIL_STATUS_PARTIAL :
return LAN_MAILOUT_219;
case MAIL_STATUS_FAILED :
return LAN_MAILOUT_212;
case MAIL_STATUS_PENDING :
return LAN_MAILOUT_214;
case MAIL_STATUS_SAVED :
return LAN_MAILOUT_215;
case MAIL_STATUS_HELD :
return LAN_MAILOUT_217;
default :
if (($status > MAIL_STATUS_PENDING) && ($status <= MAIL_STATUS_ACTIVE)) return LAN_MAILOUT_214;
}
return LAN_MAILOUT_216.' ('.$status.')'; // General coding error
}
/** /**
* Select the next $count emails in the send queue * Select the next $count emails in the send queue
* $count gives the maximum number. '*' does 'select all' * $count gives the maximum number. '*' does 'select all'
@@ -605,7 +653,7 @@ class e107MailManager
// Try and send // Try and send
$result = $this->mailer->sendEmail($email['mail_recipient_email'], $email['mail_recipient_name'], $email, TRUE); $result = $this->mailer->sendEmail($email['mail_recipient_email'], $email['mail_recipient_name'], $email, TRUE);
// return; // ************************************************************************* Temporarily stop DB being updated ***************************** // return; // ************************************************** Temporarily stop DB being updated when line active *****************************
$this->checkDB(2); // Make sure DB object created $this->checkDB(2); // Make sure DB object created
@@ -656,6 +704,38 @@ class e107MailManager
'WHERE' => '`mail_source_id` = '.intval($email['mail_source_id']))); 'WHERE' => '`mail_source_id` = '.intval($email['mail_source_id'])));
} }
if (($this->currentBatchInfo['mail_togo_count'] == 0) && ($email['mail_notify_complete'] > 0))
{ // Need to notify completion
$email = array_merge($email, $this->currentBatchInfo); // This should ensure the counters are up to date
$mailInfo = LAN_MAILOUT_247.'<br />'.LAN_MAILOUT_135.': '.$email['mail_title'].'<br />'.LAN_MAILOUT_248.$this->statusToText($email['mail_content_status']).'<br />';
$mailInfo .= '<br />'.LAN_MAILOUT_249.'<br />';
foreach ($this->mailCountFields as $f => $t)
{
$mailInfo .= $t.' => '.$email[$f].'<br />';
}
$mailInfo .= LAN_MAILOUT_250;
$message = array( // Use same structure for email and notify
'mail_subject' => LAN_MAILOUT_244.$email['mail_subject'],
'mail_body' => $mailInfo.'<br />'
);
if ($email['mail_notify_complete'] & 1)
{ // Notify email initiator
if ($this->db2->db_Select('user', 'user_name, user_email', '`user_id`='.intval($email['mail_creator'])))
{
$row = $this->db2->db_Fetch(MYSQL_ASSOC);
require_once(e_HANDLER.'mail.php');
$mailer = new e107Email();
$mailer->sendEmail($row['user_name'], $row['user_email'], $message,FALSE);
}
}
if ($email['mail_notify_complete'] & 2)
{ // Do e107 notify
notify_maildone($message);
}
e107::getEvent()->trigger('maildone', $email);
}
return $result; return $result;
} }
@@ -874,11 +954,16 @@ class e107MailManager
* Update status for email, including all recipient entries (called once all recipients added) * Update status for email, including all recipient entries (called once all recipients added)
* @var int $handle - as returned by makeEmail() * @var int $handle - as returned by makeEmail()
* @var $hold boolean - TRUE to set status to held, false to release for sending * @var $hold boolean - TRUE to set status to held, false to release for sending
* @var $notify - value to set in the mail_notify_complete field:
* 0 - no action on run complete
* 1 - notify admin who sent email only
* 2 - notify through e107 notify system only
* 3 - notify both
* @var $firstTime int - only valid if $hold === FALSE - earliest time/date when email may be sent * @var $firstTime int - only valid if $hold === FALSE - earliest time/date when email may be sent
* @var $lastTime int - only valid if $hold === FALSE - latest time/date when email may be sent * @var $lastTime int - only valid if $hold === FALSE - latest time/date when email may be sent
* @return boolean TRUE on no errors, FALSE on errors * @return boolean TRUE on no errors, FALSE on errors
*/ */
public function activateEmail($handle, $hold = FALSE, $firstTime = 0, $lastTime = 0) public function activateEmail($handle, $hold = FALSE, $notify = 0, $firstTime = 0, $lastTime = 0)
{ {
if (($handle <= 0) || !is_numeric($handle)) return FALSE; if (($handle <= 0) || !is_numeric($handle)) return FALSE;
$this->checkDB(1); // Make sure DB object created $this->checkDB(1); // Make sure DB object created
@@ -902,18 +987,20 @@ class e107MailManager
} }
$query = ''; $query = '';
if (!$hold) $query = '`mail_creator` = '.USERID.', `mail_create_date` = '.time().', '; // Update when we send - might be someone different if (!$hold) $query = '`mail_creator` = '.USERID.', `mail_create_date` = '.time().', '; // Update when we send - might be someone different
$query .= '`mail_content_status` = '.($hold ? MAIL_STATUS_HELD : MAIL_STATUS_PENDING).$lt.' WHERE `mail_source_id` = '.intval($handle); $query .= '`mail_notify_complete`='.intval($notify).', `mail_content_status` = '.($hold ? MAIL_STATUS_HELD : MAIL_STATUS_PENDING).$lt.' WHERE `mail_source_id` = '.intval($handle);
// echo "Update mail body: {$query}<br />"; // echo "Update mail body: {$query}<br />";
// Set status of email body first // Set status of email body first
if (!$this->db->db_Update('mail_content',$query)) if (!$this->db->db_Update('mail_content',$query))
{ {
$this->e107->admin_log->e_log_event(10,-1,'MAIL','Activate/hold mail','mail_content: '.$query.'[!br!]Fail: '.$this->db->mySQLlastErrText,FALSE,LOG_TO_ROLLING);
return FALSE; return FALSE;
} }
// Now set status of individual emails // Now set status of individual emails
$query = '`mail_status` = '.($hold ? MAIL_STATUS_HELD : (MAIL_STATUS_PENDING + e107MailManager::E107_EMAIL_MAX_TRIES)).$ft.' WHERE `mail_detail_id` = '.intval($handle); $query = '`mail_status` = '.($hold ? MAIL_STATUS_HELD : (MAIL_STATUS_PENDING + e107MailManager::E107_EMAIL_MAX_TRIES)).$ft.' WHERE `mail_detail_id` = '.intval($handle);
// echo "Update individual emails: {$query}<br />"; // echo "Update individual emails: {$query}<br />";
if (FALSE === $this->db->db_Update('mail_recipients',$query)) if (FALSE === $this->db->db_Update('mail_recipients',$query))
{ {
$this->e107->admin_log->e_log_event(10,-1,'MAIL','Activate/hold mail','mail_recipient: '.$query.'[!br!]Fail: '.$this->db->mySQLlastErrText,FALSE,LOG_TO_ROLLING);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
@@ -975,6 +1062,7 @@ class e107MailManager
*/ */
public function markBounce($bounceString, $emailAddress = '') public function markBounce($bounceString, $emailAddress = '')
{ {
$bounceInfo = array('mail_bounce_string' => $bounceString, 'mail_recipient_email' => $emailAddress); // Ready for event data
$errors = array(); // Log all errors, at least until proven $errors = array(); // Log all errors, at least until proven
$vals = explode('/',$bounceString); // Should get one or four fields $vals = explode('/',$bounceString); // Should get one or four fields
if (!is_numeric($vals[0])) // Email recipient user id number (may be zero) if (!is_numeric($vals[0])) // Email recipient user id number (may be zero)
@@ -1001,8 +1089,8 @@ class e107MailManager
if (count($errors) == 0) if (count($errors) == 0)
{ // Look up in mailer DB if no errors so far { // Look up in mailer DB if no errors so far
$this->checkDB(1); $this->checkDB(1);
if (FALSE === ($this->DB->db_Select_gen( if (FALSE === ($this->db->db_Select_gen(
"SELECT mr.`mail_recipient_id`, mr.`mail_recipient_email` FROM `#mail_recipients` AS mr "SELECT mr.`mail_recipient_id`, mr.`mail_recipient_email`, mr.`mail_recipient_name` FROM `#mail_recipients` AS mr
LEFT JOIN `#mail_content` as mc ON mr.`mail_detail_id` = mc.`mail_source_id` LEFT JOIN `#mail_content` as mc ON mr.`mail_detail_id` = mc.`mail_source_id`
WHERE mr.`mail_target_id` = {$vals[2]} AND mc.`mail_source_id` = {$vals[1]}"))) WHERE mr.`mail_target_id` = {$vals[2]} AND mc.`mail_source_id` = {$vals[1]}")))
{ // Invalid mailer record { // Invalid mailer record
@@ -1020,7 +1108,11 @@ class e107MailManager
if (count($errors) == 0) if (count($errors) == 0)
{ // All passed - can update mailout databases { // All passed - can update mailout databases
$this->db->db_Update('mail_content', '`mail_bounce_count` = `mail_bounce_count` + 1 WHERE `mail_source_id` = '.$vals[1]); $this->db->db_Update('mail_content', '`mail_bounce_count` = `mail_bounce_count` + 1 WHERE `mail_source_id` = '.$vals[1]);
$this->db->db_Update('mail_recipients', '`mail_status` = '.MAIL_STATUS_BOUNCED); $this->db->db_Update('mail_recipients', '`mail_status` = '.MAIL_STATUS_BOUNCED.' WHERE `mail_target_id` = '.$vals[2]);
$bounceInfo['mail_source_id'] = $vals[1];
$bounceInfo['mail_target_id'] = $vals[2];
$bounceInfo['mail_recipient_id'] = $uid;
$bounceInfo['mail_recipient_name'] = $row['mail_recipient_name'];
} }
} }
} }
@@ -1034,8 +1126,7 @@ class e107MailManager
$this->checkDB(1); $this->checkDB(1);
$qry = ''; $qry = '';
if ($uid) { $qry = '`user_id`='.$uid; } if ($uid) { $qry = '`user_id`='.$uid; }
if ($emailAddress) { if ($qry) $qry .= ' OR '; $qry .= '`user_email` = '.$emailAddress; } if ($emailAddress) { if ($qry) $qry .= ' OR '; $qry .= "`user_email` = '{$emailAddress}'"; }
$qry = 'WHERE '.$qry;
if (FALSE === $this->db->db_Select('user', 'user_id, user_email', $qry)) if (FALSE === $this->db->db_Select('user', 'user_id, user_email', $qry))
{ {
$errors[] = 'User not found: '.$uid.'/'.$emailAddress; $errors[] = 'User not found: '.$uid.'/'.$emailAddress;
@@ -1053,16 +1144,18 @@ class e107MailManager
} }
else else
{ // Valid user! { // Valid user!
$this->db->db_Update('user', '`user_ban` = 3 WHERE `user_id` = '.$row['user_id'].' LIMIT 1'); $this->db->db_Update('user', '`user_ban` = 3 WHERE `user_id` = '.$row['user_id'].' LIMIT 1'); // TODO: Call via user API
} }
} }
} }
if (count($errors)) if (count($errors))
{ {
$this->e107->admin_log->e_log_event(10,-1,'BOUNCE','Bounce receive error',$bounceString.'('.$emailAddress.')[!br!]'.implode('[!br!]',$errors),FALSE,LOG_TO_ROLLING); $logString = $bounceString.' ('.$emailAddress.')[!br!]'.implode('[!br!]',$errors);
$this->e107->admin_log->e_log_event(10,-1,'BOUNCE','Bounce receive error',$logString,FALSE,LOG_TO_ROLLING);
return FALSE; return FALSE;
} }
$this->e107->admin_log->e_log_event(10,-1,'BOUNCE','Bounce received/logged',$bounceString.'('.$emailAddress.')',FALSE,LOG_TO_ROLLING); $this->e107->admin_log->e_log_event(10,-1,'BOUNCE','Bounce received/logged',$bounceString.' ('.$emailAddress.')',FALSE,LOG_TO_ROLLING);
e107::getEvent()->trigger('mailbounce', $bounceInfo);
return TRUE; return TRUE;
} }

View File

@@ -9,8 +9,8 @@
* Administration - Site Maintenance * Administration - Site Maintenance
* *
* $Source: /cvs_backup/e107_0.8/e107_handlers/mailout_admin_class.php,v $ * $Source: /cvs_backup/e107_0.8/e107_handlers/mailout_admin_class.php,v $
* $Revision: 1.6 $ * $Revision: 1.7 $
* $Date: 2009-11-23 21:06:00 $ * $Date: 2009-11-27 21:42:46 $
* $Author: e107steved $ * $Author: e107steved $
* *
*/ */
@@ -25,7 +25,7 @@ TODO:
1. Use API to downloads plugin to get available files (when available) 1. Use API to downloads plugin to get available files (when available)
2. Fuller checking prior to send 2. Fuller checking prior to send
3. May want more control over date display format 3. May want more control over date display format
4. Add JS calendar for 'last visit' selector 4. Look at orphan removal query
*/ */
if (!defined('e107_INIT')) { exit; } if (!defined('e107_INIT')) { exit; }
@@ -36,6 +36,7 @@ require_once(e_HANDLER.'mail_manager_class.php');
class mailoutAdminClass extends e107MailManager class mailoutAdminClass extends e107MailManager
{ {
public $_cal = array();
protected $mode; // So we know what the current task is protected $mode; // So we know what the current task is
protected $mailHandlers = array(); protected $mailHandlers = array();
protected $showFrom = 0; protected $showFrom = 0;
@@ -78,6 +79,7 @@ class mailoutAdminClass extends e107MailManager
'mail_creator' => array('title' => LAN_MAILOUT_85, 'proc' => 'username'), 'mail_creator' => array('title' => LAN_MAILOUT_85, 'proc' => 'username'),
'mail_create_app' => array('title' => LAN_MAILOUT_133), 'mail_create_app' => array('title' => LAN_MAILOUT_133),
'mail_e107_priority' => array('title' => LAN_MAILOUT_134), 'mail_e107_priority' => array('title' => LAN_MAILOUT_134),
'mail_notify_complete' => array('title' => LAN_MAILOUT_243, 'nolist' => 'TRUE'),
'mail_last_date' => array('title' => LAN_MAILOUT_129, 'proc' => 'sdatetime'), 'mail_last_date' => array('title' => LAN_MAILOUT_129, 'proc' => 'sdatetime'),
'mail_body' => array('title' => LAN_MAILOUT_100, 'proc' => 'trunc200'), 'mail_body' => array('title' => LAN_MAILOUT_100, 'proc' => 'trunc200'),
// 'mail_other' = array('title' => LAN_MAILOUT_84), // 'mail_other' = array('title' => LAN_MAILOUT_84),
@@ -96,12 +98,12 @@ class mailoutAdminClass extends e107MailManager
// List of fields to be hidden for each action ('nolist' attribute true) // List of fields to be hidden for each action ('nolist' attribute true)
protected $hideFields = array( protected $hideFields = array(
'orphans' => array(), 'orphans' => array(),
'saved' => 'mail_content_status,mail_togo_count,mail_sent_count,mail_fail_count,mail_bounce_count,mail_start_send,mail_end_send,mail_e107_priority,mail_last_date,mail_selectors', 'saved' => 'mail_content_status,mail_togo_count,mail_sent_count,mail_fail_count,mail_bounce_count,mail_start_send,mail_end_send,mail_e107_priority,mail_notify_complete,mail_last_date,mail_selectors',
'sent' => 'mail_togo_count,mail_last_date,mail_selectors', 'sent' => 'mail_togo_count,mail_last_date,mail_selectors,mail_notify_complete',
// 'pending' => 'mail_togo_count,mail_sent_count,mail_fail_count,mail_bounce_count,mail_start_send,mail_end_send,mail_e107_priority,mail_last_date,mail_selectors', // 'pending' => 'mail_togo_count,mail_sent_count,mail_fail_count,mail_bounce_count,mail_start_send,mail_end_send,mail_e107_priority,mail_last_date,mail_selectors',
'pending' => 'mail_start_send,mail_end_send,mail_e107_priority,mail_last_date,mail_selectors', 'pending' => 'mail_start_send,mail_end_send,mail_e107_priority,mail_notify_complete,mail_last_date,mail_selectors',
'held' => 'mail_sent_count,mail_fail_count,mail_bounce_count,mail_start_send,mail_end_send,mail_e107_priority,mail_last_date,mail_selectors', 'held' => 'mail_sent_count,mail_fail_count,mail_bounce_count,mail_start_send,mail_end_send,mail_e107_priority,mail_notify_complete,mail_last_date,mail_selectors',
'resend' => 'mail_Selectors', 'resend' => 'mail_Selectors,mail_notify_complete',
'recipients' => 'mail_detail_id' 'recipients' => 'mail_detail_id'
); );
@@ -164,7 +166,9 @@ class mailoutAdminClass extends e107MailManager
public function __construct($mode = '') public function __construct($mode = '')
{ {
parent::__construct(); parent::__construct();
// $saveMode = $mode; require_once(e_HANDLER.'calendar/calendar_class.php');
$this->_cal = new DHTML_Calendar(true);
$dbTable = ''; $dbTable = '';
if (isset($this->tasks[$mode])) if (isset($this->tasks[$mode]))
{ {
@@ -256,6 +260,13 @@ class mailoutAdminClass extends e107MailManager
/**
* Calculate the list of fields (columns) to be displayed for a given mode
*
* @param string $mode - display mode
* @param boolean $noOptions - set TRUE to suppress inclusion of any 'options' column. FALSE to include 'options' (default)
* @return array of field definitions
*/
protected function calcFieldSpec($mode, $noOptions = FALSE) protected function calcFieldSpec($mode, $noOptions = FALSE)
{ {
if (!isset($this->tasks[$mode])) if (!isset($this->tasks[$mode]))
@@ -323,47 +334,14 @@ class mailoutAdminClass extends e107MailManager
} }
/**
* Convert numeric represntation of mail status to a text string
*
* @param integer $status - numeric value of status
* @return string text value
*/
public function statusToText($status)
{
switch (intval($status))
{
case MAIL_STATUS_SENT :
return LAN_MAILOUT_211;
case MAIL_STATUS_BOUNCED :
return LAN_MAILOUT_213;
case MAIL_STATUS_CANCELLED :
return LAN_MAILOUT_218;
case MAIL_STATUS_PARTIAL :
return LAN_MAILOUT_219;
case MAIL_STATUS_FAILED :
return LAN_MAILOUT_212;
case MAIL_STATUS_PENDING :
return LAN_MAILOUT_214;
case MAIL_STATUS_SAVED :
return LAN_MAILOUT_215;
case MAIL_STATUS_HELD :
return LAN_MAILOUT_217;
default :
if (($status > MAIL_STATUS_PENDING) && ($status <= MAIL_STATUS_ACTIVE)) return LAN_MAILOUT_214;
}
return LAN_MAILOUT_216.' ('.$status.')'; // General coding error
}
/** /**
* Generate the HTML for displaying actions box for emails * Generate the HTML for displaying actions box for emails
* *
* Options given depend on $mode, and also values in the email data. * Options given depend on $mode, and also values in the email data.
* *
* @param $mailData - array of email-related info * @param array $mailData - array of email-related info
* @return HTML for display * @return string HTML for display
*/ */
public function makeMailOptions($mode,$mailData) public function makeMailOptions($mode,$mailData)
{ {
@@ -1191,7 +1169,6 @@ class mailoutAdminClass extends e107MailManager
<col class='col-label' /> <col class='col-label' />
<col class='col-control' /> <col class='col-control' />
</colgroup> </colgroup>
<tbody>"; <tbody>";
$text .= $this->showMailDetail($mailData, 'send'); $text .= $this->showMailDetail($mailData, 'send');
@@ -1209,14 +1186,16 @@ class mailoutAdminClass extends e107MailManager
// Figures - number of emails to send, number of duplicates stripped // Figures - number of emails to send, number of duplicates stripped
$text .= '<tr><td>'.LAN_MAILOUT_173.'</td><td>'.($mailData['mail_togo_count'])."<input type='hidden' name='mailIDConf' value='{$mailID}' /></td></tr>"; $text .= '<tr><td>'.LAN_MAILOUT_173.'</td><td>'.($mailData['mail_togo_count'])."<input type='hidden' name='mailIDConf' value='{$mailID}' /></td></tr>";
$text .= '<tr><td>'.LAN_MAILOUT_71.'</td><td> '.$counters['add'].' '.LAN_MAILOUT_69.$counters['dups'].LAN_MAILOUT_70.'</td></tr>'; $text .= '<tr><td>'.LAN_MAILOUT_71.'</td><td> '.$counters['add'].' '.LAN_MAILOUT_69.$counters['dups'].LAN_MAILOUT_70.'</td></tr>';
$text .= "<tr><td colspan='2'>Add in start/end dates here</td></tr>";
$text .= "</tbody></table>\n</fieldset>"; $text .= "</tbody></table>\n</fieldset>";
$text .= $this->makeAdvancedOptions(TRUE); // Show the table of advanced options
$text .= "<div class='buttons-bar center'> $text .= "<div class='buttons-bar center'>
<input class='button' type='submit' name='email_send' value=\"".LAN_SEND."\" /> <input class='button' type='submit' name='email_send' value=\"".LAN_SEND."\" />
&nbsp;<input class='button' type='submit' name='email_hold' value=\"".LAN_HOLD."\" /> &nbsp;<input class='button' type='submit' name='email_hold' value=\"".LAN_HOLD."\" />
&nbsp;<input class='button' type='submit' name='email_cancel' value=\"".LAN_CANCEL."\" /> &nbsp;<input class='button' type='submit' name='email_cancel' value=\"".LAN_CANCEL."\" />
</div>
</form>
</div>"; </div>";
$this->e107->ns->tablerender("<div style='text-align:center'>".ADLAN_136." :: ".LAN_MAILOUT_179."</div>", $text); $this->e107->ns->tablerender("<div style='text-align:center'>".ADLAN_136." :: ".LAN_MAILOUT_179."</div>", $text);
@@ -1224,6 +1203,48 @@ class mailoutAdminClass extends e107MailManager
protected function makeAdvancedOptions($initHide = FALSE)
{
// Separate table for advanced mailout options
// mail_notify_complete field
$text = "
<legend>".LAN_MAILOUT_242."</legend>
<fieldset id='email-send-options'>
<table cellpadding='0' cellspacing='0' class='adminlist'>
<colgroup span='2'>
<col class='col-label' />
<col class='col-control' />
</colgroup>
<tbody>";
$text .= "<tr><td>".LAN_MAILOUT_238."</td><td>".$this->makeCalendar('mail_earliest_time')."</td></tr>";
$text .= "<tr><td>".LAN_MAILOUT_239."</td><td>".$this->makeCalendar('mail_latest_time')."</td></tr>";
// Can comment the two lines above, uncomment two lines below, and default time/date is shown. May or may not be preferable
// $text .= "<tr><td>".LAN_MAILOUT_238."</td><td>".$this->makeCalendar('mail_earliest_time', time())."</td></tr>";
// $text .= "<tr><td>".LAN_MAILOUT_239."</td><td>".$this->makeCalendar('mail_latest_time', time()+86400)."</td></tr>";
$text .= "<tr><td>".LAN_MAILOUT_240."</td><td><input type='checkbox' value='1' name='mail_notify_complete' />".LAN_MAILOUT_241."</td></tr>";
$text .= "</tbody></table>\n</fieldset>";
return $text;
}
public function makeCalendar($calName, $calVal = '')
{
$calOptions = array(
'showsTime' => TRUE,
'showOthers' => false,
'weekNumbers' => false,
'ifFormat' => '%d/%m/%Y %H:%I'
);
$calAttrib = array(
'class' => 'tbox',
'size' => 15, // Number of characters
'name' => $calName,
'value' => (($calVal == '') ? '' : date('d/m/Y H:I',$calVal))
);
return $this->_cal->make_input_field($calOptions, $calAttrib);
}
/** /**
@@ -1372,6 +1393,8 @@ class mailoutAdminClass extends e107MailManager
$noError = TRUE; $noError = TRUE;
$results = array(); $results = array();
$this->checkDB(2); // Make sure DB object created $this->checkDB(2); // Make sure DB object created
// First thing, delete temporary records from both tables
if (($res = $this->db2->db_Delete('mail_content', '`mail_content_status` = '.MAIL_STATUS_TEMP)) === FALSE) if (($res = $this->db2->db_Delete('mail_content', '`mail_content_status` = '.MAIL_STATUS_TEMP)) === FALSE)
{ {
$results[] = 'Error '.$this->db2->mySQLlastErrNum.':'.$this->db2->mySQLlastErrText.' deleting temporary records from mail_content'; $results[] = 'Error '.$this->db2->mySQLlastErrNum.':'.$this->db2->mySQLlastErrText.' deleting temporary records from mail_content';
@@ -1407,7 +1430,7 @@ class mailoutAdminClass extends e107MailManager
// Scan content table for anomalies, out of time records // Scan content table for anomalies, out of time records
if (($res = $this->db2->db_Select_gen("SELECT * FROM `#mail_content` if (($res = $this->db2->db_Select_gen("SELECT * FROM `#mail_content`
WHERE (`mail_content_status` >".MAIL_STATUS_FAILED.") AND (`mail_content_status` <=".MAIL_STATUS_MAX_ACTIVE.") WHERE (`mail_content_status` >".MAIL_STATUS_FAILED.") AND (`mail_content_status` <=".MAIL_STATUS_MAX_ACTIVE.")
AND ((`mail_togo_count`=0) OR (`mail_last_date` < ".time()."))")) === FALSE) AND ((`mail_togo_count`=0) OR ( (`mail_last_date` != 0) AND (`mail_last_date` < ".time().")))")) === FALSE)
{ {
$results[] = 'Error '.$this->db2->mySQLlastErrNum.':'.$this->db2->mySQLlastErrText.' checking bad status in mail_content'; $results[] = 'Error '.$this->db2->mySQLlastErrNum.':'.$this->db2->mySQLlastErrText.' checking bad status in mail_content';
$noError = FALSE; $noError = FALSE;
@@ -1424,6 +1447,10 @@ class mailoutAdminClass extends e107MailManager
{ {
$results[] = 'Error cancelling email ref: '.$row['mail_source_id']; $results[] = 'Error cancelling email ref: '.$row['mail_source_id'];
} }
else
{
$results[] = 'Email cancelled: '.$row['mail_source_id'];
}
} }
} }
if (count($items)) $results[] = str_replace(array('--COUNT--', '--RECORDS--'), array(count($items), implode(', ', $items)), LAN_MAILOUT_228); if (count($items)) $results[] = str_replace(array('--COUNT--', '--RECORDS--'), array(count($items), implode(', ', $items)), LAN_MAILOUT_228);
@@ -1486,10 +1513,10 @@ class mailoutAdminClass extends e107MailManager
switch ($row['mail_status']) switch ($row['mail_status'])
{ {
case MAIL_STATUS_SENT : // Mail sent. Email handler happy, but may have bounced (or may be yet to bounce) case MAIL_STATUS_SENT : // Mail sent. Email handler happy, but may have bounced (or may be yet to bounce)
$counters['mail_togo_count'] += $row['mr_count']; $counters['mail_sent_count'] += $row['mr_count'];
break; break;
case MAIL_STATUS_BOUNCED : case MAIL_STATUS_BOUNCED :
$counters['mail_togo_count'] += $row['mr_count']; // It was sent, so increment that counter $counters['mail_sent_count'] += $row['mr_count']; // It was sent, so increment that counter
$counters['mail_bounce_count'] += $row['mr_count']; //...but bounced, so extra status $counters['mail_bounce_count'] += $row['mr_count']; //...but bounced, so extra status
break; break;
case MAIL_STATUS_CANCELLED : // Cancelled email - treat as a failure case MAIL_STATUS_CANCELLED : // Cancelled email - treat as a failure
@@ -1506,7 +1533,7 @@ class mailoutAdminClass extends e107MailManager
} }
} }
} }
if ($changeCount) $results[] = str_replace('--COUNT--', $changeCount, LAN_MAILOUT_229); if ($changeCount) $results[] = str_replace('--COUNT--', $changeCount, LAN_MAILOUT_237);
} }
$this->e107->admin_log->log_event('MAIL_05', implode('[!br!]', $results), E_LOG_INFORMATIVE, ''); $this->e107->admin_log->log_event('MAIL_05', implode('[!br!]', $results), E_LOG_INFORMATIVE, '');

View File

@@ -9,8 +9,8 @@
* Forum plugin notify configuration * Forum plugin notify configuration
* *
* $Source: /cvs_backup/e107_0.8/e107_handlers/notify_class.php,v $ * $Source: /cvs_backup/e107_0.8/e107_handlers/notify_class.php,v $
* $Revision: 1.9 $ * $Revision: 1.10 $
* $Date: 2009-11-19 20:24:21 $ * $Date: 2009-11-27 21:42:46 $
* $Author: e107steved $ * $Author: e107steved $
* *
*/ */
@@ -112,6 +112,7 @@ class notify
'mail_sender_email' => $pref['siteadminemail'], 'mail_sender_email' => $pref['siteadminemail'],
'mail_sender_name' => $pref['siteadmin'], 'mail_sender_name' => $pref['siteadmin'],
'mail_send_style' => 'textonly', 'mail_send_style' => 'textonly',
'mail_notify_complete' => 0, // NEVER notify when this email sent!!!!!
'mail_body' => $message 'mail_body' => $message
); );
$result = $mailer->saveEmail($mailData, TRUE); $result = $mailer->saveEmail($mailData, TRUE);
@@ -255,6 +256,13 @@ function notify_newsdel($data)
} }
function notify_maildone($data)
{
$message = '<b>'.$data['mail_subject'].'</b><br /><br />'.$data['mail_body'];
e107::getNotify()->send('maildone', NT_LAN_ML_1.': '.$data['mail_subject'], $message);
}
function notify_fileupload($data) function notify_fileupload($data)
{ {
global $nt; global $nt;
@@ -262,6 +270,7 @@ function notify_fileupload($data)
$nt->send('fileupload', $data['upload_name'], $message); $nt->send('fileupload', $data['upload_name'], $message);
} }
if (isset($nt->notify_prefs['plugins'])) if (isset($nt->notify_prefs['plugins']))
{ {
foreach ($nt->notify_prefs['plugins'] as $plugin_id => $plugin_settings) foreach ($nt->notify_prefs['plugins'] as $plugin_id => $plugin_settings)

View File

@@ -1,9 +1,9 @@
<?php <?php
if (!defined('e107_INIT')) { exit; } if (!defined('e107_INIT')) { exit; }
// $Id: pop3_class.php,v 1.2 2008-01-02 20:14:05 e107steved Exp $ // $Id: pop3_class.php,v 1.3 2009-11-27 21:42:46 e107steved Exp $
// Main ReciveMail Class File - Version 1.0 (01-03-2006) // Main ReceiveMail Class File - Version 1.0 (01-03-2006)
/* /*
* File: recivemail.class.php * Original file name: recivemail.class.php
* Description: Receiving mail With Attachment * Description: Receiving mail With Attachment
* Version: 1.0 * Version: 1.0
* Created: 01-03-2006 * Created: 01-03-2006
@@ -47,6 +47,7 @@ class receiveMail
$this->marubox=imap_open($this->server,$this->username,$this->password); $this->marubox=imap_open($this->server,$this->username,$this->password);
} }
function getHeaders($mid) // Get Header info function getHeaders($mid) // Get Header info
{ {
$mail_header=imap_header($this->marubox,$mid); $mail_header=imap_header($this->marubox,$mid);
@@ -69,6 +70,8 @@ class receiveMail
return $mail_details; return $mail_details;
} }
function get_mime_type(&$structure) //Get Mime type Internal Private Use function get_mime_type(&$structure) //Get Mime type Internal Private Use
{ {
$primary_mime_type = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER"); $primary_mime_type = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");
@@ -78,6 +81,8 @@ class receiveMail
} }
return "TEXT/PLAIN"; return "TEXT/PLAIN";
} }
function get_part($stream, $msg_number, $mime_type, $structure = false, $part_number = false) //Get Part Of Message Internal Private Use function get_part($stream, $msg_number, $mime_type, $structure = false, $part_number = false) //Get Part Of Message Internal Private Use
{ {
if(!$structure) { if(!$structure) {
@@ -122,11 +127,15 @@ class receiveMail
} }
return false; return false;
} }
function getTotalMails() //Get Total Number off Unread Email In Mailbox function getTotalMails() //Get Total Number off Unread Email In Mailbox
{ {
$headers=imap_headers($this->marubox); $headers=imap_headers($this->marubox);
return count($headers); return count($headers);
} }
function GetAttach($mid,$path) // Get Atteced File from Mail function GetAttach($mid,$path) // Get Atteced File from Mail
{ {
$struckture = imap_fetchstructure($this->marubox,$mid); $struckture = imap_fetchstructure($this->marubox,$mid);
@@ -159,6 +168,8 @@ class receiveMail
$ar=substr($ar,0,(strlen($ar)-1)); $ar=substr($ar,0,(strlen($ar)-1));
return $ar; return $ar;
} }
function getBody($mid,$mode="") // Get Message Body function getBody($mid,$mode="") // Get Message Body
{ {
if($mode != "plain") if($mode != "plain")
@@ -172,10 +183,14 @@ class receiveMail
} }
return $body; return $body;
} }
function deleteMails($mid) // Delete That Mail function deleteMails($mid) // Delete That Mail
{ {
imap_delete($this->marubox,$mid); imap_delete($this->marubox,$mid);
} }
function close_mailbox() //Close Mail Box function close_mailbox() //Close Mail Box
{ {
imap_close($this->marubox,CL_EXPUNGE); imap_close($this->marubox,CL_EXPUNGE);

View File

@@ -0,0 +1,263 @@
<?php
/*
* e107 website system
*
* Copyright (C) 2008-2009 e107 Inc (e107.org)
* Released under the terms and conditions of the
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
*
* Bounce handler for cron or manual triggering
*
* $Source: /cvs_backup/e107_0.8/e107_handlers/pop_bounce_handler.php,v $
* $Revision: 1.1 $
* $Date: 2009-11-27 21:42:46 $
* $Author: e107steved $
*/
/*
This handler is intended for use with a cron job, or with manual triggering, to get bounce notifications from a POP3 or IMAP account.
It extends the receiveMail class (pop3_class.php) to provide some higher level methods.
Can be used for getting mail from any POP3 mail account.
Some parts used from/based on the receiveMail class, by Mitul Koradia (Email: mitulkoradia@gmail.com, Cell : +91 9879697592)
Notes:
1. Requires that the IMAP extension is installed
2. Mailbox names that contain international characters besides those in the printable ASCII space have to be encoded width imap_utf7_encode().
*/
class pop3BounceHandler
{
protected $e107;
protected $server=''; // String to connect to server
protected $username='';
protected $password='';
protected $email=''; // Email address receiving bounces
protected $delBounce = FALSE; // TRUE to delete emails after reading
protected $mailResource = ''; // Resource identifier for IMAP
protected $mailManager = FALSE;
public function __construct($override = FALSE)
{
global $pref;
$this->e107 = e107::getInstance();
if (($override === FALSE) || !is_array($override))
{ // Set up from prefs
$override['mail_bounce_user'] = $pref['mail_bounce_user'];
$override['mail_bounce_pass'] = $pref['mail_bounce_pass'];
$override['mail_bounce_email'] = $pref['mail_bounce_email'];
$override['mail_bounce_pop3'] = $pref['mail_bounce_pop3'];
$override['mail_bounce_type'] = varset($pref['mail_bounce_type'],'pop3');
}
if($override['mail_bounce_type']=='imap')
{
$port = varset($override['mail_bounce_port'], '143');
$strConnect='{'.$override['mail_bounce_pop3'].':'.$port. '}INBOX';
}
else
{
$port = varset($override['mail_bounce_port'], '110'); // POP3 port
$servertype = '/'.varset($override['mail_bounce_type'], 'pop3');
$strConnect='{'.$override['mail_bounce_pop3'].':'.$port. $servertype.'}INBOX';
}
$this->server = $strConnect;
$this->username = $override['mail_bounce_user'];
$this->password = $override['mail_bounce_pass'];
$this->email = $override['mail_bounce_email'];
$this->delBounce = ($pref['mail_bounce_delete']) ? true : false;
}
function connect() //Connect To the Mail Box
{
$this->mailResource=imap_open($this->server,$this->username,$this->password);
}
function getTotalMails() //Get Total Number off Unread Email In Mailbox
{
$headers=imap_headers($this->mailResource);
return count($headers);
}
function getHeaders($mid) // Get Header info
{
$mail_header=imap_header($this->mailResource,$mid);
$sender=$mail_header->from[0];
$sender_replyto=$mail_header->reply_to[0];
$stat = (strtolower($sender->mailbox)!='mailer-daemon' && strtolower($sender->mailbox)!='postmaster') ? FALSE : TRUE;
if(strpos($mail_header->subject,"delayed"))
{
$stat = FALSE;
}
$mail_details=array(
'from'=>strtolower($sender->mailbox).'@'.$sender->host,
'fromName'=>$sender->personal,
'toOth'=>strtolower($sender_replyto->mailbox).'@'.$sender_replyto->host,
'toNameOth'=>$sender_replyto->personal,
'subject'=>$mail_header->subject,
'to'=>strtolower($mail_header->toaddress),
'bounce'=>$stat,
'date'=>$mail_header->date
);
return $mail_details;
}
protected function get_mime_type(&$structure) //Get Mime type Internal Private Use
{
$primary_mime_type = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");
if($structure->subtype)
{
return $primary_mime_type[(int) $structure->type] . '/' . $structure->subtype;
}
return "TEXT/PLAIN";
}
protected function get_part($stream, $msg_number, $mime_type, $structure = false, $part_number = false) //Get Part Of Message Internal Private Use
{
if(!$structure)
{
$structure = imap_fetchstructure($stream, $msg_number);
}
if($structure)
{
if($mime_type == $this->get_mime_type($structure))
{
if(!$part_number)
{
$part_number = '1';
}
$text = imap_fetchbody($stream, $msg_number, $part_number);
if($structure->encoding == 3)
{
return imap_base64($text);
}
else if($structure->encoding == 4)
{
return imap_qprint($text);
}
else
{
return $text;
}
}
if($structure->type == 1) /* multipart */
{
while(list($index, $sub_structure) = each($structure->parts))
{
if($part_number)
{
$prefix = $part_number . '.';
}
$data = $this->get_part($stream, $msg_number, $mime_type, $sub_structure, $prefix . ($index + 1));
if($data)
{
return $data;
}
}
}
}
return false;
}
function getBody($mid,$mode='') // Get Message Body
{
if($mode != 'plain')
{
$body = $this->get_part($this->mailResource, $mid, 'TEXT/HTML');
}
if (($body == '') || $mode == 'plain')
{
$body = $this->get_part($this->mailResource, $mid, 'TEXT/PLAIN');
}
if ($body == '')
{
return '';
}
return $body;
}
function deleteMails($mid) // Delete That Mail
{
imap_delete($this->mailResource,$mid);
}
function close_mailbox() //Close Mail Box
{
imap_close($this->mailResource,CL_EXPUNGE);
}
/**
* Loop reading all emails from the bounces mailbox. If an email address and/or e107 header are
* identified, process the bounce.
* Delete all emails after processing, if $pref flag is set.
*
* @return void
*/
public function processBounces()
{
$this->connect();
$tot = $this->getTotalMails(); // Get all the emails
for ($i = 1; $i <= $tot; $i++)
{
$head = $this->getHeaders($i); // Get the headers
if ($head['bounce'])
{
//print_a($head);
$body = $this->getBody($i);
$e107Header = '';
if (preg_match('#.*X-e107-id:(.*?)[\n\r]#',$body, $result))
{
$e107Header = varset($result[1],'');
}
$emailAddress = '';
if (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$body,$result))
{
$emailAddress = varset($result[0],'');
if ($emailAddress == $this->email)
{
$emailAddress = ''; // Email address found is that of the bounce email account
}
}
// Call the bounce handler here
if ($this->mailManager === FALSE)
{
require_once(e_HANDLER.'mail_manager_class.php');
$this->mailManager = new e107MailManager();
}
echo "Email: {$emailAddress}<br />Header: {$e107Header}<br />";
$this->mailManager->markBounce($e107Header, $emailAddress);
}
// Now delete the email, if option set (do it regardless of whether a bounce email)
if ($this->delBounce)
{
$this->deleteMails($i); // Not actually deleted until we close the mailbox
}
}
$this->close_mailbox();
}
}
?>

View File

@@ -9,8 +9,8 @@
* Administration - Site Maintenance * Administration - Site Maintenance
* *
* $Source: /cvs_backup/e107_0.8/e107_languages/English/admin/lan_mailout.php,v $ * $Source: /cvs_backup/e107_0.8/e107_languages/English/admin/lan_mailout.php,v $
* $Revision: 1.12 $ * $Revision: 1.13 $
* $Date: 2009-11-24 20:40:35 $ * $Date: 2009-11-27 21:42:46 $
* $Author: e107steved $ * $Author: e107steved $
* *
*/ */
@@ -244,7 +244,7 @@ define('LAN_MAILOUT_222', 'Default email format');
define('LAN_MAILOUT_223', '(Used for some non-bulk emails)'); define('LAN_MAILOUT_223', '(Used for some non-bulk emails)');
define('LAN_MAILOUT_224', 'Inc. Images'); define('LAN_MAILOUT_224', 'Inc. Images');
define('LAN_MAILOUT_225', 'Include images in email'); define('LAN_MAILOUT_225', 'Include images in email');
define('LAN_MAILOUT_226', '--COUNT-- orphaned recipient records removed'); define('LAN_MAILOUT_226', '--COUNT-- orphaned recipient record(s) removed');
define('LAN_MAILOUT_227', 'Deleted --COUNT-- records from --TABLE--'); define('LAN_MAILOUT_227', 'Deleted --COUNT-- records from --TABLE--');
define('LAN_MAILOUT_228', '--COUNT-- anomalies in mail_content corrected; records: --RECORDS--'); define('LAN_MAILOUT_228', '--COUNT-- anomalies in mail_content corrected; records: --RECORDS--');
define('LAN_MAILOUT_229', 'Email ID --ID-- put on hold'); define('LAN_MAILOUT_229', 'Email ID --ID-- put on hold');
@@ -255,10 +255,24 @@ define('LAN_MAILOUT_233', 'Auto-process script');
define('LAN_MAILOUT_234', 'Mail account'); define('LAN_MAILOUT_234', 'Mail account');
define('LAN_MAILOUT_235', '(Your server has to be configured to use this script)'); define('LAN_MAILOUT_235', '(Your server has to be configured to use this script)');
define('LAN_MAILOUT_236', 'Last Bounce Processed'); define('LAN_MAILOUT_236', 'Last Bounce Processed');
define('LAN_MAILOUT_237', ''); define('LAN_MAILOUT_237', 'Summary counters updated on --COUNT-- emails');
define('LAN_MAILOUT_238', ''); define('LAN_MAILOUT_238', 'Earliest time to send');
define('LAN_MAILOUT_239', ''); define('LAN_MAILOUT_239', 'Latest time to send');
define('LAN_MAILOUT_240', ''); define('LAN_MAILOUT_240', 'Notify me when run complete');
define('LAN_MAILOUT_241', ' (This is in addition to the standard e107 notify options)');
define('LAN_MAILOUT_242', 'Additional options (only when sending)');
define('LAN_MAILOUT_243', 'Notify');
define('LAN_MAILOUT_244', 'Email sent: ');
define('LAN_MAILOUT_245', 'Check for bounces automatically');
define('LAN_MAILOUT_246', 'If checked, you will need to activate the task in the scheduler');
define('LAN_MAILOUT_247', 'Email information:');
define('LAN_MAILOUT_248', 'Completion status: ');
define('LAN_MAILOUT_249', 'Send results:');
define('LAN_MAILOUT_250', '--- End of notification ---');
define('LAN_MAILOUT_251', '');
define('LAN_MAILOUT_252', '');
define('LAN_MAILOUT_253', '');
define('LAN_MAILOUT_254', '');
define('LAN_SEND', 'Send'); define('LAN_SEND', 'Send');

View File

@@ -4,9 +4,9 @@
| e107 website system - Language File. | e107 website system - Language File.
| |
| $Source: /cvs_backup/e107_0.8/e107_languages/English/admin/lan_notify.php,v $ | $Source: /cvs_backup/e107_0.8/e107_languages/English/admin/lan_notify.php,v $
| $Revision: 1.1.1.1 $ | $Revision: 1.2 $
| $Date: 2006-12-02 04:34:41 $ | $Date: 2009-11-27 21:42:46 $
| $Author: mcfly_e107 $ | $Author: e107steved $
+----------------------------------------------------------------------------+ +----------------------------------------------------------------------------+
*/ */
@@ -32,6 +32,9 @@ define("NN_LAN_3", "News item posted by admin");
define("NN_LAN_4", "News item edited by admin"); define("NN_LAN_4", "News item edited by admin");
define("NN_LAN_5", "News item deleted by admin"); define("NN_LAN_5", "News item deleted by admin");
define('NM_LAN_1', 'Mail Events');
define('NM_LAN_2', 'Bulk email run complete');
define("NF_LAN_1", "File Events"); define("NF_LAN_1", "File Events");
define("NF_LAN_2", "File uploaded by user"); define("NF_LAN_2", "File uploaded by user");

View File

@@ -4,9 +4,9 @@
| e107 website system - Language File. | e107 website system - Language File.
| |
| $Source: /cvs_backup/e107_0.8/e107_languages/English/lan_notify.php,v $ | $Source: /cvs_backup/e107_0.8/e107_languages/English/lan_notify.php,v $
| $Revision: 1.1.1.1 $ | $Revision: 1.2 $
| $Date: 2006-12-02 04:34:39 $ | $Date: 2009-11-27 21:42:46 $
| $Author: mcfly_e107 $ | $Author: e107steved $
+----------------------------------------------------------------------------+ +----------------------------------------------------------------------------+
*/ */
@@ -28,6 +28,8 @@ define("NT_LAN_FL_2", "IP address banned for flooding");
define("NT_LAN_SN_1", "News Item Submitted"); define("NT_LAN_SN_1", "News Item Submitted");
define('NT_LAN_ML_1', 'Bulk email send complete');
define("NT_LAN_NU_1", "Updated"); define("NT_LAN_NU_1", "Updated");
define("NT_LAN_ND_1", "News Item Deleted"); define("NT_LAN_ND_1", "News Item Deleted");