tags:

views:

379

answers:

6

I'm trying to send an e-mail to multiple e-mail address in my database. Here is my current code. It is only working when I specify a single e-mail address, however, I need to have them query my database and send the e-mail to each e-mail address. Where am I going wrong here?

function sendmail($cat, $user) {
    require_once "Mail.php";
    $elist = mysql_query("SELECT cEmail FROM tblUsers WHERE cAlerts = 'All' AND cEAlerts = 'Yes' AND cPreferences LIKE '%$cat%';");
    $elist = mysql_fetch_array($elist);

    $from = "EMAIL ADDRESS";
    $to = $elist;
    $subject = "SUBJECT";
    $body = "BODY";

    $host = "smtp.domain.com";
    $username = "USERNAME";
    $password = "PASSWORD";

    $headers = array ('From' => $from,
    'To' => $to,
    'Subject' => $subject);
    $smtp = Mail::factory('smtp',
    array ('host' => $host,
    'auth' => true,
    'username' => $username,
    'password' => $password));

    $mail = $smtp->send($to, $headers, $body);
 }
+1  A: 

mysql_fetch_array fetches an array with entries corresponding to each of the columns of a single row of your table. In other words, here it's an array containing one user's cEmail column.

You need to fetch all the values into a single array before calling the mail functions. You could do it like this:

$dest = array();
while ($arr = mysql_fetch_array($elist)) {
   $dest[] = $arr['cEmail'];
}
Borealid
@Downvoter: Why? I think this is a fine solution. I concisely and accurately pointed out the problem with the given code, and presented a solution. If what you don't like is that it sends one email: the correct behavior is to use `$dest` with the BCC field. That results in one call to the `$smtp->send` function, but still conceals each user's address from the others. Why would you **want** to authenticate and make a whole new connection and reauthenticate to the SMTP server for each of your hundred users?
Borealid
I agree with you Borealid.The other examples aren't wrong, but are bloated.Combining the addresses in one BCC-fields is way more gentle on the resources.
Deefjuh
+1  A: 

Try something like this but one point to note is that you should send emails individually ratehr than group all your email addresses in one "to" field. Other users might not like others seeing that. Maybe your smtp function breaks down the array, not sure :-|

function sendmail($cat, $user)
{ 
    require_once "Mail.php"; 
    $elist = mysql_query("SELECT cEmail FROM tblUsers WHERE cAlerts = 'All' AND cEAlerts = 'Yes' AND cPreferences LIKE '%$cat%';"); 

    $from = "EMAIL ADDRESS"; 
    $subject = "SUBJECT"; 
    $body = "BODY"; 

    $host = "smtp.domain.com"; 
    $username = "USERNAME"; 
    $password = "PASSWORD"; 

        if(mysql_num_rows($elist) > 0)
        {
            while($elist_result = mysql_fetch_array($elist))
            {
            $headers = array ('From' => $from, 
            'To' => $elist_result['cEmail'], 
            'Subject' => $subject); 
            $smtp = Mail::factory('smtp', 
            array ('host' => $host, 
            'auth' => true, 
            'username' => $username, 
            'password' => $password)); 

            $mail = $smtp->send($to, $headers, $body); 
            }
        }
 } 
PHPology
It still isn't sending an e-mail. I wrote it exactly how you have it above. I can't post the code in the comments because of character limitations
BigMike
just above the $headers variqble place this code:$to = $elist_result['cEmail'];
PHPology
PHPology - Thanks for your help. Still not working. I have a feeling that the fetch_array is grabbing all of the e-mail addresses and putting them into the "To" field. However, for e-mails sent to multple recipients, there needs to be a comma separating the e-mail addresses. How would that be done?
BigMike
@BigMike: `implode(',', $array);` will join the array with commas. But according to http://pear.php.net/manual/en/package.mail.mail.send.php an array is fine for the destination. And please, see my answer. `fetch_array` does *not* fetch all the email addresses in one call.
Borealid
Borealid - I'd like to try your answer. Where would this be inserted into my code?
BigMike
@Borealid - Also, is it possible to avoid the "To:" field having all e-mail addresses in there. I'd prefer to avoid sending everyone eachothers e-mail addresses. I noticed you mentioned using BCC, however, if possible, it'd be nice to have each individual e-mail address in the To:
BigMike
@BigMike: If you want each person to have their own address in the 'To' field, you need to send a separate email per recipient. Sorry. If you're doing that, just use PHPology's answer, changing his `$to` in the `smtp->send` to `$elist_result['cEmail']` (he has a small error in his code). I would also advise moving the creation of the factory (`$smtp = Mail::factory`) *outside* of the while loop; that way, you won't reauthenticate to the server for each email you send. You should probably also check to make sure the SMTP login works - otherwise you'll never know your email wasn't delivered!
Borealid
Awesome, works like a charm now. Thanks to you both!
BigMike
A: 

