Sending an Email through PHP using a Db
Hey, how would i send an email to a large group of email addresses, taken from a dB? I have a form setup, which would contain the body, but what would be the send-to? You know what I'm saying? Any help would be great. Thanks.
necrotic posted this at 20:19 — 18th January 2004.
He has: 296 posts
Joined: May 2002
<?php
$query = mysql_query(\"SELECT email FROM users\");
while ($emails = mysql_fetch_row($query)) {
$sendto = (isset($sendto)) ? $sendto.\", \".$emails['email'] : $emails['email'];
}
mail($sendto,\"Subject\",\"Body\");
?>
Untested, but that should work.
[James Logsdon]
Renegade posted this at 09:52 — 19th January 2004.
He has: 3,022 posts
Joined: Oct 2002
Dude, I think that will only send one email, you need the mail() function in the while() loop body.
<?php
$query = mysql_query(\"SELECT email FROM users\");
while ($emails = mysql_fetch_row($query)) {
$sendto = (isset($sendto)) ? $sendto.\", \".$emails['email'] : $emails['email'];
mail($sendto,\"Subject\",\"Body\");
}
?>
kb posted this at 23:15 — 18th January 2004.
He has: 1,380 posts
Joined: Feb 2002
ok thanks.
Abhishek Reddy posted this at 10:48 — 19th January 2004.
He has: 3,348 posts
Joined: Jul 2001
heh, Renegade, no. To send multiple emails, you list them as "[email protected], [email protected], [email protected]". James's code creates a comma-separated string of all the email addresses. The mail() function need only be used once; the mailserver handles the multiple addresses.
The code you provide is dangerous for two reasons. First, it'll send one email to all addresses, for each email address to send to. Not only will this fill up inboxes, but it will likely break the server. Second, when you use the mail() function, you're opening a connection with the mail server, sending data, then closing. Repeating this several times over creates substantial overhead on the server. Read the user notes on the mail function page at php.net for more info.
kb posted this at 16:34 — 19th January 2004.
He has: 1,380 posts
Joined: Feb 2002
lol thanks
Suzanne posted this at 16:54 — 19th January 2004.
She has: 5,507 posts
Joined: Feb 2000
Abhi, that doesn't make sense to me -- I can't send out emails with all the addresses visible, they need to be showing as one email to one recipient. The other option is a "group" name and then having all the emails as a bcc: -- can you explain why sending an email to each recipient would break the server? I wouldn't think that most servers can't handle 150 emails sent out one at a time any more problematically than 150 emails sent at once, barring the additional overhead of multiple mail()?
Abhishek Reddy posted this at 04:22 — 20th January 2004.
He has: 3,348 posts
Joined: Jul 2001
As I understand it...
Suppose there are 200 addresses in the db to send to, the looping code with the stringed addresses will have the server send 200 mails out, 200 times (because the loop repeats it for each address in the db). 200*200 = 40,000. And since it sends to the same addresses, 200 people will theoretically end up with 200 copies of the same email in their inbox.
Why the server breaks is because the PHP mail() function is reasonably inefficient. For the reason that it opens a connection to the Mail Transfer Agent, sends the required mail data to the MTA, then closes the connection. This is fine for sending a few emails, or even for sending a list of emails for the MTA to parse and handle. But with the code in question, it means it will open a connection, send 200 addresses to send to and close the connection (this is fine), but repeat it 200 times (this is not fine).
As noted in the user comments on the ref.mail and function.mail pages on php.net, opening a single socket with the MTA to send multiple mails out is more efficient.
m3rajk posted this at 18:21 — 22nd January 2004.
They have: 461 posts
Joined: Jul 2003
either i'm reading the code wrong, or your math is wrong.
i'm reading that in the one with the mail in the loop it adds an address with each loop, thus if there is 200 name,s the first gets 200 emails, the second 199, and thus down to the 200th gets one.
however i also see the point of what suzanne said about the dynamic body, in which case merely changing the script to reset the to feild should make it 200 emails flat int hat situation. and in that cas, do you have a way to send 200 different emails in one call? or would one need to make all 200 calls to the mail function?
personally if everything else was static, i'd build the mailing list as a bcc and send it once with myself in the to feild so that no recipient would see the others, thus protecting privacy
POSIX. because a stable os that doesn't have memory leaks and isn't buggy is always good.
Mark Hensler posted this at 07:49 — 20th January 2004.
He has: 4,048 posts
Joined: Aug 2000
If the body is static (same for all recipients), you may want to consider using an alias on your own domain.
If the body is dynamic (different for all recipients), then you will need to build the body and send it out within a loop.
Which solution do you need?
Mark Hensler
If there is no answer on Google, then there is no question.
Renegade posted this at 09:47 — 20th January 2004.
He has: 3,022 posts
Joined: Oct 2002
So when a user gets the email, the To: field will show 150 addressess?
Suzanne posted this at 18:26 — 20th January 2004.
She has: 5,507 posts
Joined: Feb 2000
Okay, this is important to me to understand -- we have a list of 150 persons. Each email has the same body except for a piece that reminds the person of their personal login ID and a section personalizing the email (Hi, $username).
I *don't* understand how looping through a list of email addresses and composing and then sending an email for each address would result in 150x150?! I'm not making an array of email addresses, just one email address per mail(). In practice, this has resulted in each person getting one copy of the personalized email (I send one to myself as well), containing only that email address (no bcc, no groups, no list) and the server hasn't broken.
What am I not understanding here (reading the references now, I may find the answer there, if so, I'll report back)?
Suzanne posted this at 18:39 — 20th January 2004.
She has: 5,507 posts
Joined: Feb 2000
Alrighty, I see that someone says that using mail() for heavy emailing isn't efficient if it's in a loop. Not that it causes an exponential amount of mailing -- can you quote the relevant part for me, Abhi, I can't seem to find it?
Does heavy emailing mean a big list, or a big email sent to a big list? Would a small text-only email be as big a deal?
druagord posted this at 18:47 — 20th January 2004.
He has: 335 posts
Joined: May 2003
What makes a big deal is how many you send. The best way to preserve server resource is to put all recipient in bcc
Suzanne posted this at 18:58 — 20th January 2004.
She has: 5,507 posts
Joined: Feb 2000
I understand that, but that's not always feasible (see need to personalize each email). I'm less concerned with server resources (unless it will crash the server) than with crashing the user's inbox. The server is there to be used, I see no benefit in conserving what I do with it except whereas it impacts other things I need it for (i.e. I don't conserve food just to conserve it, I conserve food when there is a shortage).
Then again, I send them out monthly, in the middle of the night.
druagord posted this at 19:10 — 20th January 2004.
He has: 335 posts
Joined: May 2003
Sorry i guess i read to fast
ok the problem is in the code by renegade all address are added to the to field it could be corrected like this.
<?php
$query = mysql_query(\"SELECT email FROM users\");
while ($emails = mysql_fetch_row($query)) {
$sendto = $emails['email'];/* remove this (isset($sendto)) ? $sendto.\", \". $emails['email'] :$emails['email'];*/
mail($sendto,\"Subject\",\"Body\");
}
?>
IF , ELSE , WHILE isn't that what life is all about
Suzanne posted this at 19:37 — 20th January 2004.
She has: 5,507 posts
Joined: Feb 2000
We need someone to come through and remove all my questions and make a nice summary of what should actually be done, lol...
Is this right??:
An ideal mass-mailing script made of php wouldn't use mail(), it would use another method. (e.g. Eskator should investigate another method of sending out his emails as he has a large group, such as the function being worked on by grey at greywyvern dot com
?)
You can use mail() in a loop, if you only feed it one email address at a time or use BCC? But beware that over (what, 50?, 100?) emails, you're seriously compromising the efficiency of your server and should look into one of the other options for mass mail outs, such as _________ (sendmail()? using a pipe to the SMTP server?).
A method for using mail(); with a database of email addresses, is:
<?php
// connect to the db
// query the db for all the email addresses and other information needed
// send the email for each address
while ($results = mysql_fetch_row($qry)) {
// prepare the message by filling in all the pieces as needed
$recipient = $results['email'];
mail($recipient,$sender,$subject,$message,$otherheaders);
}
?>
druagord posted this at 19:50 — 20th January 2004.
He has: 335 posts
Joined: May 2003
I use mail() in a loop for a mailling list of about 1000 user and it work fine without any trouble to my server. i group my adresses by 50 in the bcc
so there are around 200 calls to mail() this doesn't stress my server at all
IF , ELSE , WHILE isn't that what life is all about
necrotic posted this at 20:34 — 20th January 2004.
He has: 296 posts
Joined: May 2002
Woohhh... this turned into a big thread!
So I don't get it: is my code ex. OKAY to use? Or would you want to use BCC instead of TO? I'm not much with server stuff, so it stumps me.
[James Logsdon]
Renegade posted this at 21:17 — 20th January 2004.
He has: 3,022 posts
Joined: Oct 2002
The code that you have is OK to use - just not the one that I gave.
The problem with the one I gave is that it will send the first email then the first and second email then the first, second and third email...so on and so on.
druagord posted this at 21:26 — 20th January 2004.
He has: 335 posts
Joined: May 2003
IMO using BCC is better because it recipients won't be able to get the email adresse of other recipients spammer register themself to mailling list just to get emails. Server wise it make no difference.
IF , ELSE , WHILE isn't that what life is all about
Abhishek Reddy posted this at 05:46 — 21st January 2004.
He has: 3,348 posts
Joined: Jul 2001
Suzanne, I was referring to Renegade's flawed code, which appends an address to the $sendto string, then sends out a set of mails, then appends the next address to $sendto, and then mails once again to the new set. I oversimplified the math so as not to break into this algorithm... it actually sends 200 emails to the first person, 199 to the second, 198 to the third . . . 1 to the last.
As for efficiency, all reports I've read regarding this indicate that opening a single socket with the MTA (usually sendmail) is more efficient than using mail() repeatedly. I don't have first-hand experience with this so I can't say for myself. I objected to using a repeating mail() script in Renegade's loop since that would send out additional unnecessary mails... which could be dangerous.
Last comment on this page: http://nz2.php.net/manual/en/function.mail.php (lit at matches dot com[b])[/b] as well as the script you quoted, Suzanne.
Suzanne posted this at 06:31 — 21st January 2004.
She has: 5,507 posts
Joined: Feb 2000
*understanding dawns*
Thank you, Abhi! I feel much less confused. It's a bad day when you think you know something, then start doubting yourself. Two Mondays in a row. *sigh*
Mark Hensler posted this at 07:28 — 21st January 2004.
He has: 4,048 posts
Joined: Aug 2000
I've always avoided use of the BCC header in mail scripts. This is because of several (dated) documents that I have read that suggest that the BCC header is not fully and uniformally supported. I suppose the determining factor would be the MTA that you use to initially send out the email, but I have not done any in-depth investigation.
I also recently read that the To, Cc, and Bcc headers have nothing to do with determining where an email is sent to. But that the destination si determined in the SMTP negotiation through the RCPT command.
Imagine a 15 minute intermission while I run to the RFC Editor
Ah ha! I found it in Seciont 3.3 "Mail Transactions" of RFC 2821. Basically, there is an "envelope" which includes a MAIL command ("tells the SMTP-receiver that a new mail transaction is starting"), a RCPT command ("a forward-path identifying one recipient"), then a DATA command. The DATA command contains all information which will be sent to the address identified in the RCPT call. This data also includes the headers of the email (to, cc, bcc, etc.).
I may have dug deaper than necessary. If your scripts work, pay no attention to my bcc phobia.
Mark Hensler
If there is no answer on Google, then there is no question.
Abhishek Reddy posted this at 08:32 — 21st January 2004.
He has: 3,348 posts
Joined: Jul 2001
Mark, I didn't get a word of that.
Is this correct?
- MAIL command initiates a transaction
- RCPT does what? Identify a single primary recipient?
- DATA contains headers which are sent to the RCPT recipient? So one recipient gets all the headers?
At what point are the CC/BCC headers actually processed?
Mark Hensler posted this at 17:36 — 22nd January 2004.
He has: 4,048 posts
Joined: Aug 2000
Ok, so maybe I didn't deep enough for some of you.
From what I've read: yes, yes, and "that can't be true!" (disbelief)
I didn't read the entire RFC, but I think Appendix B is describing how to handle TO, CC, and BCC headers.
It is recommended that the UA provide its initial ("submission
client") MTA with an envelope separate from the message itself.
However, if the envelope is not supplied, SMTP commands SHOULD be
generated as follows:
1. Each recipient address from a TO, CC, or BCC header field SHOULD
be copied to a RCPT command (generating multiple message copies if
that is required for queuing or delivery). This includes any
addresses listed in a RFC 822 "group". Any BCC fields SHOULD then
be removed from the headers. Once this process is completed, the
remaining headers SHOULD be checked to verify that at least one
To:, Cc:, or Bcc: header remains. If none do, then a bcc: header
with no additional information SHOULD be inserted as specified in
[32].
Mark Hensler
If there is no answer on Google, then there is no question.
Mark Hensler posted this at 07:25 — 23rd January 2004.
He has: 4,048 posts
Joined: Aug 2000
If the body of the email is different for each recipient, then you need one mail() call per recipient.
Abhishek Reddy posted this at 09:59 — 23rd January 2004.
He has: 3,348 posts
Joined: Jul 2001
m3rajk, my math is indeed flawed, as I noted in one of my responses to Suzanne above:
I don't know how else to send in the case of a dynamic body. Is there no way to construct an array of messages in PHP and send it all to the MTA once and have it mail each to a different address?
How are mails sent to really large lists of addresses in "industrial" situations? I guess some kind of third party software is used?
Suzanne posted this at 14:29 — 23rd January 2004.
She has: 5,507 posts
Joined: Feb 2000
I know a number of ISPs will block huge lists of BCCs as well, or terminate them at 150 or some arbitrary number.
I'm also leery of BCCs and somewhat guilty of emphasizing dynamic content so I don't have to deal with them...
Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.