-#!/usr/local/bin/php -q
+#! /usr/bin/php5
<?php
/**
- *
- * Massmail backend cron script
- * This is mass mailing backend script which actually sends messages
- * of the mailings scheduled via the web frontend. It does so by
- * spooling messages directly to mail server via SMTP protocol.
- * Mailing types, for which this is applicable, have trailer
- * appended with individual URL for unsubscription from future
- * mailings.
- *
- * SourceForge: Breaking Down the Barriers to Open Source Development
- * Copyright 1999-2001 (c) VA Linux Systems
- * http://sourceforge.net
- *
- * @version $Id$
- *
- */
-
-require ('squal_pre.php');
+ * Massmail backend cron script
+ * This is mass mailing backend script which actually sends messages
+ * of the mailings scheduled via the web frontend.
+ * Mailing types, for which this is applicable, have trailer
+ * appended with individual URL for unsubscription from future
+ * mailings.
+ *
+ * Copyright 1999-2001 (c) VA Linux Systems
+ * Copyright 2003 (c) GForge, LLC
+ *
+ * This file is part of GForge.
+ *
+ * GForge is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GForge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GForge; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 US
+ */
+
+require dirname(__FILE__).'/../www/env.inc.php';
+require $gfwww.'include/squal_pre.php';
+require $gfcommon.'include/cron_utils.php';
+
+$err='';
+
+if (!cron_create_lock(__FILE__)) {
+ $err = "Massmail already running...exiting";
+ if (!cron_entry(6,$err)) {
+ # rely on crond to report the error
+ echo "cron_entry error: ".db_error()."\n";
+ }
+ exit();
+}
-// SMTP server to connect to
-$MAILSERVER = "sf-list1";
-//$MAILSERVER = "localhost";
-// Whether to feed batch on its entirety and ignore responces or
-// *talk* with server. I decided against using pipelining.
-$PIPELINE = 0;
-// Number of users to mail during single run
-$CHUNK = 2000;
-// Size of SMTP batch (so many messages are sent in one connection)
-$BATCH = 20;
-// Pause between batches, sec
-$SLEEP = 10;
-// Dump batches to file instead sending them over socket
-$TEST = 0;
+// Pause between messages, sec
+$SLEEP = 1;
// This tables maps mailing types to tables which required to perform it
$table_mapping = array(
- 'ALL' => "users",
- 'SITE' => "users",
- 'COMMNTY' => "users",
- 'DVLPR' => "users,user_group",
- 'ADMIN' => "users,user_group",
- 'SFDVLPR' => "users,user_group",
+ 'ALL' => "users",
+ 'SITE' => "users",
+ 'COMMNTY' => "users",
+ 'DVLPR' => "users,user_group",
+ 'ADMIN' => "users,user_group,groups",
+ 'SFDVLPR' => "users,user_group",
);
// This tables maps mailing types to WHERE subclauses which select
// appropriate users
$cond_mapping = array(
- 'ALL' => "",
- 'SITE' => "AND mail_siteupdates=1",
- 'COMMNTY' => "AND mail_va=1",
- 'DVLPR' => "AND users.user_id=user_group.user_id",
- 'ADMIN' => "AND users.user_id=user_group.user_id AND user_group.admin_flags='A'",
- 'SFDVLPR' => "AND users.user_id=user_group.user_id AND user_group.group_id=1"
+ 'ALL' => "",
+ 'SITE' => "AND mail_siteupdates=1",
+ 'COMMNTY' => "AND mail_va=1",
+ 'DVLPR' => "AND users.user_id=user_group.user_id",
+ 'ADMIN' => "AND users.user_id=user_group.user_id AND user_group.admin_flags='A' AND groups.status='A' AND groups.group_id=user_group.group_id",
+ 'SFDVLPR' => "AND users.user_id=user_group.user_id AND user_group.group_id=1"
);
-/*if (!strstr($REMOTE_ADDR,$sys_internal_network)) {
- exit_permission_denied();
-}*/
-
-$mail_res = db_query("
- SELECT *
+$mail_res = db_query_params ('SELECT *
FROM massmail_queue
WHERE finished_date=0
- ORDER BY queued_date
-", 1);
+ ORDER BY queued_date',
+ array()) ;
+
/* If there was error, notify admins, but don't be pesky */
if (!$mail_res) {
- print "cannot execute quesry to select pending mailings\n";
+ $err .= "cannot execute query to select pending mailings: ".db_error()."\n";
$hrs = time()/(60*60);
// Send reminder every second day at 11am
if (($hrs%24)==11 && (($hrs/24)%2)==1) {
- global $sys_default_domain;
+ global $sys_admin_email;
util_send_message(
- "admin@$sys_default_domain",
+ "$sys_admin_email",
"ATT: Problems with massmail cron script",
- "This is automatically generated message from\n"
- ."the mass mailing cron script of SourceForge\n"
- ."installation. There was error querying massmail_queue\n"
- ."database table. Please take appropriate actions.\n",
+ "This is automatically generated message from\n
+the mass mailing cron script of ".forge_get_config ('forge_name')."\n
+installation. There was error querying massmail_queue\n
+database table. Please take appropriate actions.\n"
);
}
-
- exit(1);
+ m_exit();
}
-// print "Got ".db_numrows($mail_res)." rows\n";
+// $err .= "Got ".db_numrows($mail_res)." rows\n";
if (db_numrows($mail_res)<1) {
// Nothing to send
- exit();
+ m_exit();
}
$type = db_result($mail_res, 0, 'type');
if (!$table_mapping[$type]) {
- print "Unknown mailing type\n";
- exit(1);
+ $err .= "Unknown mailing type\n";
+ m_exit();
}
$subj = db_result($mail_res, 0, 'subject');
$mail_id = db_result($mail_res, 0, 'id');
+$body = db_result($mail_res, 0, 'message');
+//$err .= "Got mail to send: ".$subj."\n";
+
+$qpa = db_construct_qpa (false, 'SELECT DISTINCT users.user_id,users.user_name,users.realname,users.email,users.confirm_hash') ;
+switch ($type) {
+case 'ALL':
+case 'SITE':
+case 'COMMNTY':
+ $qpa = db_construct_qpa ($qpa, ' FROM users') ;
+ break ;
+case 'DVLPR':
+case 'SFDVLPR':
+ $qpa = db_construct_qpa ($qpa, ' FROM users, user_group') ;
+ break ;
+case 'ADMIN':
+ $qpa = db_construct_qpa ($qpa, ' FROM users, user_group, groups') ;
+ break ;
+}
-//print "Got mail to send: ".$subj."\n";
+$qpa = db_construct_qpa ($qpa, ' WHERE users.user_id > $1 AND users.status=$2',
+ array (db_result($mail_res, 0, 'last_userid'),
+ 'A')) ;
-$sql = "
- SELECT users.user_id,user_name,realname,email,confirm_hash
- FROM ".$table_mapping[$type]."
- WHERE users.user_id>".db_result($mail_res, 0, 'last_userid')."
- AND status='A'
- ".$cond_mapping[$type]."
- ORDER BY users.user_id
-";
+$cond_mapping = array(
+ 'ALL' => "",
+ 'SITE' => "",
+ 'COMMNTY' => "",
+ 'DVLPR' => "",
+ 'ADMIN' => "",
+ 'SFDVLPR' => ""
+);
-//echo $sql;
+
+switch ($type) {
+case 'ALL':
+ break ;
+case 'SITE':
+ $qpa = db_construct_qpa ($qpa, ' AND mail_siteupdates=1') ;
+ break ;
+case 'COMMNTY':
+ $qpa = db_construct_qpa ($qpa, ' AND mail_va=1') ;
+ break ;
+case 'DVLPR':
+ $qpa = db_construct_qpa ($qpa, ' AND users.user_id=user_group.user_id') ;
+ break ;
+case 'SFDVLPR':
+ $qpa = db_construct_qpa ($qpa, ' AND users.user_id=user_group.user_id AND user_group.group_id=1') ;
+ break ;
+case 'ADMIN':
+ $qpa = db_construct_qpa ($qpa, ' AND users.user_id=user_group.user_id AND user_group.admin_flags=$1 AND groups.status=$2 AND groups.group_id=user_group.group_id',
+ array ('A', 'A')) ;
+ break ;
+}
+
+$qpa = db_construct_qpa ($qpa, ' ORDER BY users.user_id') ;
// Get next chunk of users to mail
-$users_res = db_query($sql, $CHUNK);
+$users_res = db_query_qpa ($qpa);
-print "Mailing ".db_numrows($users_res)." users.\n";
+$err .= "Mailing ".db_numrows($users_res)." users.\n";
// If no more users left, we've finished with this mailing
if ($users_res && db_numrows($users_res)==0) {
- db_query("
- UPDATE massmail_queue
- SET failed_date=0,finished_date='".time()."'
- WHERE id=$mail_id
- ");
- exit();
+ db_query_params ('UPDATE massmail_queue SET failed_date=0,finished_date=$1 WHERE id=$2',
+ array(time(),
+ $mail_id));
+ m_exit();
}
-$batch_no = 0;
-$count = 0;
-$last_userid = 0;
+// Actual mailing loop
+$compt = 0;
+while ($row =& db_fetch_array($users_res)) {
+ $compt++;
+ if ($type=='SITE' || $type=='COMMNTY') {
+ $tail = "\r\n==================================================================\r\n" ;
+ $tail .= sprintf (_('You receive this message because you subscribed to %1$s
+site mailing(s). You may opt out from some of them selectively
+by logging in to %1$s and visiting your Account Maintenance
+page (%2$s), or disable them altogether
+by visiting following link:
+<%3$s>
+'),
+ forge_get_config ('forge_name'),
+ util_make_url('/account/'),
+ util_make_url('/account/unsubscribe.php?ch=_'.$row['confirm_hash'])) ;
+ } else {
+ $tail = "" ;
+ }
+ util_send_message($row['email'],$subj, $body."\r\n".$tail,'noreply@'.forge_get_config('web_host'));
+ $last_userid = $row['user_id'];
-// These mailing types should include unsubscription info
-if ($type=='SITE' || $type=='COMMNTY') {
- $tail = "\r\n==================================================================\r\n"
- ."You receive this message because you subscribed to SourceForge\r\n"
- ."site mailing(s). You may opt out from some of them selectively\r\n"
- ."by logging in to SourceForge and visiting your Account Maintenance\r\n"
- ."page (https://$sys_default_domain/account/), or disable them altogether\r\n"
- ."by visiting following link:\r\n"
- ."<https://$sys_default_domain/account/unsubscribe.php?ch=_%s>\r\n";
+ sleep($SLEEP);
}
-$body = db_result($mail_res, 0, 'message');
-//$lines = explode("\n", $body);
-//$crlf_body = implode("\r\n", $lines);
-// Get SMTP response
-function get_resp() {
- global $out;
- global $response;
-
- $response = fgets($out, 500);
-// print ">$response";
- return substr($response, 0, 3);
-}
+db_query_params ('UPDATE massmail_queue SET failed_date=0, last_userid=$1, finished_date=$2 WHERE id=$3',
+ array($last_userid,
+ time (),
+ $mail_id));
-// Expect given response, fail with $diag otherwise
-function expect($diag, $resp) {
- global $PIPELINE;
- global $response;
-
- if (!$PIPELINE) {
- if (get_resp()!=$resp) {
- print "Error: $diag: $response";
- exit(1);
- }
- }
+if (db_error()) {
+ $err .= $sql.db_error();
}
+$mess = "massmail $compt mails sent";
+m_exit($mess);
-// Start new batch
-function start_batch() {
- global $out;
- global $batch_no;
- global $sys_default_domain;
- global $MAILSERVER;
- global $TEST;
-
- if ($TEST) {
- $out = fopen("!batch.$batch_no","wb");
- } else {
- $out = fsockopen($MAILSERVER, 25, $errno, $errstr);
- }
+function m_exit($mess = '') {
+ global $err;
- if (!$out) {
- print "Error connecting to SMTP: $errstr\n";
- exit(1);
+ if (!cron_remove_lock(__FILE__)) {
+ $err .= "Could not remove lock\n";
}
- if (!$TEST) {
- $resp = fgets($out,200);
- if (substr($resp,0,3)!="220") {
- print "Server is not ready to receive messages\n";
- exit(1);
- }
- }
- fputs($out,"HELO $sys_default_domain\r\n");
- expect("HELO", "250");
-}
-
-// Finish new batch
-function flush_batch() {
- global $out;
- global $count;
- global $last_userid;
- global $mail_id;
- global $TEST;
-
- if ($count) {
- fputs($out,"QUIT\r\n");
- if (!$TEST) {
-// fpassthru($out);
- while (!feof($out)) fgets($out, 200);
- fclose($out);
- } else {
- fclose($out);
- }
- $count = 0;
-
- $sql="
- UPDATE massmail_queue
- SET failed_date=0,
- last_userid=$last_userid
- WHERE id=$mail_id
- ";
-// print $sql;
- db_query($sql);
-
- sleep($SLEEP);
+ if (!cron_entry(6,$mess.$err)) {
+ # rely on crond to report the error
+ echo "cron_entry error: ".db_error()."\n";
}
+ exit;
}
-
-// Actual mailing loop
-while ($row = db_fetch_array($users_res)) {
-
- if (!$count) {
- $batch_no++;
- start_batch();
- }
-
-// print "Sending for: ".$row['user_id']."\n";
-
-// $row['email'] = 'test@email';
-
- fputs($out,"MAIL FROM: noreply@$sys_default_domain\r\n");
- expect("MAIL", "250");
- fputs($out,"RCPT TO: ".$row['email']."\r\n");
- expect("RCPT", "250");
- fputs($out,"DATA\r\n");
- expect("DATA", "354");
- fputs(
- $out,
- "From: Mailer <noreply@$sys_default_domain>\r\n"
- ."To: \"".strtr($row['realname'],'"',"'")."\" <".$row['email'].">\r\n"
- ."Subject: ".$subj."\r\n"
- ."\r\n"
- .$body
- ."\r\n"
- .sprintf($tail,$row['confirm_hash'] )
- ."\r\n.\r\n"
- );
- expect("DATA end", "250");
-
- $last_userid = $row['user_id'];
-
- if (++$count == $BATCH) {
- flush_batch();
- }
-}
-
-flush_batch();
-
-// print "end\n";
+// Local Variables:
+// mode: php
+// c-file-style: "bsd"
+// End:
?>