Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Chops up WordPress out-going emails so that number of bcc addressees stays below a configured limit
Plugin Name: Ovni chop up emails
Description: Prevents number of Bcc addresees exceeding defined limit by breaking it up into multiple emails.
Author: Tony Voss
Version: 1.0 1 Mar 2019
Version: 1.0 1 Mar 2019 Initial version
(1) If an email contains mutiple cc addressees it notes it in the error log but lets the email through. Not seen any such emails from my websites.
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
function ovni_chop_email($args){
/* configuration */
$max_bcc = 10; // maximum number of Bcc addresses allowed
$debug = false; // whether want debug
if ($debug){
$result = ob_get_clean();
error_log("Entering ovni_chop_email\n" . $result);
$headers = $args['headers'];
if (empty($headers)) return($args); // if no headers, nothing to do
// pick up CC/BCC, collating them from headers
if (isset($args['headers'])) {
$cc = array();
$bcc = array();
$other = array();
if (!is_array($headers)) {
$headers = explode("\n", str_replace("\r\n", "\n", $headers));
foreach ($headers as $header) {
if ($header) {
switch (strtolower(substr($header, 0, 3))) {
case 'cc:':
$cc[] = $header;
error_log("Found cc:" . $header);
case 'bcc':
$bcc[] = $header;
$others[] = $header;
if (!empty($cc)){
// not yet supporting cc
error_log("Ovni_chop_mail saw addressee in cc field for email: " . $args['subject']);
if (sizeof($bcc) == 1){ // may be a list of adressees with a single bcc header, as from Subscribe2
$bcc = explode("\n", str_replace(",", "\nBcc:", $bcc[0]));
if (sizeof($bcc) <= $max_bcc) return($args); // This one can go straight through - nothing to do
// we need to chop up this email into multiples
remove_filter('wp_mail', 'ovni_chop_email',5); // We do not want to be called back each time we send one of the parts
while (sizeof($bcc) > $max_bcc){
if($debug) error_log("Chopping up - bcc=". strval(sizeof($bcc)));
$this_batch = array_slice($bcc, 0, $max_bcc);
$bcc = array_slice($bcc, $max_bcc); // reduce to those not in this batch
$headers = array_merge($others, $this_batch);
if (!wp_mail($args["to"], $args["subject"], $args["message"], $headers, $args["attachments"])) error_log("Ovni_chop_email returned error");
// We are here because we have done all but the last chunk. Return and let original call do this one.
$headers = array_merge($others, $bcc);
$args['headers'] = $headers;
add_filter('wp_mail', 'ovni_chop_email',5); // restore the filter
add_filter('wp_mail', 'ovni_chop_email',5);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment