PHP mail() BCC - display only the end receivers address in To: header - php

I'm attempting to BCC to a list of subscribers from a database, using PHP mail(). Everything works, but I'm running into a problem that has troubled me all morning. I'm able to send the list with BCC, but are unable to append the receiving end email address to the deader "To:".
For example, I send the list to the following email addresses (test1#example.com, test2#example.com, and test3#example.com). Each email address receives an email and the other email addresses are hidden because of BCC.
My problem is that in the header, "To:" is displayed blank on all of the receiving ends of the list. That I understand and know that header won't display because I have only the BCC header within the outgoing message. I've attemted to for loop the process but I receive all of the emails, plus one for that address in one loop.
Here is my working code: The working code includes the loop that I attempted for solving the To: header. I'm able to send the email, though I receive all of the emails that were sent.
<?php
/*
Gathers the number of rows within the database. Used for the loop that displays the entire list in the BCC.
*/
session_start();
include_once '../dbconnect.php';
$result = mysql_query("SELECT * FROM news");
$num_rows = mysql_num_rows($result);
$rows = $num_rows;
/*
Requests the list from the database, please the list in a loop, displays the list only once, and places list in an operator.
*/
$result = mysql_query("SELECT * FROM `news`");
while($row = mysql_fetch_array( $result )) {
for ($x = 1; $x <= 1; $x++) {
$contacts.= "".$row['email'].",";
}
}
/*
ATTEMPT (It works... sort of): Sends mail to the list using BCC, displays the ONLY receivers email address in the To: header
*/
$result = mysql_query("SELECT * FROM `news`");
while($row = mysql_fetch_array( $result )) {
for ($x = 1; $x <= 1; $x++) {
$receiver= "".$row['email']."";
$to = "$receiver";
$subject = 'Test Email';
$headers = "From: example#example.com\r\n";
$headers .= "BCC: $contacts";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$message = '<html><body>';
$message .= '<h1 style="">Test Message</h1>';
$message .= '</body></html>';
mail($to,$subject, $message, $headers);
}
}
?>
My general thought was to loop, but I can't find a solution that actually solves this completely, by BBC to the list and displaying only the receiving ends email address in the To: header. Any thoughts or ideas?
Update with SMTP Server
I've been attempting to use the solution found in this thread and apply it to an SMTP server. Send the message using SendGrid was the ideal choice. I've come up with the below option, but the script only seems to send one message to one of the addresses in the database and not all the address.
<?php
require_once "Mail.php";
$sub = $_POST['subject'];
$ttl = $_POST['title'];
$img = $_POST['image'];
$bdy = $_POST['body'];
$lk = $_POST['link'];
mysql_connect("", "", "") or die(mysql_error()) ;
mysql_select_db("") or die(mysql_error()) ;
$result = mysql_query("SELECT `email` FROM news");
$num_rows = mysql_num_rows($result);
$receivers = array();
while ($row = mysql_fetch_array($result)) {
$receivers[] = $row['email'];
}
foreach ($receivers as $receiver) { }
$from = "test#example.com";
$to = $receiver;
$subject = $sub;
$mime = "1.0";
$ctype = "text/html; charset=ISO-8859-1";
$body = '
<html><body>
<p>Test Message!</p>
</body></html>
';
$host = "";
$port = "";
$username = "";
$password = "";
$headers = array ('From' => $from,
'To' => $to,
'Subject' => $subject,
'MIME-Version' => $mime ,
'Content-Type:' => $ctype);
$smtp = Mail::factory('smtp',
array ('host' => $host,
'port' => $port,
'auth' => true,
'username' => $username,
'password' => $password));
$mail = $smtp->send($to, $headers, $body);
if (PEAR::isError($mail)) {
echo("<p>" . $mail->getMessage() . "</p>");
} else {
echo("<p>Message successfully sent!</p>");
}
?>

The code includes some general improvements to your code. I have added inline comments to explain what I have done.
<?php
// General thing: If you do not need a session, do not start one ;)
session_start();
include_once '../dbconnect.php';
// Select only what you really need from the table. This saves you memory
// and it speeds up the query.
$result = mysql_query("SELECT `email` FROM news");
// You are not using these numbers in the script you showed us. I am just
// leaving them in here to show you, how you can reuse the "$result"
// variable without querying the database again.
$num_rows = mysql_num_rows($result);
// We are reusing the "$result" here without re-querying the database, which
// speeds the whole process up and takes load away from the database. We are
// storing all receivers in a dedicated variable, to reuse them later on.
$receivers = array();
while ($row = mysql_fetch_array($result)) {
$receivers[] = $row['email'];
}
// Now, instead of querying the database again, we are using our stored mail
// addresses in "$receivers" to send the emails one by one. We could have
// done this part in the "while" loop before, but I wanted to stay close to
// your code, so you would recognize it ;)
foreach ($receivers as $receiver) {
// I have removed the "for" loop here, because it runs only once. If a loop
// only runs once and you control all its input, you really do not need a
// loop at all (except some exceptions, just in case someone knows one^^).
// You can actually just put the value of $receiver in $to. PHP is pretty
// good at typecasting of scalar types (integers, strings etc.), so you do
// not need to worry about that.
$to = $receiver;
$subject = 'Test Email';
// I am putting the headers into an array and implode them later on. This
// way we can make sure that we are not forgetting the new line characters
// somewhere.
$headers = array(
"From: example#example.com",
"MIME-Version: 1.0",
"Content-Type: text/html; charset=ISO-8859-1",
// I have removed the "BCC" header here, because this loops send out an
// email to each user seperately. It is basically me sending an email to
// you. Afterwards I copy&paste all the content to another new mail and
// send it to another fella. You would never know that you both got the
// same mail ;)
);
$message = '<html><body>';
$message .= '<h1 style="">Test Message</h1>';
$message .= '</body></html>';
// Imploding the headers.
$imploded_headers = implode("\r\n", $headers);
mail($to, $subject, $message, $imploded_headers);
}
This code basically send out one email at a time. No one who receives such an email knows which email addresses the email went to.
As mentioned in the code, this snippet can be further optimized. Since email sending itself is a pretty difficult area, I would really suggest that you find some PHP library that bundles that whole thing and work with it. You can make so many mistakes with the whole email sending thing, that I would not run a script like that in production if you do not want to get marked as spam soon after.

Add \r\n to:
$headers .= "BCC: $contacts\r\n";
Each header must be on new line.

Related

how to send mails to multiple list of emails from a database using php

i am working on script to send a mail to a list of emails from my table using php
presently i run a query on the table and echo all the emails meeting such requirements from the sql query
sql="SELECT * FROM people WHERE status in('member','client')";
$result = mysql_query($sql)or die("Cannot query orders_products data" . mysql_error());
while($row=mysql_fetch_array($result)) {
$list = array();
$list[] = $row['Email'];
echo implode(",",$list);
$email = 'xxxxxxxxxxx';
$emailto = implode( "," ,$list );
$subject = "xxxxxxxxxxxxxxxx";
$headers = "From: $email";
$body .= ++$i.") ".$row['title'] ."\n\n";
}
$body .= "Regards\n\n";
$body .= "xxxxxxxxxxxxxxxxxx\n\n";
$send = mail($emailto, $subject, $body, $headers);
when i try passing these emails to a mail function snippet the mail sending fails.
Please what could i be doin wrong, i need help
Update :
$list[] = $row['Email'];
echo implode(",",$list);
all the emails are displayed
But without commas.
$emailto = implode( "," ,$list );
i use the same method of imploding the array of data gotten from
$list[] = $row['Email'];
By fail i just mean i was hoping since the emails got echoed using the implode it would all successfully pass the emails to $emailto and then send a mail to each of them.
So, what I think you're trying to do is to get the email address from your table where the user is either a member or a client. Then, you have a from address, subject, and a body. In addition, it looks like maybe you're trying to add to the body some unique information. Finally, I think you want to send an individual email to each user, separately.
You could modify your code to be like this:
<?php
$sql="SELECT * FROM people WHERE status in('member','client')";
$result = mysql_query($sql) or die("Cannot query orders_products data" . mysql_error());
$emailContent = 'xxxxxxxxxxx';
$emailSubject = 'xxxxxxxxxxx';
$body = 'xxxxxxxxxxxxxxx';
$headers = "From: from#email.com";
while ($row = mysql_fetch_array($result)) {
// optionally modify body here...?
$emailBody = $body .= $row['title']; // or whatever you're trying to do here...
// send email to each individual person
mail($row['Email'], $emailSubject, $emailBody, $headers);
}
I think this is how you'd modify your code to get it to do what you're asking.

Sending Mass Mail is too slow via PHP mail() function

I am trying to send mass mail via PHP mail() function but it is too slow. All the emails are fetched from database. Currently, I am performing this with Xampp (offline) with Sendmail. And right now in my database there are only 6 emails and it is taking 2 mins to complete sending all the mails. I am just worried about what what will happen when in production mode there will be thousands of users. A sample code is given below about what I am using. Is there any way of making it execute faster?
$from = (!empty($_POST['from']))?$_POST['from']:null;
$type = (!empty($_POST['type']))?$_POST['type']:null;
$to = (!empty($_POST['to']))?$_POST['to']:null;
$subject = (!empty($_POST['subject']))?$_POST['subject']:null;
$message = (!empty($_POST['message']))?$_POST['message']:null;
if($_POST){
$emails = $pdo->prepare("SELECT mem_email FROM members");
$emails-> execute();
$adminMail = $pdo->prepare("SELECT set_site_name, set_admin_support_mail FROM settings");
$adminMail-> execute();
$amf = $adminMail->fetch();
$headers = "From: ".$from." (".$amf['set_admin_support_mail'].")";
while($u = $emails->fetch()){
$sendTo = $u['mem_email']; // note the comma
mail($sendTo, $subject, $message, $headers);
}
}

php app mailing function

I'm having a problem using a mailing function in a php ecomm app I purchased from envato. The developer has a mailer function which is used to send emails from the website.
Function :
/* Send mail with custom templates:$template : E-mail template.$array : Variables for email template. $subject : E-mail Subject.$to : E-mail receiver.*/
function mailing($template,$array,$subject,$to) {
$cfg = DB::select('SELECT * FROM config WHERE id = 1')[0];
$array['url'] = url('');
$array['name'] = $cfg->name;
$array['address'] = nl2br($cfg->address);
$array['phone'] = $cfg->phone;
$array['email'] = $cfg->email;
// Get the template from the database
$message = DB::select("SELECT template FROM templates WHERE code = '".$template."'")[0]->template;
foreach ($array as $ind => $val) {
$message = str_replace("{{$ind}}",$val,$message);
}
$message = preg_replace('/\{\{(.*?)\}\}/is','',$message);
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
$headers .= 'From: '.$cfg->name.' <'.$cfg->email.'>'."\r\n";
mail($to,$subject,$message,$headers);
return true;
}
The email template is pulled from the db.
As part of the checkout process in the API.php file, the mailer function is used to email the order to the user with the follwing code:
// Send an email to customer
mailing(
'order',
array( 'buyer_name'=>$data['name'],
'buyer_email'=>$data['email'],
'buyer_fields'=>$email_fields,
'name'=>$this->cfg->name,
'address'=>$this->cfg->address,
'phone'=>$this->cfg->phone,
'products'=>$email_products,
'total'=>$total
),
'Order Confirmation #'.$order,
$data['email']
);
This is fine, however, I'm trying to get that to also send myself the email of the order as opposed to having to check the admin ux as is currently the way it works. Could anyone point me in the right direction ?
Many Thanks in advance.
The simple answer is to add another call to mail() an replace $to with your email address in the mailing() function.
But as this is probably used in more than one place in the app, it might be nice to add a parameter to this function that tells it to email to you as well as the intended recipient
function mailing($template,$array,$subject,$to, $toMe=false) {
// new parameter ^^^^^^^^^^^
$cfg = DB::select('SELECT * FROM config WHERE id = 1')[0];
$array['url'] = url('');
$array['name'] = $cfg->name;
$array['address'] = nl2br($cfg->address);
$array['phone'] = $cfg->phone;
$array['email'] = $cfg->email;
// Get the template from the database
$message = DB::select("SELECT template FROM templates WHERE code = '".$template."'")[0]->template;
foreach ($array as $ind => $val) {
$message = str_replace("{{$ind}}",$val,$message);
}
$message = preg_replace('/\{\{(.*?)\}\}/is','',$message);
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
$headers .= 'From: '.$cfg->name.' <'.$cfg->email.'>'."\r\n";
mail($to,$subject,$message,$headers);
// now mail yourself if $toMe is true
if ( $toMe !== false ) {
mail($toMe,$subject,$message,$headers);
}
return true;
}
Then anywhere in the app where it sends mail yo can add a request to get a copy of the email. BUT, if you dont add the new parameter, the mailing() function will act just as it did before.
// Send an email to customer
mailing(
'order',
array( 'buyer_name'=>$data['name'],
'buyer_email'=>$data['email'],
'buyer_fields'=>$email_fields,
'name'=>$this->cfg->name,
'address'=>$this->cfg->address,
'phone'=>$this->cfg->phone,
'products'=>$email_products,
'total'=>$total
),
'Order Confirmation #'.$order,
$data['email'],
'me#mymail.com' // new parameter added
);
Now none of the existing calls to mailing will be effected, because you used a default value in the function prototype, unless you add the extra parameter to the call to mailing but any of them you want to alter can be done easily, and as you specify the address when you want to get a copy, you can use any of your email addresses.
Just add another
mail($to,$subject,$message,$headers);
line and replace $to with your email. That's it.

Sending multiple CC's and BCCs with PHP PEAR MAIL

I have a project that I am working on at my job and I am using Pear's mailing. I need to use smtp because we need to be able to track everything from our mailserver. And users need to be able to log in before sending a company based email. We cannot use php's mail function fo this.
My problem is that I cant find any documentation on the net for sending CC and Bcc as well as sending multiple BCCs. It is very easy to do with php' mail funciton . All you do is add it to the $header variable like so
$headers .= 'Cc: birthdayarchive#example.com' . "\r\n";
$headers .= 'Bcc: birthdaycheck#example.com' . "\r\n";
This is my code for the php function where I use PEAR
function sender_mail($email,$subject,$mailmsg, $cc, $bcc){
include("Mail.php");
/* mail setup recipients, subject etc */
//DEFAULT VALUE OF FROM
$from = "noreply#addata.net";
//GET EMAIL OF USER
$result = mysql_query("SELECT email, email_pass FROM u_perinfo WHERE user_id = '$_SESSION[uid]'")
or die("There was an error when grabbing your email information");
if(mysql_num_rows($result) > 0){
$row = mysql_fetch_array($result);
if($row[0] != ''){
$from = $row[0];
}
$email_pass = $row[1];
}
$recipients = "$email";
$headers["From"] = "$from";
$headers["To"] = "$email";
$headers["Subject"] = $subject;
$headers["Cc"] = "$cc"; //Line added by Me to see if it works
$headers["Bcc"] = "$bcc"; //Line added by Me to see if it works
//$mailmsg = "Welcome to Addatareference.com! \r\n\r\nBelow is your unique login information. \r\n\r\n(Please do not share your login information.)$accountinfo";
/* SMTP server name, port, user/passwd */
$smtpinfo["host"] = "smtp.emailsrvr.com";
$smtpinfo["port"] = "25";
$smtpinfo["auth"] = true;
$smtpinfo["username"] = "$from";
$smtpinfo["password"] = "$email_pass";
/* Create the mail object using the Mail::factory method */
$mail_object =& Mail::factory("smtp", $smtpinfo);
/* Ok send mail */
$mail_object->send($recipients, $headers, $mailmsg);
}
I have been trying to find a solution to this with no real info coming back my way. If someone could help me out with this I would be greatly appreciated.
There is a problem with Bcc though when using the PEAR Mail function: Thunderbird displays the Bcc header, so the recipient is not hidden, which is the whole point of Bcc. It is also displayed in the To: header list (since you have to include the Bcc list in recipients).
Edit: SOLVED - I found from another site that the solution is just to include the Bcc list in the $recipients, and not in any of the headers. It works!
Thus:
$bcc = "foo#example.com";
$to = "bar#example.com";
$headers = array(..other stuff.., 'To' => $to, ..rest of header stuff); // No Bcc header!
$recipients = $to.", ".$bcc;
$mail = $smtp->send($recipients, $headers, $message);
Edit #2: Acknowledging my source - http://raamdev.com/2008/adding-cc-recipients-with-pear-mail/
Have you tried to add multiple addresses "," separated?
$headers['Cc'] = 'cc#example.com, bb#example.com, dd#ex.com';
This might work, according to line 218 in the source.
You just need to add all to, cc, bcc in $recipients variable. Header decides where to send.

How to send e-mail to multiple recipients from database query (PHP)

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);
}
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);
}
}
}
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'];
}
I had a similar issue while trying to loop though my recipients' database table with the aim of sending personalized PEAR emails to each recipient.
The problem I encountered was that the loop would cease after one iteration until I amended $recipients to just send the first item in the array, as illustrated in this code snippet. ($recipients is an array of IDs for recipients):
/*PEAR mail set-up code included here*/
for ($i = 0; $i < count($recipients); $i++) {
$sql_recipients = "SELECT * FROM $data_table WHERE id = $recipients[$i] ORDER BY id ASC ";
$res_recipients = mysqli_query($mysqli,$sql_recipients)
or die (mysqli_error($mysqli));
$recipients_info = mysqli_fetch_array($res_recipients);
$recip_id = $recipients_info['id'];
$recip_organisation = $recipients_info['organisation'];
$recip_fname = $recipients_info['fname'];
$recip_lname = $recipients_info['lname'];
$recip_email = $recipients_info['email'];
/*PEAR mail code here */
$recipients[0] = $recip_email;
$mail->send($recipients[0], $hdrs, $body);
}
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 = 'you#yoursite.com';
$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.
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.
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);
}
}
Use this code to resolve your problem.
//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;

Categories