Google Answers Logo
View Question
 
Q: sendmail recipients on Linux command line via PHP popen() ( Answered 5 out of 5 stars,   0 Comments )
Question  
Subject: sendmail recipients on Linux command line via PHP popen()
Category: Computers > Programming
Asked by: greendavid-ga
List Price: $20.00
Posted: 11 Sep 2002 06:05 PDT
Expires: 11 Oct 2002 06:05 PDT
Question ID: 63829
I am writing a mailing list application in PHP.  I intend to send a
message to a list of e-mail addresses pulled from a MySQL database (up
to 1300 addresses; not spam, a community club).

I will not use the "Bcc:" header, because (according to RFC 2822,
Sections 3.6.3 and 5; http://www.faqs.org/rfcs/rfc2822.html) the
"Bcc:" recipients may receive a list of all "Bcc:" recipients.

I intend to put the recipient addresses in the call to sendmail using
PHP popen(). (See http://www.php.net/manual/en/function.popen.php). 
The call looks like this, given that $addresses holds a
comma-delimited list of e-mail addresses and $message holds a properly
formatted e-mail message, including headers:

--- begin PHP code ---
$mail = popen("/usr/sbin/sendmail -oi -fmailer@mydomain".
$addresses,"w");
fwrite($mail, $message);
$result = (pclose($mail)>>8)&0xFF;
--- end PHP code ---

Here are the 2 questions:  Is there an upper limit on the number of
characters in $addresses (i.e. strlen($addresses))?  Is there an upper
limit on the number of e-mail addresses that can be delivered to the
sendmail command in this way?

--David B.

P.S. I believe the Linux version is 2.2.19 Debian.

Request for Question Clarification by studboy-ga on 11 Sep 2002 08:00 PDT
Why not use a while/for-loop and loop through each of the addresses?
You sacrifice a little computational time but in that case you don't 
need to even worry about this.  The memory buffer may be different
for different system OS/shell.

Clarification of Question by greendavid-ga on 11 Sep 2002 08:55 PDT
I considered using a while loop in the PHP script.  The problem is
that the PHP script (which is called by Apache) may time out before
all the messages are sent.

It was suggested to me that I use PHP exec() to call separate PHP
script which would be launched in a new process.  The script called
from the Web server might time out, but the one launched with exec()
would continue until all the messages were sent.  Is this a good idea?

Clarification of Question by greendavid-ga on 11 Sep 2002 09:29 PDT
Also, using a loop will create multiple sendmail (or SMTP) sessions,
while sending all the addresses in a comma-delimited list creates only
one.
Answer  
Subject: Re: sendmail recipients on Linux command line via PHP popen()
Answered By: spot_tippybuttons-ga on 12 Sep 2002 03:10 PDT
Rated:5 out of 5 stars
 
There is a limit to what Sendmail can accept, as well as the Linux
command line itself. I was not able to identify exactly what the limit
is, but I found numerous estimates of anywhere from 4K and up. Some
Sendmail implementations have a 512 byte address limit, but this does
not appear to be the case for 8.12.6, which is the most current
distribution.

In any case, you do not want to send the whole address list in one big
chunk as this will most likely clog up your mail server, as well as
risk truncating the list.

The most efficient thing would be to sort your mailing list by domain,
and send groups of addresses to Sendmail batched by domain. If you are
concerned about multiple Sendmail processes, simply pause a few
seconds after each batch or use pclose to get the return status before
starting the next process. i.e.:

$ret=(pclose($f)>>8)&0xFF;

The other advantage of batching calls to Sendmail is the ability to
restart the mailing midway should a problem occur. As you send batches
out, record your current position in the mailing list to a file. If a
fatal error occurs, use the file to determine where to restart the
process.

Launching your script with exec is an excellent idea. Otherwise, your
script has a very high chance of being timed out, or worse yet, killed
by Apache should you lose your connection. When you launch your script
with exec, be sure to redirect the output to a file or PHP will wait
on execution. If you're clever, you can use the results recorded into
the file to check up on your scripts progress later through your web
browser.

Speaking of timeouts, even if you are running your script in the
background, don't forget to call set_time_limit(0) at the beginning or
PHP itself will terminate your script after 30 seconds. Calling
set_time_limit(0) will set the time limit to infinite, so your mailing
list will have all the time it needs to complete.

With 1300 names, you may want to consider a full fledged mailing list
program or batch sending utility. You may get better performance than
you will with Sendmail and PHP, as many of the batch mailing utilities
are optimized for high performance.

Let me know if you need more details on anything.



Sendmail
http://www.sendmail.org

Specifying command line arguments in a file?
http://gcc.gnu.org/ml/gcc/2001-04/msg01368.html

Thread: joining a bunch of files
http://www.geocrawler.com/archives/3/93/2001/11/0/7211954/

Thread: rm problem
http://www.geocrawler.com/archives/3/84/2000/8/50/4258520/

Performance and system-load issues related to mail delivery
http://www.faqs.org/faqs/mail/list-admin/software-faq/section-10.html

PHP Documentation
http://www.php.net

Search Strategy:
linux "command line" character limit length
://www.google.com/search?q=linux+%22command+line%22+character+limit+length&hl=en&lr=&ie=UTF-8&start=0&sa=N

mail maximum addresses sendmail
://www.google.com/search?q=mail+maximum+addresses+sendmail&hl=en&lr=&ie=UTF-8&as_qdr=all&start=0&sa=N

manual review of sendmail source code available from sendmail.org

Request for Answer Clarification by greendavid-ga on 12 Sep 2002 10:42 PDT
Thank you for the extreme clarity and usefulness of your answer (not
to mention speed)!

With reference to "$ret=(pclose($f)>>8)&0xFF;"  I have used this and
understand (only) that a non-zero value indicates an error.

1) Can you refer me to a list of the meanings of the numerical
results, please?
2) Do you know if any non-zero value means that no messages were sent,
or can an error result be returned even if messages were sent to some
of the addresses?