I learned to this from one of the examples in the book I am learning PHP from, Head First PHP & MySQL.

What you can do is send each e-mail individually, but simultaneously, through a while loop. With a mysqli_query selecting the e-mails, make a while loop that goes through my

while ($row_data = mysqli_fetch_array($your_query_in_a_variable)) {

    // Then you will set your variables for the e-mail using the data 
    // from the array.

    $from = '[email protected]';
    $to = $row_data['email']; // The column where your e-mail was stored.
    $subject = 'Open Me!';
    $msg = 'Hello world!';
    mail($to, $msg, $from);
}

I hope that is clear. You basically just call the rows you want in your query, then use mysqli_fetch_array, which goes through each row every time it is called (someone correct me, if wrong) and will exit when there are no more rows left that were called.

Tarik
A: 

My suggestion would be use the php mail() function and set the smtp server parameters in your php.ini file.

Then all you have to do is query your db, pull the first record out as your to address and then loop through the result set and put each email address into an array. Then just use the join function to join the array with commas and use it as the BCC for the header string.

Here is what I would use if possible. I've included a couple notes as //comments

function sendmail($cat, $user) {

    $result = mysql_query("SELECT cEmail FROM tblUsers WHERE cAlerts = 'All' AND cEAlerts = 'Yes' AND cPreferences LIKE '%$cat%';");

    //pull out first email as the to address
    $to = mysql_fetch_array($result);

    //create array to store all the emails
    $elist = array();

    //loop through and put each email into an array
    // you might be able to skip this altogether if you can just join $result
    // but I'm to lazy to investigate what all is being returned 
    while($row = mysql_fetch_assoc($result)){
        $elist[] = $row['cEmail'];
    }

    //join the emails into a comma separated string
    $bcc = join($elist, ",");

    $from = "EMAIL ADDRESS";
    $subject = "SUBJECT";
    $body = "BODY";

    $headers  = "From: ". $from ."\r\n";
    $headers  .="BCC: ". $bcc ."\r\n";

    mail($to, $subject, $body, $headers);
}

Hopefully this is useful information.. Feel free to pick it apart and use whatever you may need, like if you can use part to implement your Mail class.

Kelly Copley
A: 

You schould not use the php mail() function. It is dead slow because it does a full connect to the smtp server every single mail you send.
A good Mail library such as Zend_Mail connects only once and delivers the mails in one batch to the smtp server.
You should also not send all your mails via a long BCC-Line. At least if you want your email not marked as spam (See this Question and this Blog-Entry by Jeff).

<?php
function sendmail($cat, $user) {
    // Setup mailer
    require_once "Mail.php";

    $smtp = Mail::factory('smtp', array(
        'host'     => "smtp.domain.com";
        'auth'     => true,
        'username' => "USERNAME";
        'password' => "PASSWORD";
    ));

    // ALWAYS escape your variables!
    $query = sprintf("SELECT cEmail FROM tblUsers WHERE cAlerts = 'All' AND cEAlerts = 'Yes' AND cPreferences LIKE '%s'",
            mysql_real_escape_string($cat),

    // submit the query
    $result = mysql_query($query);

    // iterate over each row
    while ($row = mysql_fetch_assoc($result)) {
        $from    = "EMAIL ADDRESS";
        $to      = $row['cEmail'];
        $subject = "SUBJECT";
        $body    = "BODY";

        $headers = array(
            'From'    => $from,
            'To'      => $to,
            'Subject' => $subject
        );

        // Send mail with individual to-address via smtp 
        $mail = $smtp->send($to, $headers, $body);
    }
}
Benjamin Cremer
A: 

Hey BigMike,

Use this code to resolve your problem. I hope this will really help You out.

  //Connect to database
  mysql_connect("localhost","user","password") or die(mysql_error());
  mysql_select_db("db") or die(mysql_error()); 
  $sql = "SELECT email FROM members";  
  $res = mysql_query($sql) or die(mysql_error());
  while($row = mysql_fetch_assoc($res) )   
  {  
  $area .= $row['email']. ", ";
  }
    // read the list of emails from the file.
   $email_list = explode(',', $area);
  // count how many emails there are.
  $total_emails = count($email_list);
  // go through the list and trim off the newline character.
  for ($counter=0; $counter<$total_emails; $counter++)
  {
  $email_list[$counter] = trim($email_list[$counter]);
   }
  $to = $email_list;
  echo $to;

I hope you will make you out from the Problem. All the Best.

Rahul Patil