> mail($Email, $MsgTitle, "$Message\n\n\n$Content", $Header);
Here is the "culprit" -- This is going to fire up a sendmail process for
every single email.
You are going to choke your server to death with tons and tons of sendmail
processes.
Actually, after about 50 of these, the mail() function is going to fail.
With an "Unable to fork" message, I think. Then, a few of those early
sendmails will finish, and your loop will still be going, and some more will
go through okay, until you're back up to 50 concurrent sendmails, and some
more will choke, and... You'll never be able to keep track of which ones
worked.
Here is an excerpt from some code I wrote recently.
This uses PostgreSQL, so you'll have to adjust it a bit.
Hopefully the comments and debug output I've left in there until this is in
production awhile will be sufficient as-is.
Better more general-purpose code is available in Manuel Lemos' mail class at
UpperDesign and several other SMTP email functions/classes. This is pretty
raw and unplugged, but that's the way I like it :-)
*ALL* of these lines are needed to essentially replace the one line above...
<?php
# This is to be run as a cron job.
# This script:
# Opens the SMTP port
# Initiates an SQL transaction (thus making this script thread-safe)
# Grabs any queued email, in "liame" order, and for each email:
# Attempts to send that email via SMTP
# Snags the emailid from SMTP
# Updates the database with the emailid and marks that email "sent"
#
# I may also code it to:
# Move any sent emails from "queue" to "sent"
# Or maybe I'll do that in another script, to reduce execution time of
this one
# Open SMTP socket:
$smtp = fsockopen('localhost', 25, &$errorno, &$errorstr, 2.0);
if (!$smtp){
if ($errno){
die("SMPT returned Error #$errno: $errorstr<BR>\n");
}
else{
die("Unable to open SMTP<BR>\n");
}
}
# ... and let SMTP say "Hi":
$greeting = fgets($smtp, 1024);
switch((int) $greeting){
case 220:
# Everything is beautiful
echo $greeting, "<BR>\n";
break;
default:
die("SMTP was expected to greet us, but said<BR>\n$greeting<BR>\n");
break;
}
echo "Saying HELO<BR>\n";
flush();
# Now, we say "Hi" back:
$bytes = fputs($smtp, "HELO listbaby.com\r\n");
if (!$bytes){
die("SMTP wouldn't even take our 'HELO'<BR>\n");
}
# ... and let SMTP say, yeah, yeah, let's go:
$gotit = fgets($smtp, 1024);
switch((int) $gotit){
case 250:
# Everything is beautiful
echo $gotit, "<BR>\n";
break;
default:
die("SMTP didn't like us when we said HELO<BR>\n$gotit<BR>\n");
break;
}
# Now, we're ready to start spewing out the emails!
# I'm not real clear if I need both the transaction and SELECT ... FOR
UPDATE ...
# But I reckon having both won't hurt, eh?
# Serializable is "more" transactional than the default:
/*
But I don't have that in my version... Hopefully you do...
$query = "set transaction isolation level serializable";
echo $query, "<BR>\n";
flush();
$serialize = pg_exec($connection, $query);
*/
# Hmmmm. What I *really* want here is to mark the emails I'm sending
# as "pending" right away for all transactions to see,
# so if *another* copy of this script runs in parallel, no duplicates are
sent...
# I'm going to ignore this for now, really, and just not run two in
parallel,
# because I haven't quite figured out which isolation level does that...
$query = "begin transaction";
echo $query, "<BR>\n";
flush();
$transaction = pg_exec($connection, $query);
# "for update" locks these rows, so if another "sendmail.htm" runs in the
middle of this, we
# won't step on our own feet...
# Or, at least, that's how I sort of understand it...
# liame is "email" backwards -- As I understand it, SMTP can go faster if
it your emails
# are pre-sorted by destination. IE, all the AOLusers are together, all
the Hotmails etc.
# So, as a poor man's sort, I keep everybody's email reversed in liame.
$query = "select queue_id, email, reply, headers, body from queue where
not sent = 't' order by liame ";
# Looks like I don't have "for update" in my PostgreSQL either...
//$query .= " for update ";
echo $query, "<BR>\n";
flush();
$emails = pg_exec($connection, $query);
echo "Starting loop<BR>\n";
flush();
$emailcount = 0;
while (list($queue_id, $email, $reply, $headers, $body) =
@pg_fetch_row($emails, $emailcount++)){
$error = 0;
echo "Sending queue_id $queue_id<BR>\n";
flush();
# Tell SMTP who it's from:
$command = "MAIL FROM: $reply\r\n";
echo $command, "<BR>\n";
flush();
$mailfrom = fputs($smtp, $command);
if (!$mailfrom){
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't like this at all $command<BR>\n";
flush();
$error++;
}
$mailfrom = fgets($smtp, 1024);
switch((int) $mailfrom){
case 250:
# Every thing is beautiful
echo $mailfrom, "<BR>\n";
flush();
break;
default:
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't like $command<BR>\n";
echo $mailfrom, "<BR>\n";
flush();
$error++;
break;
}
# Tell SMTP who it's to:
$command = "RCPT TO: $email\r\n";
echo $command, "<BR>\n";
flush();
$rcptto = fputs($smtp, $command);
if (!$rcptto){
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't like this at all $command<BR>\n";
flush();
$error++;
}
$rcptto = fgets($smtp, 1024);
switch((int) $rcptto){
case 250:
# Everything is beautiful
echo $rcptto, "<BR>\n";
flush();
break;
default:
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't like $command<BR>\n";
echo $rcptto, "<BR>\n";
flush();
$error++;
break;
}
# Tell SMTP we're about to spew the actual email:
$command = "DATA\r\n"; # No, it's not Star Trek: The Next Generation
echo $command, "<BR>\n";
flush();
$data = fputs($smtp, $command);
if (!$data){
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't like this at all $command<BR>\n";
flush();
$error++;
}
$data = fgets($smtp, 1024);
switch ((int) $data){
case 354:
# Everything is beautiful
echo $data, "<BR>\n";
flush();
break;
default:
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't like $command<BR>\n";
echo $data, "<BR>\n";
flush();
$error++;
break;
}
# The definition of the end of an email for SMTP is a "." all by itself
on a line
# What if one of our emails actually *HAS* that as part of its content?
# I later found out that there's a flag to sendmail to alter the end of
message signal
# I'm betting there's a SMTP command for that too.
# You'll have to find that on your own.
$body = str_replace("\n.\n", "\n. \n", $body);
$body = ereg_replace("^.\\n", ". \\n", $body);
# There's no way our headers should be so messed up, but...
# Am I paranoid enough?
$headers = str_replace("\n.\n", "\n. \n", $headers);
$headers = ereg_replace("^.\\n", ". \\n", $headers);
$headout = fputs($smtp, $headers);
echo nl2br($headers);
flush();
if (!$headout){
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't like these headers:<BR>\n";
echo nl2br($headers);
flush();
}
$newline = fputs($smtp, "\r\n");
echo "<BR>\n";
$bodyout = fputs($smtp, $body);
echo nl2br($body);
flush();
if (!$bodyout){
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't like this body:<BR>\n";
echo nl2br($body);
flush();
}
# End this email:
$dotout = fputs($smtp, ".\r\n");
if (!$dotout){
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't get the email ending...<BR>\n";
flush();
}
$sent = fgets($smtp, 1024);
if (!$sent){
echo "queue_id $queue_id<BR>\n";
echo "SMTP really didn't like that email.<BR>\n";
flush();
}
switch((int) $sent){
case 250:
# Everything is beautiful
# But let's snag that sendmail unique identifier
# So we can literally backtrack to our data
$twofifty = strtok($sent, ' ');
$sendmail_id = strtok(' ');
if (!$error){
$query = "update queue set sent = 't', sendmail_id =
'$sendmail_id' where queue_id = $queue_id";
echo $query, "<BR>\n";
flush();
$update = pg_exec($connection, $query);
}
break;
default:
echo "queue_id $queue_id<BR>\n";
echo "SMTP didn't like that email.<BR>\n";
flush();
break;
}
echo "Next<BR>\n";
flush();
}
# Tell SMPT we're quitting:
$command = "QUIT\r\n";
$quit = fputs($smtp, $command);
if (!$quit){
echo "SMTP didn't like $command<BR>\n";
flush();
}
$quit = fgets($smtp, 1024);
switch ((int) $quit){
case 221:
# Everything is beautiful
echo $quit, "<BR>\n";
break;
default:
echo "SMTP didn't like $command<BR>\n";
echo $quit, "<BR>\n";
flush();
break;
}
$query = "commit transaction";
echo $query, "<BR>\n";
pg_exec($connection, $query);
# Close it down:
fclose($smtp);
?>
--
WARNING [EMAIL PROTECTED] address is an endangered species -- Use
[EMAIL PROTECTED]
Wanna help me out? Like Music? Buy a CD: http://l-i-e.com/artists.htm
Volunteer a little time: http://chatmusic.com/volunteer.htm
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]