Thanks again!

--David B.
"greendavid"

Clarification of Answer by spot_tippybuttons-ga on 12 Sep 2002 15:37 PDT
Generally, receiving a numerical error code other than zero (which is
success) means the whole job didn't work, especially when you are
batching e-mails. If a specific user can't be delivered to, Sendmail
will drop this message in the queue and retry it again later. How much
later depends on your Sendmail configuration settings. You may or may
not get an error code if this happens depending on your implementation
and other flags to Sendmail. This is in part a hold over from the "old
days" when it was normal for remote systems to be temporarily
unavailable on a regular basis.

When you complete the job, you can force the queue to reprocess
immediately if you want. The command for this on most implementations
is:

 sendmail -q

The best thing to do for error handling is to set up an e-mail account
specifically to receive bounces. When you generate the e-mail, set the
"from" address to the error account. Set the "reply to" address to the
account that should receive real mail from users, i.e.  the list
administration account.

The error account will collect all the bounced mails. The best thing
to do then is to write an automated script that will parse the
addresses out of all of the bounces and remove them from your mailing
list. People frequently change e-mail accounts and forget to update
their list subscriptions and the like, so it is normal to have some
number of dead addresses on any mailing list. Pruning the dead
addresses will help you save time next time you send your list.

I'm not sure what kind of system access you have, but if you don't
want to have to parse the mailbox after the fact, you can use the
Sendmail alias command and the #error directive to redirect everything
from the error account to a script as soon as it is received. You will
find more information about how to use the alias command in your man
pages. There is also a very good book by O'Reilly, appropriately
titled "Sendmail" that has pretty much anything you ever wanted to
know about Sendmail. You can read more about the book at
http://www.ora.com/catalog/sendmail2/

Here is a list of exit codes for Sendmail from the 8.12.6 source code.
Note: These are NOT to be confused with the return codes that Sendmail
sends by TCP/IP to the remote host. These are the command line exit
codes.

(0) EX_OK -- successful termination

(64) EX_USAGE -- The command was used incorrectly, e.g., with the
wrong number of arguments, a bad flag, a bad syntax in a parameter, or
whatever.

(65) EX_DATAERR -- The input data was incorrect in some way. This
should only be used for user's data & not system files.

(66) EX_NOINPUT -- An input file (not a system file) did not exist or
was not readable.  This could also include errors like "No message" to
a mailer (if it cared to catch it).

(67) EX_NOUSER -- The user specified did not exist.  This might be
used for mail addresses or remote logins.

(68) EX_NOHOST -- The host specified did not exist.  This is used in
mail addresses or network requests.

(69) EX_UNAVAILABLE -- A service is unavailable.  This can occur if a
support program or file does not exist.  This can also be used as a
catchall message when something you wanted to do doesn't work, but you
don't know why.

(70) EX_SOFTWARE -- An internal software error has been detected. This
should be limited to non-operating system related errors as possible.

(71) EX_OSERR -- An operating system error has been detected. This is
intended to be used for such things as "cannot fork", "cannot create
pipe", or the like.  It includes things like getuid returning a user
that does not exist in the passwd file.

(72) EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
etc.) does not exist, cannot be opened, or has some sort of error
(e.g., syntax error).

(73) EX_CANTCREAT -- A (user specified) output file cannot be created.

(74) EX_IOERR -- An error occurred while doing I/O on some file.

(75) EX_TEMPFAIL -- temporary failure, indicating something that is
not really an error.  In sendmail, this means that a mailer (e.g.)
could not create a connection, and the request should be reattempted
later.

(76) EX_PROTOCOL -- the remote system returned something that was "not
possible" during a protocol exchange.

(77) EX_NOPERM -- You did not have sufficient permission to perform
the operation.  This is not intended for file system problems, which
should use NOINPUT or CANTCREAT, but rather for higher level
permissions.

(78) EX_CONFIG -- configuration error



Good luck with your mailing!
greendavid-ga rated this answer:5 out of 5 stars
The answer is clear, direct, comprehensive, and provides additional
information that I did not even know I needed!

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy