Using PHPMailer for MIME messages with BCC issues in Gmail API

I’m facing a challenge with the BCC feature while using PHPMailer to create email messages for the Gmail API.

My Setup:
I utilize PHPMailer solely for formatting MIME messages, passing them to the Gmail API afterwards instead of sending directly via SMTP. Although the TO and CC addresses receive emails without any issues, the BCC recipients do not.

Code Example:

// Create a PHPMailer instance
$mail = new PHPMailer();
$mail->isSMTP();
$mail->IsHTML(true);
$mail->SMTPDebug = 0;

// Set up sender and recipients
$mail->setFrom('[email protected]', 'Sender Name');
$mail->addReplyTo('[email protected]', 'Reply Name');
$mail->addAddress('[email protected]', 'Main Recipient');
$mail->addCC('[email protected]', 'CC Recipient');
$mail->addBCC('[email protected]', 'BCC Recipient');

// Prepare email content
$mail->Subject = 'Test Email';
$mail->Body = file_get_contents('/path/to/email.html');
$mail->addAttachment('/path/to/document.pdf', 'document.pdf', 'base64', 'application/pdf');

// Create MIME message and send it via Gmail API
$mail->preSend();
$mimeMessage = $mail->getSentMIMEMessage();

$gmailMessage = new Google_Service_Gmail_Message();
$encodedContent = base64_encode($mimeMessage);
$encodedContent = str_replace(['+', '/', '='], ['-', '_', ''], $encodedContent);
$gmailMessage->setRaw($encodedContent);

$gmailService = new Google_Service_Gmail($client);
$gmailService->users_messages->send('me', $gmailMessage);

The Issue:
After sending, I notice the absence of an ‘undisclosed-recipients’ header, and BCC recipients aren’t receiving the emails. However, when using Gmail’s web interface to send emails with BCC options, it works perfectly.

Is there a known workaround for this BCC issue when working with PHPMailer and Gmail API?

I encountered this exact problem last year and spent considerable time debugging it. The core issue is that PHPMailer’s getSentMIMEMessage() method doesn’t properly handle BCC headers when you’re bypassing the actual SMTP sending process. When you call preSend() without actually sending through SMTP, the BCC handling gets disrupted because PHPMailer expects to strip BCC headers during the actual transmission phase, not during MIME generation. What worked for me was manually extracting the BCC addresses before calling preSend() and then sending separate API calls for each BCC recipient. You can access the BCC addresses through the getBccAddresses() method, store them in an array, then remove them from the PHPMailer instance before generating your MIME message. After that, send the main message to TO and CC recipients, then iterate through your stored BCC addresses and send individual messages to each one with only their address in the TO field. It’s not elegant but it ensures proper delivery while maintaining the BCC privacy aspect.

had similar headache with this - the problem is gmail api treats bcc differently than regular smtp. try setting the bcc recipients directly in the api call instead of the mime headers. create your message without bcc in phpmailer, then use the gmail api’s ‘bcc’ parameter when calling the send method. worked for me after hours of debugging this exact issue.

This happens because the Gmail API expects BCC recipients to be handled differently than traditional SMTP. When you generate the MIME message through PHPMailer, the BCC headers are included in the raw message, but the Gmail API strips them out during processing since BCC addresses shouldn’t appear in the final message headers visible to recipients. I solved this by modifying the approach entirely - instead of relying on PHPMailer’s BCC handling, I extract all recipient addresses first and create a single message with only TO and CC recipients in the MIME headers. Then I use the Gmail API’s native threading capability by sending the same message to BCC recipients separately using the Gmail API’s send method with different recipient parameters. The key is to use the same message-id and thread-id for all sends, which maintains email threading while ensuring BCC privacy. You’ll need to iterate through your BCC addresses and make individual API calls for each, but this guarantees delivery and proper BCC behavior consistent with Gmail’s web interface.