Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 2.0.0

Bug #8047 Cc and Bcc handling
Submitted: 2006-06-28 06:46 UTC
From: ahayes at wcg dot net dot au Assigned:
Status: Bogus Package: Mail (version 1.1.10)
PHP Version: 5.1.4 OS: FC5
Roadmaps: (Not assigned)    
Subscription  


 [2006-06-28 06:46 UTC] ahayes at wcg dot net dot au (Alex Hayes)
Description: ------------ It seems as tho the Mail factory 'smtp' behaves a little differently to its cousins 'mail' and 'sendmail'. I realise that this could be the implementation of the sendmail program as I have recieved differing results on some servers, however at the very least it would be nice to have some clarification in the documentation. The problem lies in the handling of the Cc and Bcc headers. For example, with the 'mail' factory it will send the email out to those listed in the Cc and Bcc, 'smtp' does not. The reason for this I believe is because you must specify all the recipients in the 'recipients' parameter of the Mail_smtp::send() method. This is trivial, however if you are switching between mail factories a problem arises. Say for instance I do join up all my recipients (To, Cc & Bcc) for calls to Mail_mail::send() as I would have to for Mail_smtp::send(), Mail_mail::send() will cause those listed in the Cc and Bcc to be in the 'To' header when the email is delivered. So, either the 'recipient' param is just supposed to be those for the 'To' header, or there needs to be some modification of Mail_mail, however I would assume that this will be the harder of the two. A very simple fix (PHP5) for this would be as follows, however I am unsure if this breaks anything, or of the reason for this "bug" (if in fact it even is a bug and not a documentation issue). =============8<=============== class Mail_smtpfix extends Mail_smtp { function send($recipients, $headers, $body) { if(!empty($headers['Cc'])) { if(is_array($headers['Cc'])) { $headers['Cc'] = $this->parseRecipients($headers['Cc']);; } $recipients = is_array($recipients) ? array_merge($recipients, array($headers['Cc'])) : array($recipients, $headers['Cc']); } if(!empty($headers['Bcc'])) { if(!is_array($headers['Bcc'])) { $headers['Bcc'] = $this->parseRecipients($headers['Bcc']);; } $recipients = is_array($recipients) ? array_merge($recipients, array($headers['Bcc'])) : array($recipients, $headers['Bcc']); } return parent::send($recipients, $headers, $body); } } =============>8=============== Note that if this is not a bug with Mail_smtp then it means that the mail factories do not behave in the same manner, which, in my opinion, **kind of** breaks the factory based approach. Test script: --------------- <?php include('Mail.php'); include('Mail/mime.php'); $params['factory'] = 'smtp'; $params['options'] = array( 'host' => 'smtp.host.com' ); $params['crlf'] = "\r\n"; $params['hdrs'] = array( 'To' => 'example@example.com', 'From' => 'me@example.com', 'Cc' => 'friends@example.com', 'Subject' => 'Test Message' ); $text = "Parameter Information: \n\n" . var_export($params, true); $mime = new Mail_mime($params['crlf']); $mime->setTXTBody($text); $body = $mime->get(); $hdrs = $mime->headers($params['hdrs']); $mail =& Mail::factory($params['factory'], $params['options']); $result = $mail->send( $params['hdrs']['To'], $hdrs, $body ); var_dump($result); Expected result: ---------------- The email should arrive to both the To and the Cc recipients. Actual result: -------------- The email only arrives to the To.

Comments

 [2006-06-28 18:13 UTC] chagenbu at php dot net (Chuck Hagenbuch)
The fact that PHP's mail: function delivers to cc: and bcc: header addresses is because it doesn't have a proper recipients parameter. With Mail, you *must* specify the envelope recipients - anyone who should get the message - in the $recipients parameter. Headers are headers - they don't mean _anything_ about who the message should be delivered to.
 [2006-06-28 22:57 UTC] ahayes at wcg dot net dot au
So, then is it possible that Mail_mail can be modified, so that when it talks to PHP's mail it behaves properly? Or is this really something that should (but probably will not) be addressed with the mail function itself? My guess is the later.
 [2007-02-28 20:29 UTC] tkamin at argotinc dot com (Todd Kamin)
So, basically, the PEAR Mail class doesn't support Cc: or Bcc: functionality.
 [2007-03-04 01:03 UTC] testing83 at verizon dot net (testing83)
I am unable to use the Mail Factory with smtp to send a blind carbon copy (Bcc). The problem I am having is discussed in this bug report. If I don't place the bcc email address in the list of recipients then the email does not get sent to the bcc email address. If I place the bcc email address in the list of recipients then the email is sent but it not blind to the other recipients. I would really like to know how I can send an email which includes a bcc using the Mail Factory with an smtp mail server. Thank you.
 [2007-04-20 13:59 UTC] mmoch (Michael Moch)
