View Full Version : How to use php to send multiple emails at a time
On a website users can select categories of what information they want to receive from the various members, ie. if they select category 'Flowers', their request is emailed only to members in the Flowers category who can then respond directly to the user.
I know how to:
SELECT email FROM members WHERE category = 'Flowers';
but what is the best way to mail an email message using php to all the email addresses that are listed in the result?
And what if they select more than one category?
Thanks! e :)
thetestingsite
06-25-2009, 02:03 AM
Something like this perhaps? Change $_POST to $_GET if needed.
<?php
include('db_connect.php'); //connect to your db
if (isset($_POST['categories'])) { //make the checkmarks with name categories[]
foreach ($_POST['categories'] as $cat) {
$email_query = mysql_query("SELECT email FROM members WHERE `category` = '" . $cat . "'");
if (mysql_num_rows($email_query)) {
while ($email = mysql_fetch_array($email_query)) {
mail($email, 'Subject','Message Goes Here', "From: <noreply@domain.com>");
}
}
}
}
?>
This is just a basic script for you to learn from. Let me know if you need any more help with this.
Hope this helps.
Dear TestingSite: It's great to hear from you!! I was wondering how you were doing. I have to get some sleep right now but as soon as I wake up I'll make an attempt at this.
One question that occurs is how do I send myself a copy of the email only once?
Thanks for the help and I'm so glad you are still on the scene. :)
thetestingsite
06-25-2009, 05:10 PM
Just add the mail function just outside the foreach loop (before the last } ).
Hope this helps.
Sorry for the long delay but a million things happened in between and I am just able to get back to it now.
Here is the code that displays the categories in the form:
<input type="checkbox" name="categories[]" value="'.$row['cat_id'].'">' .$row['category']
Here is the code adapted from your code above:
$subject2 = "Maui Wedding Club Information Request";
$headers2 = "From: Maui Wedding Club <noreply@mauiweddingclub.com>\n";
include_once('db-connect.php');
if (isset($_POST['categories'])) { //make the checkmarks with name categories[]
foreach ($_POST['categories'] as $cat) {
$email_query = mysql_query("SELECT email FROM members WHERE member_id IN(SELECT member_id FROM membercat WHERE `cat_id` = '" . $cat . "'"));
if (mysql_num_rows($email_query)) {
while ($to_member = mysql_fetch_array($email_query)) {
mail($to_member, $subject2, $body2, $headers2);
}//end while
}//endif
}//end foreach
mail(info@mauiweddingclub.com, $subject2, $body2, $headers2);
}//endif
1) Is there a way to test the mailing without sending out any messages but still showing me where the messages would have been sent and what they would look like?
2) I suspect there will be a problem with the value of $cat which needs to be equal to the cat_id (an integer) but it looks as if it would be cat_id joined with category name. The membercat table has only 2 fields: member_id and cat_id so category description is not in that table.
3) When you click Reply to a noreply@domain.com address, does it always let you know immediately that the message cannot go? I find with forms, people often Reply instead of clicking on the client's email link.
As soon as I get this form working I can launch the site, so I am very eager. Thanks for any assistance. Mahalo!
JShor
09-21-2009, 07:28 PM
You could just echo all of the inputted variables, wouldn't that work?
That way, it shows what the email would've looked like.
echo $body2;
:)
djr33
09-22-2009, 02:41 AM
In general, PHP emails are like regular emails-- you can send it to as many people as you want using the standard format (I think it's just a comma, but look that up to be sure).
So, basically all you need to do is gather a link however you'd like and then put it in the mail() function. You can use cc and bcc as well, if you'd like. The documentation is all at php.net.
For what you want specifically, though, you'll find explode() and implode() useful (for getting the information out of the database into an array, then back into a list form separated by commas), and you can just use arrays-- get as many lists as arrays as you want, then merge the arrays and you can sort/delete duplicates easily using the basic array functions (see php.net for that, too).
If you've already got what you need from above, then that's fine-- if not, here's some more to give an idea at how you can approach things in general.
Dear JShor:
You're right, but I was able to see what it looked like anyway because I was able to get it to send to me even though it wouldn't send to anyone from a category. So I have the email looking the way I want now. But these lines don't work..
if (mysql_num_rows($email_query)) {
while ($to_member = mysql_fetch_array($email_query)) {
mail($to_member, $subject2, $body2, $headers2);
}//end while
}//endif
I've never seen msysql_num_rows used like that... is that a proper command?
Back to the drawing board. :)
Dear Daniel:
I like the approach you are suggesting. I'm heading to php.net now to read up on implode/explode. I have a few gaps in my understanding about arrays and loops. I'm embarrassed to be labeled 'Senior Coder' when I'm just an amateur who asks a lot of questions. Thanks for your help. e :)
djr33
09-23-2009, 12:33 AM
Not a problem. Arrays and loops can get confusing (especially when you're doing a lot of layers on a complex project), but implode and explode are very easy. The only trouble with them is that they don't always work for everything you need to do-- but if they do it's a fast and efficient way to process lists. But also don't be afraid to get into arrays and loops at some point because they are very useful and once you understand how they work it will open a lot of possibilities for you.
Not a problem for you maybe, but I have spent hours on this already and have gone from getting the first email address only to getting a blank page. I am retrogressing!
Is there an example of how to do this somewhere? I am not bad at modifying code when I see how it is supposed to be done, but I am not good at blazing trail. Today is my birthday... can someone please give me a break and show me explicitly how to do this? It's only a couple of lines of code I am having trouble with. Please! Mahalo, e :)
thetestingsite
09-23-2009, 02:09 AM
Happy B-day and sorry I have not been able to post a response to this, but I have been extremely busy with 2 full time jobs, going to school, some freelance work, and other things that have just taken up my time completely. What exactly are you trying to accomplish with this? Just seeing where the emails will be going or what? I've modified the code a little, so see if this works for you.
if (mysql_num_rows($email_query)) {
while ($to_member = mysql_fetch_array($email_query)) {
mail($to_member['email'], $subject2, $body2, $headers2);
//echo $to_member['email'].'<br>'; /* DEBUGGING */
/*Uncomment the above and comment out the mail function to debug code */
}//end while
}//endif
Hope this helps.
Dear thetestingsite:
Thanks a million!! That worked. I had been using print_r($email_query); to try to debug and it listed only one email address so I thought it wasn't working. Not sure if it was or not. It makes me crazy that one little word can consume so many hours of my time getting nowhere. Thanks for putting me out of my misery ... the best birthday present I can imagine at this point! :)
I did make the site live but don't feel 100% confident that the form is working as intended. A new mystery is that the emails that get sent have the "From: " address as the hosting account username@server#.hostname.com which is a considerable security risk. I have the "From:" defined in the headers but it is not using it. This seems to be a default return address. Any idea why this would be happening and how to fix it?
Sorry to take up your time when you are so busy, but I love you for helping. e :)
forum_amnesiac
09-23-2009, 06:33 AM
Happy belated birthday.
The explode() function is very easy to use, it splits up the string, as long as you have been consistent with your separator, and creates an array with the string split into the various elements.
Here is a link to page that explains it:
http://www.toknowmore.net/e/1/php/php-explode-function.php
there is also an explanation of implode():
http://www.toknowmore.net/e/1/php/php-implode-function.php
Both of these links have examples that you can modify
Salut
Thanks for the links. So is this correct? ...as Daniel suggested above, instead of using a while loop, I could take the array of email addresses and use implode to create one long list separated by commas and then use just one mail command?
$new_array=array($email_array);
$newstring=implode(",",$new_array);
mail($newstring, $subject2, $body2, $headers2);
Which method is the most economical use of the server resources? And is there any downside to having an indeterminate number of email addresses in the "To:" field? ie. is there a built-in php limit for one command other than a probable limit on number of emails per hour by the host?
Even though it may already be working, I'd like to learn the best practices way of solving this problem so that the next time I have to do something similar, I can build on it. Has anyone tried both ways and come up with a determination? Thanks.
djr33
09-23-2009, 11:45 PM
PHP emails are configured on your server, sometimes beyond what you can change in the PHP code itself-- your host may have set it up to automatically use that as the from email, in which case there isn't much you can do. I'd look at their FAQs to see if they explain a bit more. That will vary by host, and there may be some workarounds, like perhaps looking into php.ini (the configuration file for PHP), because it might be a default in that-- IF you have access to the file, and be careful because that could seriously change settings you don't want to mess with.
As for implode/explode, you're on the right track, but here's a basic example you can work from:
$emails = "1@1.1, 2@2.2, 3@3.3, ...";
$emails = explode (', ',$emails); //note the space after the comma
sort($emails); //arranges alphabetically-- you can do other things, but just an example
$emails = implode(', ',$emails);
mail($emails,.....);
What you have above is a little confusing, maybe because there is no code before it.
From what I can tell, though, it looks like you are using too many layers of an array--
You are putting the $array within array($array), on your first line.
Remember that arrays are basically lists, and that you are making a list of a list, so now you have a one item array consisting of an array. That list item then has a list inside it, but you don't need to have it so embedded.
Once something is an array, it's just like a normal variable.
$ar = array(1,2,3);
$ar2 = $ar; //not array($ar);
$ar==$ar2; //TRUE
So: $new_array=array($email_array);
should be: $new_array=$email_array;
Or, you may not need "new_array" at all.
Hope this helps.
Dear Daniel: I was able to solve the problem of the From: address by creating a forwarder BUT ever since I did that, my code stopped working. It shouldn't have anything to do with it but now it doesn't send out any emails. I successfully used implode to create a list of the categories but now the mail function doesn't work. So I have tried the method you suggested. Does this look right? Not sure why you have to explode them implode but...
$emails = mysql_query("SELECT email FROM members WHERE `cat_id` = '".$cat."') ");
if (mysql_num_rows($emails)) {
$emails = explode (', ',$emails);
$emails_nodups = array_unique($emails);
$emails_nodups = implode(', ',$emails_nodups);
mail($emails_nodups, $subject2, $body2, $headers2);
}//endif
Thanks for your help. e :)
djr33
09-26-2009, 02:52 AM
implode(explode(X)) == X, so you do not need to use them.
However, using them gives you an array in the middle and that way you can use the array_unique function, which is what you wanted before.
The code looks fine, assuming $subject2, $body2, $headers2 are all ok.
You could test what values they are getting by changing "mail(" to "print_r(", and you'll print out all the data send through the mail function to see what's actually being sent.
Dear D: I got this error message when trying to test with print_r...
Warning: print_r() expects at most 2 parameters, 4 given...
Then I removed all but $emails and got this message...
Resource id #3Resource id #4Resource id #5Resource id #6
Then I tried making a while loop with an echo command and got this...
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in
I have The Testingsite's method now working perfectly (thanks D!), but I wanted to compare this method. I just can't get it to list the array so I can test it. Is there any difference in efficiency between sending the emails one by one with a loop compared to sending to all the addresses at once using one mail command?
Thanks for your help. I always like to learn the best way. e :)
djr33
09-27-2009, 06:11 AM
It's more efficient to send them all at once, but it's not going to crash the server or anything.
Sorry about that-- you do just need one input for print_r.... I forgot about that. However, yes, just use $emails.
I'm not sure why you are getting "resource_id...". That is what happens when you reference a mysql query result directly, rather than properly extracting its contents. In other words, you need to do a while(mysql_fetch... loop first, getting all of the emails ready, then do the code above. I'm not exactly sure where that went wrong in your code, but it definitely explains why it's not working to send anything. But the email code itself is probably fine-- the data just needs a bit of preparation first.
Powered by vBulletin® Version 4.2.2 Copyright © 2021 vBulletin Solutions, Inc. All rights reserved.