1

i use the following code to send mail with PHPMailer.It sends the emails to the recipients from db ,but it sends many emails to them.I want to send them only 1 with the related records in the HTML Table for each user.eg. if there are 5 records returned for a user then it sends 5 emails to the user with 1 record inside. Also,i don't want to use the try and catch commands the default PHPMailer script uses,but while ...

How can i change it to do what i want? Thank you.

<?php
$stmt = sqlsrv_query( $conn, $sql );   

$rows = array();
while($row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC)){

$rows[] = $row; 

//foreach ($result as $row) {
try {


    $mail->addAddress($row['email']);
} 
   catch (Exception $e) {
    echo 'Invalid address skipped: ' . htmlspecialchars($row['email']) . '<br>';
    continue;
}

try {
    $body = 'Hi: '. $row['first'] .' '. $row['last'] .'<br>';
    $body .=  '<table border="1"><tr><th>Username</th><th>Day</th><th>Date</th></tr><th>Action</th>';

    $body .= '<tr><td>';         
    $body .= $row['username'] . '</td><td>'; 
    $body .= $row['day'] . '</td><td>';  
    $body .= $row['date'] . '</td><td>';                        
    $body .= $row['action'] . '</td></tr>';
    $body .= '</table>';      

    $mail->msgHTML($body);

    $mail->send();
    echo 'Message sent to :' . htmlspecialchars($row['last']) . ' '. htmlspecialchars($row['first']) . '(' . htmlspecialchars($row['email']) . ')<br>';


} catch (Exception $e) {
    echo 'Mailer Error (' . htmlspecialchars($row['email']) . ') ' . $mail->ErrorInfo . '<br>';
    $mail->smtp->reset();
}

$mail->clearAddresses();
$mail->clearAttachments();
 }
?>
3
  • We kind of need to see your SQL query, but it sounds like each of those "records" you mention are a result row, so that's why you're getting the behavior you are. Commented Oct 29, 2019 at 12:47
  • Your query more than likely needs to GROUP BY the user id. Commented Oct 29, 2019 at 12:50
  • $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC returns all the records for all users.You mean to GROUP BY in the SQL Statement?I think it needs ane more loop inside the while command. Commented Oct 29, 2019 at 12:58

2 Answers 2

1

is this what you mean? send all results to each person in result set only once?

$stmt = sqlsrv_query( $conn, $sql );   

$rows = array();
$body = '<table border="1"><tr><th>Username</th><th>Day</th><th>Date</th></tr><th>Action</th>';

while($row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC)){

  $rows[] = $row; 
  $name = $row['first'] .' '. $row['last'];

  $body .= '<tr><td>';         
  $body .= $row['username'] . '</td><td>'; 
  $body .= $row['day'] . '</td><td>';  
  $body .= $row['date'] . '</td><td>';                        
  $body .= $row['action'] . '</td></tr>';


  $mail->addAddress($row['email'], $name);

}
$body .= '</table>'; 
$mail->msgHTML($body);

$mail->send();

Here is an example of the double while loops. $sql = select all the people & email addresses within your timeframe or other section criteria

$stmt = sqlsrv_query( $conn, $sql );  
while($row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC)){

  $name = $row['first'] .' '. $row['last'];
  $email = $row['email'];
  $body = '<table border="1"><tr><th>Username</th><th>Day</th><th>Date</th></tr><th>Action</th>';

  // now get this person's messages

  $sql2 = "SELECT username, day, date, action from Message WHERE name = $row['name']";

  $stmt2 = sqlsrv_query( $conn, $sql2 );  
  while($row2 = sqlsrv_fetch_array( $stmt2, SQLSRV_FETCH_ASSOC)){
    $body .= '<tr><td>';         
    $body .= $row['username'] . '</td><td>'; 
    $body .= $row['day'] . '</td><td>';  
    $body .= $row['date'] . '</td><td>';                        
    $body .= $row['action'] . '</td></tr>';
  }
  $body .= '</table>';

  // at this point you can create the phpmailer add the single email address & message body, and send the email

}

OK, here is something you can try to reorganize the results. You can replace the $testing array with your SQL result set. Using two foreach loops you can reorganize it into a multidimensional array $names and then loop thru that to send your emails.

$test1 = array('name'=>'mike','email'=>'mike@mike','day'=>'monday','action'=>'acrtion1');
$test2 = array('name'=>'mike','email'=>'mike@mike','day'=>'tuesday','action'=>'acrtion2');
$test3 = array('name'=>'mike','email'=>'mike@mike','day'=>'wedday','action'=>'acrtion3');

$test4 = array('name'=>'dave','email'=>'dave@mike','day'=>'monday','action'=>'acrtion1');
$test5 = array('name'=>'dave','email'=>'dave@mike','day'=>'tuesday','action'=>'acrtion2');
$test6 = array('name'=>'dave','email'=>'dave@mike','day'=>'wedday','action'=>'acrtion3');

$test7 = array('name'=>'tom','email'=>'tom@mike','day'=>'monday','action'=>'acrtion1');
$test8 = array('name'=>'tom','email'=>'tom@mike','day'=>'tuesday','action'=>'acrtion2');
$test9 = array('name'=>'tom','email'=>'tom@mike','day'=>'wedday','action'=>'acrtion3');

$testing = array($test1,$test2,$test3,$test4,$test5,$test6,$test7,$test8,$test9);

$names = array();

foreach($testing as $test){
    $names[$test['name']][] = $test;
}

print_r($names);

foreach($names as $name=>$records){
    echo "<p>email $name";
    foreach($records as $record){
        // this is where you can construct the email body for current $name
        echo "<p>".$record['email']." ".$record['day']." ".$record['action'];
    }
    // now send the email to current $name
}
Sign up to request clarification or add additional context in comments.

5 Comments

Let's say it returns 90 records (30 for each user).I want to send 3 emails (one for each user) with 30 records in the HTML Table.
ok, the first while or foreach loop should select each of the users, and the next one should select the records for that user and build the email body table. then send the email to that user.
I don't understand how to write the 2nd loop.
its hard to explain without seeing your sql, since there are several ways to accomplish the same thing here. I will post another answer
My sql returns the following rsult.The email has to be GROUPED BY??? Username email Day Date Action Mike mike@... wed … Action 1 Mike mike@... fri …. Action 2 Mike mike@... sat … Action 3 John john@... Fri … Action 2 John john@... Mon … Action 1 Maria maria@... Mon … Action 2 Maria maria@... Sat .. Action 3
0

My sql returns the following result.The 'email' has to be GROUPED BY???

enter image description here

2 Comments

I cant debug sql if I cant see it
You don't need to debug anything in SQL.I posted the SQL result.I don't know how to use the foreach (email loop) in my example.I want to send 1 email/user and inside the email to include the records from the 2nd loop for each user(eg. mike 3 records,John 2 records,Maria 2 records).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.