FWIW, I was having the exact same issue using the sendmail factory. I wanted to see how other PHP mail software handled this issue, so I downloaded PHPMailer. The author of that package passes arguments "-oi -t" to sendmail. On our servers, sendmail is a symlink to exim. Looking at the manpage for exim, I noticed that -oi specifies that a single '.' by itself should not terminate a locally generated email message. The -t option specifies that exim should build the recipients list from the 'To', 'Cc', and 'Bcc' headers rather than from the arguments list. When we make our call, we don't pass any arguments to sendmail. On a hunch, instead of just calling $mail =& Mail::factory( 'sendmail', array( 'sendmail_path' => '/path/to/sendmail' ) ); I added the sendmail_args param like so: $mail =& Mail::factory( 'sendmail', array( 'sendmail_path' => '/path/to/sendmail', 'sendmail_args' => '-oi -t' ) ); It seems to have solved the issue for me.
 [2007-07-02 10:35 UTC] simeruk (Simon Bakowski)
Hello all, Has that problem been solved in any way or at least is there any sort of official confirmation from class owner as to expected behavior of that class? I was also having and still have the same problem - just browsing for some reliable solution but would prefer to use rather smtp method instead of any other (like mail for example). Thanks. Simon
 [2007-07-06 15:22 UTC] arminf (Armin Frey)
It seems that the Recipients decides where to send the e-mail and the headers decide how to display it. The simple solution is that you add all the addresses to $recipients. Here is the code I used: $to = 'to@example.com'; $cc = 'cc@example.com'; $recipients = $to.", ".$cc; $headers['From'] = 'from@example.com'; $headers['To'] = $to; $headers['Subject'] = 'Test message'; $headers['Cc'] = 'cc@example.com'; $headers['Reply-To'] = 'from@example.com'; $send = $mail->send($recipients, $headers, $body);
 [2009-12-09 01:15 UTC] fixedd (Jeremy Logan)
Two years later... any info?
 [2010-01-28 20:23 UTC] moiseev (Igor Moiseev)
@simeruk: Thanks a lot! Works like a charm! @fixed: see post of simeruk @Pear::Mail group: thank you for the perfect class
 [2010-03-24 12:04 UTC] brozra (Russ Alexander)
Simeruk's solution only works for ONE BCC email address. It won't work for multiples. Here's a solution that I came up with. It seems to work just fine with PHP 5.3. It may not be pretty or the shortest code, but dangit, it works! The same principles can also be applied for CC. ENJOY! <?php /* One odd thing I noticed is that sometimes you have to copy the "Net" folder from the "Php" folder to the directory where you are using your script. I don't know if that's the case for everyone, but I have had to do it on all my sites on my hosting server. Can't get it working? Send me an e-mail: russ.alexander@brozra.com This solutions is provided AS-IS. If you make modifications, then you are on your own! */ include('Mail.php'); // Must have SMTP PEAR modules installed on your server $message = 'Message'; $subject = 'Subject'; /* Recommend that you use an e-mail address from the SAME domain as your host or it will be marked as SPAM / JUNK. */ $from = "from_email@domain.com"; // Specify the return address here - yes, you can use a 'noreply' address if you want. $to = "to_email@domain.com"; // Specify the main recipient here - yes, you can use a 'noreply' address if you want. /* For some reason, this was the ONLY way I could get PEAR SMTP to send BCC emails to all the email addresses with one variable If you are pulling from a database, then use the following code or similar: $sql = "SELECT `email_address` FROM `table` WHERE value='whatever'"; $result = mysql_query($sql); while ($line = mysql_fetch_array($result,MYSQL_ASSOC)) { extract($line); $count=0; if ($count > 0) { $emails .= ', '; } $bcc_emails .= $line['email_address']; $count++; } */ $bcc_emails = "email_one@domain.com, "; // Use the trailing comma and space after the email address! $bcc_emails .= "email_two@domain.com, "; // Use the trailing comma and space after the email address! $bcc_emails .= "email_three@domain.com"; // No trailing comma. It is kind of like an array, but not /* Combine the TO and BCC here - PEAR SMTP must have all e-mails as the main recipient. The KEY => VALUE assignments here are understood by the PEAR module and will route them appropriately. */ $smtp_to = array ( 'To' => $to, 'Bcc' => $bcc_emails); /* Set server information & SMTP function for PEAR SMTP */ $host = "your_mail_host"; /* Best way to avoid using your own personal e-mail here is to setup another e-mail specifically for this purpose like smtp_verify@domain.com -- don't forget to discard all incoming e-mails for that account too! */ $username = "username (or) email for SMTP verification"; $password = "password"; /* The following is not necessary unless you want to send HTML formatted */ $content_type = "text/html; charset=iso-8859-1"; $mime_ver = "1.0"; /* Establish the connection for SMTP */ $smtp = Mail::factory('smtp', array ('host' => $host, 'auth' => true, 'username' => $username, 'password' => $password)); /* Generate the headers. No need to include BCC here! If you do, then the BCC's aren't blind at all and can be viewed by recipients if they dig deep enough. The beauty of it though is that the e-mails will still be sent and the only recipient to show will be the TO from the array in $smtp_to!*/ $headers = array( 'From' => $from, 'Return-Path' => $from, 'To' => $to, 'Subject' => $subject, 'Content-type' => $content_type, 'MIME-Version' => $mime_ver); /* Finally, send the e-mail */ $send_emails = $smtp->send($smtp_to, $headers, $message); if (PEAR::isError($send_emails)) { echo $mail->getMessage(); echo "Failed to send message!"; } else { echo "Success. Message sent!"} ?>
 [2010-10-01 02:39 UTC] slant53 (Steve Hughes)
