diff --git a/e107_admin/cron.php b/e107_admin/cron.php index 41ba77806..4b69cef94 100644 --- a/e107_admin/cron.php +++ b/e107_admin/cron.php @@ -11,9 +11,9 @@ | GNU General Public License (http://gnu.org/). | | $Source: /cvs_backup/e107_0.8/e107_admin/cron.php,v $ -| $Revision: 1.23 $ -| $Date: 2009-11-22 14:10:05 $ -| $Author: e107coders $ +| $Revision: 1.24 $ +| $Date: 2009-11-27 21:42:46 $ +| $Author: e107steved $ +----------------------------------------------------------------------------+ */ @@ -49,9 +49,11 @@ class cron $mes = $mes = e107::getMessage(); $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( 0 => array('name' => 'Test Email', 'function' => 'sendEmail', 'description' => 'Send a test email to '.$pref['siteadminemail'].'
Recommended to test the scheduling system.'), 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'), // 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') @@ -314,7 +316,7 @@ function setCronPwd() { global $pref; - $core_cron = $this->coreCrons; + $core_cron = $this->coreCrons; // May need to check 'available' flag here $new_cron = e107::getAddonConfig('e_cron'); $this->e_cron = array_merge($core_cron,$new_cron); return; @@ -370,143 +372,146 @@ function setCronPwd() { foreach($cfg as $class=>$cron) { - $c = $plug.'__'. $cron['function']; // class and function. - $sep = array(); - - list($sep['minute'],$sep['hour'],$sep['day'],$sep['month'],$sep['weekday']) = explode(" ",$cronpref[$c]['tab']); - - foreach($sep as $key=>$value) + if (!isset($cron['available']) || $cron['available']) // Only display cron functions which are available { - if($value=="") + $c = $plug.'__'. $cron['function']; // class and function. + $sep = array(); + + list($sep['minute'],$sep['hour'],$sep['day'],$sep['month'],$sep['weekday']) = explode(" ",$cronpref[$c]['tab']); + + foreach($sep as $key=>$value) { - $sep[$key] = "*"; + if($value=="") + { + $sep[$key] = "*"; + } } + + $minute = explode(",",$sep['minute']); + $hour = explode(",",$sep['hour']); + $day = explode(",",$sep['day']); + $month = explode(",",$sep['month']); + $weekday = explode(",",$sep['weekday']); + + $min_options = array( + "*" => LAN_CRON_11, + "0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58" => LAN_CRON_12, + "0,5,10,15,20,25,30,35,40,45,50,55" => LAN_CRON_13, + "0,10,20,30,40,50" => LAN_CRON_14, + "0,15,30,45" => LAN_CRON_15 + ); + + $hour_options = array( + "*" => LAN_CRON_16, + "0,2,4,6,8,10,12,14,16,18,20,22" => LAN_CRON_17, + "0,3,6,9,12,15,18,21" => LAN_CRON_18, + "0,6,12,18" => LAN_CRON_19 + ); + + $text .= " + ".$cron['name']." + ".$cron['description']." + + + + + + + + + + + + + + + + + "; + $checked = ($cronpref[$c]['active'] == 1) ? "checked='checked'" : ""; + $text .= " + + + ".$frm->admin_button('execute['.$c.']', 'Run Now')." + "; } - - $minute = explode(",",$sep['minute']); - $hour = explode(",",$sep['hour']); - $day = explode(",",$sep['day']); - $month = explode(",",$sep['month']); - $weekday = explode(",",$sep['weekday']); - - $min_options = array( - "*" => LAN_CRON_11, - "0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58" => LAN_CRON_12, - "0,5,10,15,20,25,30,35,40,45,50,55" => LAN_CRON_13, - "0,10,20,30,40,50" => LAN_CRON_14, - "0,15,30,45" => LAN_CRON_15 - ); - - $hour_options = array( - "*" => LAN_CRON_16, - "0,2,4,6,8,10,12,14,16,18,20,22" => LAN_CRON_17, - "0,3,6,9,12,15,18,21" => LAN_CRON_18, - "0,6,12,18" => LAN_CRON_19 - ); - - $text .= " - ".$cron['name']." - ".$cron['description']." - - - - - - - - - - - - - - - - - "; - $checked = ($cronpref[$c]['active'] == 1) ? "checked='checked'" : ""; - $text .= " - - - ".$frm->admin_button('execute['.$c.']', 'Run Now')." - "; } } $text .= " diff --git a/e107_admin/mailout.php b/e107_admin/mailout.php index 5687fe688..860204590 100644 --- a/e107_admin/mailout.php +++ b/e107_admin/mailout.php @@ -9,8 +9,8 @@ * Administration - Site Maintenance * * $Source: /cvs_backup/e107_0.8/e107_admin/mailout.php,v $ - * $Revision: 1.29 $ - * $Date: 2009-11-24 20:40:34 $ + * $Revision: 1.30 $ + * $Date: 2009-11-27 21:42:46 $ * $Author: e107steved $ * */ @@ -18,7 +18,7 @@ /* TODO: 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'; - -require_once(e_ADMIN.'auth.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_mailout.php'); @@ -101,13 +99,6 @@ require_once(e_HANDLER.'mail_manager_class.php'); // Mail DB API require_once (e_HANDLER.'message_handler.php'); $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 $mailAdmin = new mailoutAdminClass($action); // This decodes parts of the query using $_GET syntax if ($mailAdmin->loadMailHandlers() == 0) @@ -115,6 +106,16 @@ if ($mailAdmin->loadMailHandlers() == 0) echo 'No mail handlers loaded!!'; 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(); @@ -418,7 +419,19 @@ switch ($midAction) } break; 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); $admin_log->log_event('MAIL_06','ID: '.$mailId,E_LOG_INFORMATIVE,''); @@ -561,6 +574,7 @@ function saveMailPrefs(&$emessage) break; case 'mail' : $temp['mail_bounce_email'] = $e107->tp->toDB($_POST['mail_bounce_email']); + $temp['mail_bounce_auto'] = intval($_POST['mail_bounce_auto']); break; } $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'" : ""; - $text .= "".LAN_MAILOUT_36." + $text .= "".LAN_MAILOUT_36.""; + + $check = ($pref['mail_bounce_auto']==1) ? " checked='checked'" : ""; + $text .= "".LAN_MAILOUT_245." ".LAN_MAILOUT_246." @@ -975,6 +992,9 @@ function headerjs() } "; + $mailAdmin = e107::getRegistry('_mailout_admin'); + $text .= $mailAdmin->_cal->load_files(); + return $text; } diff --git a/e107_admin/notify.php b/e107_admin/notify.php index 53bf8f1e3..df9a020b3 100644 --- a/e107_admin/notify.php +++ b/e107_admin/notify.php @@ -9,9 +9,9 @@ * * * $Source: /cvs_backup/e107_0.8/e107_admin/notify.php,v $ - * $Revision: 1.11 $ - * $Date: 2009-11-18 01:04:26 $ - * $Author: e107coders $ + * $Revision: 1.12 $ + * $Date: 2009-11-27 21:42:46 $ + * $Author: e107steved $ */ require_once('../class2.php'); @@ -149,6 +149,18 @@ class notify_config $text .= "
+ ".NM_LAN_1." + + + + + "; + + $text .= $this -> render_event('maildone', NM_LAN_2); + + + $text .= "
+
".NF_LAN_1." diff --git a/e107_admin/sql/core_sql.php b/e107_admin/sql/core_sql.php index 9bdc1e8a3..edad08daf 100644 --- a/e107_admin/sql/core_sql.php +++ b/e107_admin/sql/core_sql.php @@ -9,9 +9,9 @@ * Core SQL * * $Source: /cvs_backup/e107_0.8/e107_admin/sql/core_sql.php,v $ - * $Revision: 1.42 $ - * $Date: 2009-11-26 09:02:32 $ - * $Author: e107coders $ + * $Revision: 1.43 $ + * $Date: 2009-11-27 21:42:46 $ + * $Author: e107steved $ */ header("location:../index.php"); @@ -244,8 +244,9 @@ CREATE TABLE mail_content ( mail_end_send 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_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_notify_complete tinyint(1) unsigned NOT NULL default '0', mail_last_date int(10) unsigned NOT NULL default '0', mail_title varchar(100) NOT NULL default '', mail_subject varchar(100) NOT NULL default '', diff --git a/e107_handlers/cron_class.php b/e107_handlers/cron_class.php index bd1b1fef2..1dfba8810 100644 --- a/e107_handlers/cron_class.php +++ b/e107_handlers/cron_class.php @@ -10,8 +10,8 @@ | GNU General Public License (http://gnu.org). | | $Source: /cvs_backup/e107_0.8/e107_handlers/cron_class.php,v $ -| $Revision: 1.4 $ -| $Date: 2009-11-15 17:38:04 $ +| $Revision: 1.5 $ +| $Date: 2009-11-27 21:42:46 $ | $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 diff --git a/e107_handlers/date_handler.php b/e107_handlers/date_handler.php index 752740171..5489feeeb 100644 --- a/e107_handlers/date_handler.php +++ b/e107_handlers/date_handler.php @@ -7,9 +7,9 @@ * GNU General Public License (http://gnu.org). * * $Source: /cvs_backup/e107_0.8/e107_handlers/date_handler.php,v $ - * $Revision: 1.12 $ - * $Date: 2009-11-18 01:49:18 $ - * $Author: marj_nl_fr $ + * $Revision: 1.13 $ + * $Date: 2009-11-27 21:42:46 $ + * $Author: e107steved $ * */ if (!defined('e107_INIT')) { exit; } @@ -60,6 +60,9 @@ class convert $datestamp += TIMEOFFSET; return strftime($mask, $datestamp); } + + + /** * Convert date string back to integer (unix timestamp) @@ -105,6 +108,150 @@ class convert 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}
"; + 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') { /* $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 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) { // Just in case the wrong way round $tmp=$newer_date; diff --git a/e107_handlers/mail_manager_class.php b/e107_handlers/mail_manager_class.php index 4a63a34ce..f5db8e2fd 100644 --- a/e107_handlers/mail_manager_class.php +++ b/e107_handlers/mail_manager_class.php @@ -9,8 +9,8 @@ * e107 Main * * $Source: /cvs_backup/e107_0.8/e107_handlers/mail_manager_class.php,v $ - * $Revision: 1.7 $ - * $Date: 2009-11-24 20:40:34 $ + * $Revision: 1.8 $ + * $Date: 2009-11-27 21:42:46 $ * $Author: e107steved $ */ @@ -30,29 +30,32 @@ will be included in preference to the current theme style. TODO: - - optional notify flag - Consider whether to extract links in text-only emails - - Better check on e107 ID - add encoded value - 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 --------------- - mail_recipients - Details of individual recipients (targets) of an email mail_target_id Unique ID for this target/email combination mail_recipient_id User ID (if registered user), else zero mail_recipient_email Email address 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_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_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_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_sent_count Number of successful sends (including bounces) 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_creator User ID 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_title A description of the mailout - not sent - mail_subject - mail_body + mail_subject Subject line + mail_body Body text mail_other Evaluates to an array of misc info - cc, bcc, attachments etc @@ -137,6 +142,7 @@ class e107MailManager 'mail_creator' => 'int', 'mail_create_app' => 'todb', 'mail_e107_priority' => 'int', + 'mail_notify_complete' => 'int', 'mail_last_date' => 'int', 'mail_title' => 'todb', 'mail_subject' => 'todb', @@ -167,6 +173,14 @@ class e107MailManager 'mail_selectors' => 1, // Only used internally '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 @@ -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 * $count gives the maximum number. '*' does 'select all' @@ -605,7 +653,7 @@ class e107MailManager // Try and send $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 @@ -656,6 +704,38 @@ class e107MailManager '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.'
'.LAN_MAILOUT_135.': '.$email['mail_title'].'
'.LAN_MAILOUT_248.$this->statusToText($email['mail_content_status']).'
'; + $mailInfo .= '
'.LAN_MAILOUT_249.'
'; + foreach ($this->mailCountFields as $f => $t) + { + $mailInfo .= $t.' => '.$email[$f].'
'; + } + $mailInfo .= LAN_MAILOUT_250; + $message = array( // Use same structure for email and notify + 'mail_subject' => LAN_MAILOUT_244.$email['mail_subject'], + 'mail_body' => $mailInfo.'
' + ); + + 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; } @@ -874,11 +954,16 @@ class e107MailManager * Update status for email, including all recipient entries (called once all recipients added) * @var int $handle - as returned by makeEmail() * @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 $lastTime int - only valid if $hold === FALSE - latest time/date when email may be sent * @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; $this->checkDB(1); // Make sure DB object created @@ -902,18 +987,20 @@ class e107MailManager } $query = ''; 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); -// echo "Update mail body: {$query}
"; + $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}
"; // Set status of email body first 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; } // 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); -// echo "Update individual emails: {$query}
"; + // echo "Update individual emails: {$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 TRUE; @@ -975,6 +1062,7 @@ class e107MailManager */ 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 $vals = explode('/',$bounceString); // Should get one or four fields if (!is_numeric($vals[0])) // Email recipient user id number (may be zero) @@ -1001,8 +1089,8 @@ class e107MailManager if (count($errors) == 0) { // Look up in mailer DB if no errors so far $this->checkDB(1); - if (FALSE === ($this->DB->db_Select_gen( - "SELECT mr.`mail_recipient_id`, mr.`mail_recipient_email` FROM `#mail_recipients` AS mr + if (FALSE === ($this->db->db_Select_gen( + "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` WHERE mr.`mail_target_id` = {$vals[2]} AND mc.`mail_source_id` = {$vals[1]}"))) { // Invalid mailer record @@ -1020,7 +1108,11 @@ class e107MailManager if (count($errors) == 0) { // 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_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); $qry = ''; if ($uid) { $qry = '`user_id`='.$uid; } - if ($emailAddress) { if ($qry) $qry .= ' OR '; $qry .= '`user_email` = '.$emailAddress; } - $qry = 'WHERE '.$qry; + if ($emailAddress) { if ($qry) $qry .= ' OR '; $qry .= "`user_email` = '{$emailAddress}'"; } if (FALSE === $this->db->db_Select('user', 'user_id, user_email', $qry)) { $errors[] = 'User not found: '.$uid.'/'.$emailAddress; @@ -1053,16 +1144,18 @@ class e107MailManager } else { // 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)) { - $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; } - $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; } diff --git a/e107_handlers/mailout_admin_class.php b/e107_handlers/mailout_admin_class.php index 005458c64..e1f81a419 100644 --- a/e107_handlers/mailout_admin_class.php +++ b/e107_handlers/mailout_admin_class.php @@ -9,8 +9,8 @@ * Administration - Site Maintenance * * $Source: /cvs_backup/e107_0.8/e107_handlers/mailout_admin_class.php,v $ - * $Revision: 1.6 $ - * $Date: 2009-11-23 21:06:00 $ + * $Revision: 1.7 $ + * $Date: 2009-11-27 21:42:46 $ * $Author: e107steved $ * */ @@ -25,7 +25,7 @@ TODO: 1. Use API to downloads plugin to get available files (when available) 2. Fuller checking prior to send 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; } @@ -36,6 +36,7 @@ require_once(e_HANDLER.'mail_manager_class.php'); class mailoutAdminClass extends e107MailManager { + public $_cal = array(); protected $mode; // So we know what the current task is protected $mailHandlers = array(); protected $showFrom = 0; @@ -78,6 +79,7 @@ class mailoutAdminClass extends e107MailManager 'mail_creator' => array('title' => LAN_MAILOUT_85, 'proc' => 'username'), 'mail_create_app' => array('title' => LAN_MAILOUT_133), '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_body' => array('title' => LAN_MAILOUT_100, 'proc' => 'trunc200'), // '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) protected $hideFields = 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', - 'sent' => 'mail_togo_count,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,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_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_last_date,mail_selectors', - 'resend' => '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_notify_complete,mail_last_date,mail_selectors', + 'resend' => 'mail_Selectors,mail_notify_complete', 'recipients' => 'mail_detail_id' ); @@ -164,7 +166,9 @@ class mailoutAdminClass extends e107MailManager public function __construct($mode = '') { parent::__construct(); -// $saveMode = $mode; + require_once(e_HANDLER.'calendar/calendar_class.php'); + $this->_cal = new DHTML_Calendar(true); + $dbTable = ''; 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) { 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 * * Options given depend on $mode, and also values in the email data. * - * @param $mailData - array of email-related info - * @return HTML for display + * @param array $mailData - array of email-related info + * @return string HTML for display */ public function makeMailOptions($mode,$mailData) { @@ -1191,7 +1169,6 @@ class mailoutAdminClass extends e107MailManager - "; $text .= $this->showMailDetail($mailData, 'send'); @@ -1209,14 +1186,16 @@ class mailoutAdminClass extends e107MailManager // Figures - number of emails to send, number of duplicates stripped $text .= '"; $text .= ''; - - $text .= ""; $text .= "
'.LAN_MAILOUT_173.''.($mailData['mail_togo_count'])."
'.LAN_MAILOUT_71.' '.$counters['add'].' '.LAN_MAILOUT_69.$counters['dups'].LAN_MAILOUT_70.'
Add in start/end dates here
\n
"; + $text .= $this->makeAdvancedOptions(TRUE); // Show the table of advanced options + $text .= "
    +
+ "; $this->e107->ns->tablerender("
".ADLAN_136." :: ".LAN_MAILOUT_179."
", $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 = " + ".LAN_MAILOUT_242." +
+ + + + + + "; + + $text .= ""; + $text .= ""; + // Can comment the two lines above, uncomment two lines below, and default time/date is shown. May or may not be preferable +// $text .= ""; +// $text .= ""; + $text .= ""; + $text .= "
".LAN_MAILOUT_238."".$this->makeCalendar('mail_earliest_time')."
".LAN_MAILOUT_239."".$this->makeCalendar('mail_latest_time')."
".LAN_MAILOUT_238."".$this->makeCalendar('mail_earliest_time', time())."
".LAN_MAILOUT_239."".$this->makeCalendar('mail_latest_time', time()+86400)."
".LAN_MAILOUT_240."".LAN_MAILOUT_241."
\n
"; + 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; $results = array(); $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) { $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 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.") - 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'; $noError = FALSE; @@ -1424,6 +1447,10 @@ class mailoutAdminClass extends e107MailManager { $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); @@ -1486,10 +1513,10 @@ class mailoutAdminClass extends e107MailManager switch ($row['mail_status']) { 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; 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 break; 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, ''); diff --git a/e107_handlers/notify_class.php b/e107_handlers/notify_class.php index cf5d5505a..23e6bf971 100644 --- a/e107_handlers/notify_class.php +++ b/e107_handlers/notify_class.php @@ -9,8 +9,8 @@ * Forum plugin notify configuration * * $Source: /cvs_backup/e107_0.8/e107_handlers/notify_class.php,v $ -* $Revision: 1.9 $ -* $Date: 2009-11-19 20:24:21 $ +* $Revision: 1.10 $ +* $Date: 2009-11-27 21:42:46 $ * $Author: e107steved $ * */ @@ -112,6 +112,7 @@ class notify 'mail_sender_email' => $pref['siteadminemail'], 'mail_sender_name' => $pref['siteadmin'], 'mail_send_style' => 'textonly', + 'mail_notify_complete' => 0, // NEVER notify when this email sent!!!!! 'mail_body' => $message ); $result = $mailer->saveEmail($mailData, TRUE); @@ -255,6 +256,13 @@ function notify_newsdel($data) } +function notify_maildone($data) +{ + $message = ''.$data['mail_subject'].'

'.$data['mail_body']; + e107::getNotify()->send('maildone', NT_LAN_ML_1.': '.$data['mail_subject'], $message); +} + + function notify_fileupload($data) { global $nt; @@ -262,6 +270,7 @@ function notify_fileupload($data) $nt->send('fileupload', $data['upload_name'], $message); } + if (isset($nt->notify_prefs['plugins'])) { foreach ($nt->notify_prefs['plugins'] as $plugin_id => $plugin_settings) diff --git a/e107_handlers/pop3_class.php b/e107_handlers/pop3_class.php index f61b3c553..3c9d531d5 100644 --- a/e107_handlers/pop3_class.php +++ b/e107_handlers/pop3_class.php @@ -1,9 +1,9 @@ marubox=imap_open($this->server,$this->username,$this->password); } + function getHeaders($mid) // Get Header info { $mail_header=imap_header($this->marubox,$mid); @@ -69,6 +70,8 @@ class receiveMail return $mail_details; } + + function get_mime_type(&$structure) //Get Mime type Internal Private Use { $primary_mime_type = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER"); @@ -78,6 +81,8 @@ class receiveMail } return "TEXT/PLAIN"; } + + function get_part($stream, $msg_number, $mime_type, $structure = false, $part_number = false) //Get Part Of Message Internal Private Use { if(!$structure) { @@ -122,11 +127,15 @@ class receiveMail } return false; } + + function getTotalMails() //Get Total Number off Unread Email In Mailbox { $headers=imap_headers($this->marubox); return count($headers); } + + function GetAttach($mid,$path) // Get Atteced File from Mail { $struckture = imap_fetchstructure($this->marubox,$mid); @@ -159,6 +168,8 @@ class receiveMail $ar=substr($ar,0,(strlen($ar)-1)); return $ar; } + + function getBody($mid,$mode="") // Get Message Body { if($mode != "plain") @@ -172,10 +183,14 @@ class receiveMail } return $body; } + + function deleteMails($mid) // Delete That Mail { imap_delete($this->marubox,$mid); } + + function close_mailbox() //Close Mail Box { imap_close($this->marubox,CL_EXPUNGE); diff --git a/e107_handlers/pop_bounce_handler.php b/e107_handlers/pop_bounce_handler.php new file mode 100644 index 000000000..07d457bb1 --- /dev/null +++ b/e107_handlers/pop_bounce_handler.php @@ -0,0 +1,263 @@ +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}
Header: {$e107Header}
"; + $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(); + } +} + + +?> diff --git a/e107_languages/English/admin/lan_mailout.php b/e107_languages/English/admin/lan_mailout.php index e4530accb..fd125dd1b 100644 --- a/e107_languages/English/admin/lan_mailout.php +++ b/e107_languages/English/admin/lan_mailout.php @@ -9,8 +9,8 @@ * Administration - Site Maintenance * * $Source: /cvs_backup/e107_0.8/e107_languages/English/admin/lan_mailout.php,v $ - * $Revision: 1.12 $ - * $Date: 2009-11-24 20:40:35 $ + * $Revision: 1.13 $ + * $Date: 2009-11-27 21:42:46 $ * $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_224', 'Inc. Images'); 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_228', '--COUNT-- anomalies in mail_content corrected; records: --RECORDS--'); 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_235', '(Your server has to be configured to use this script)'); define('LAN_MAILOUT_236', 'Last Bounce Processed'); -define('LAN_MAILOUT_237', ''); -define('LAN_MAILOUT_238', ''); -define('LAN_MAILOUT_239', ''); -define('LAN_MAILOUT_240', ''); +define('LAN_MAILOUT_237', 'Summary counters updated on --COUNT-- emails'); +define('LAN_MAILOUT_238', 'Earliest time to send'); +define('LAN_MAILOUT_239', 'Latest time to send'); +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'); diff --git a/e107_languages/English/admin/lan_notify.php b/e107_languages/English/admin/lan_notify.php index 532b8104c..729083121 100644 --- a/e107_languages/English/admin/lan_notify.php +++ b/e107_languages/English/admin/lan_notify.php @@ -4,9 +4,9 @@ | e107 website system - Language File. | | $Source: /cvs_backup/e107_0.8/e107_languages/English/admin/lan_notify.php,v $ -| $Revision: 1.1.1.1 $ -| $Date: 2006-12-02 04:34:41 $ -| $Author: mcfly_e107 $ +| $Revision: 1.2 $ +| $Date: 2009-11-27 21:42:46 $ +| $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_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_2", "File uploaded by user"); diff --git a/e107_languages/English/lan_notify.php b/e107_languages/English/lan_notify.php index 0d1d412bd..c5d0835c9 100644 --- a/e107_languages/English/lan_notify.php +++ b/e107_languages/English/lan_notify.php @@ -4,9 +4,9 @@ | e107 website system - Language File. | | $Source: /cvs_backup/e107_0.8/e107_languages/English/lan_notify.php,v $ -| $Revision: 1.1.1.1 $ -| $Date: 2006-12-02 04:34:39 $ -| $Author: mcfly_e107 $ +| $Revision: 1.2 $ +| $Date: 2009-11-27 21:42:46 $ +| $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_ML_1', 'Bulk email send complete'); + define("NT_LAN_NU_1", "Updated"); define("NT_LAN_ND_1", "News Item Deleted");