I tried brozra's solution but the bcc addresses are showing up in the To field of all recipients. I'm at PHP 4.4.9 and Pear Mail 1.1.4 but I can't upgrade (my host company controls this). Has anyone tried this on an earlier php or have a different solution.
 [2010-11-10 12:10 UTC] brozra (Russ Alexander)
Switch to a hosting company that has the latest PEAR modules. That would probably be the easiest solution. No point in beating yourself up on trying to find a solution for outdated software. Shameless company plug follows: We've got all the latest PEAR, Ruby on Rails, PHP, cPanel, you name it. We update as soon as a stable release is available for everything. http://www.brozra.com
 [2010-11-25 18:07 UTC] mcnaldo (Mikael Svensson)
Thank you Brozra, that was a great tip! Specifically the part about the PEAR module understanding if you put the To, Cc and Bcc addresses into an array: /* Combine the TO and BCC here - PEAR SMTP must have all e-mails as the main recipient. The KEY => VALUE assignments here are understood by the PEAR module and will route them appropriately. */ $smtp_to = array ( 'To' => $to, 'Bcc' => $bcc_emails); Just to make it clear. The header part only affects how the message looks, not where it gets sent. The send part specifies where to send the messages (and also affects what shows up in the 'To' part of the message).
 [2011-04-19 20:48 UTC] cami (Carsten Milkau)
This IS (or at least most of it is) a bug in PEAR Mail_mail. PHP mail() manual explicitly states that CC/BCC recipients should be specified in extra headers ONLY, not in the recipients argument. in contrast Mail::send() manual explicitly states that ALL envelope recipients (including CC/BCC) must be listed in the recipients parameter. Thus, Mail_mail MUST filter out all envelope recipients that are listed in a CC/BCC header before calling mail(). This is a mail() limitation that can only be worked around by inspecting message headers. HOWEVER the fact that some mail() backends or php patches (like suhosin) ignore the CC/BCC headers passed to mail() is obviously an error in mail() and not in PEAR Mail_mail. Please fix the first part as switching the mailer backend must not change mail::send() semantics! Currently, one must manually detect the backend and filter CC/BCC from recipients if (and only if) it is Mail_mail.
 [2012-01-16 16:36 UTC] eis_ltd (Tim Eveleigh)
Have you tried using $message->addTo, $message->addCc, etc.? These made the difference for me.
 [2012-07-18 21:47 UTC] fgabrieli (Fernando Gabrieli)
Hi all, the following worked for me (based on brozra solution): $headers = array('MIME-Version' => '1.0', 'Reply-to' => $this->getFrom(), 'To' => $this->to, 'Content-type' => 'text/html; charset=ISO-8859-1', 'Content-Transfer-Encoding' => 'base64'); $smtpTo = array('To' => $this->to); if ($this->getCc()) { $headers = array_merge($headers, array('CC' => $this->getCc())); $smtpTo = array_merge($smtpTo, array('CC' => $this->getCc())); } if ($this->getBcc()) { $smtpTo = array_merge($smtpTo, array('BCC' => $this->getBcc())); } $this->send($this->getFrom(), $smtpTo, $this->subject, chunk_split( base64_encode($this->body) ), $headers); best regards, Fernando Gabrieli
 [2017-10-17 11:26 UTC] icoman (Dan Gorg)
For me worked only these combination: --- customized by me: $headers = array( 'From' => $name." <".$sender.">", 'Return-Path' => $sender, 'Subject' => $subject, 'To' => $recipient, 'Bcc' => $Bcc ); $result = $mail->send($recipient, $headers, $body); $resultA = $mail->send($Bcc, $headers, $body); with $resultA the email to $Bcc email will be delivered.