Sendgrid-php: How to stop revealing all emails in one email sending using a loop

Created on 11 Mar 2016  路  12Comments  路  Source: sendgrid/sendgrid-php

I'm doing a simple PHP for each loop to send to multiple email addresses, but it is sending one email carbon copying everyone. How can I stop this but send to one person at a time. Here's my code.

foreach($thecustomer as $key => $value){
$emailmaster->addTo($customeremail)
->setFrom($shopowner . " <" . $email . ">")
->setSubject($subject)
->setHtml($body . $openpixel);
$sendgrid->send($emailmaster); }`

Most helpful comment

hey @omarel1

The easiest way you can do it is using substitution tags. You can manipulate data in your own way. I'll give you a quick example how to do it using the preview example:

// lets suppose the input_array is a 10K recipient list
$input_array = array("[email protected]", .... "[email protected]");
// first_name for each individual email
$fname_array = array("fname1", "fname2", .... "fname_10_1000");
// open pixel for each individual email
$open_pixel_array = array("openpixel1", "openpixel2", ....., "openpixel_10_000");

// make sure you have the same number of elements in these 3 arrays
// - $input_array
// - $fname_array
// - $open_pixel_array

$number_of_emails_per_request = 1000;

// email chunks
$recipient_chunks = array_chunk($input_array, $number_of_emails_per_request);
// fname chunks
$fname_chunks = array_chunk($fname_array, $number_of_emails_per_request);
// open pixel chunks
$open_pixel_chunks = array_chunk($open_pixel_array, $number_of_emails_per_request);

// the email body contains fname and openpixel custom tags
$body = "Hey [first_name] .... here is you pixel [open_pixel]";
$from = $shopowner . " <" . $email . ">";

// process each chunk
for ($i = 0; $i < count($recipient_chunks); $i++)
{
     // create a new instance of Email inside the loop
     $emailmaster = new SendGrid\Email();
     // add 1k recipients
     $emailmaster->setSmtpapiTos($recipient_chunks[$i])
                 ->setFrom($from)
                 ->setSubject($subject)
                 ->setHtml($body);
     // add first name as substitution tag
     $emailmaster->addSubstitution('[first_name]', $fname_chunks[$i]);
     // add open pixel as substitution tag
     $emailmaster->addSubstitution('[open_pixel]', $open_pixel_chunks[$i]);
     // send 1000 emails at once 
     $sendgrid->send($emailmaster)
 }

All 12 comments

Hey @omarel1,

// loop over the recipients
foreach($thecustomer as $key => $value)
{
     // create a new instance of Email inside the loop
     $emailmaster = new SendGrid\Email();
    // add the recipient
     $emailmaster->addTo($customeremail)
                 ->setFrom($shopowner . " <" . $email . ">")
                 ->setSubject($subject)
                 ->setHtml($body . $openpixel);
    // send the email 
    $sendgrid->send($emailmaster)
 }

What you did wrong is the fact you didn't reset the $emailmaster instance.

Let me know if you have more questions.

That worked Thank you!

Is this suitable for looping to say 10,000 emails. It looks like it continually open and close the connection each time which could cause issues?

@omarel1 It's not suitable for looping over 10k emails. Instead you could use batch sending via x-smtpapi header.

Example:

// lets suppose the input_array is a 10K recipient list
$input_array = array("[email protected]", .... "[email protected]");
// split the list into 1k batches
$recipient_chunks = array_chunk($input_array, 1000)

// process each chunk
foreach ($recipient_chunks as $recipients)
{
    // create a new instance of Email inside the loop
     $emailmaster = new SendGrid\Email();
    // add 1k recipients
     $emailmaster->addTo("[email protected]")
                 ->setSmtpapiTos($recipients)
                 ->setFrom($shopowner . " <" . $email . ">")
                 ->setSubject($subject)
                 ->setHtml($body . $openpixel);
    // send 1000 emails at once 
    $sendgrid->send($emailmaster)
 }

Using this approach, you'll do 10 requests instead of 10000.

this is interesting. It's splitting a master array into multiple arrays.
Each array is called $recipients, but when I implement this now I have
trouble access the value in the array.

  1. How would I get the single email recipient since $recipients is an array.
  2. How would I place the first name in the input_array also

I could do another foreach within that foreach but then I'm thinking it
defeats the purpose since that's what we're trying to avoid right.

I ask because I need to include the first name in the array and I also need to include the individual email in the $openpixel

hey @omarel1

The easiest way you can do it is using substitution tags. You can manipulate data in your own way. I'll give you a quick example how to do it using the preview example:

// lets suppose the input_array is a 10K recipient list
$input_array = array("[email protected]", .... "[email protected]");
// first_name for each individual email
$fname_array = array("fname1", "fname2", .... "fname_10_1000");
// open pixel for each individual email
$open_pixel_array = array("openpixel1", "openpixel2", ....., "openpixel_10_000");

// make sure you have the same number of elements in these 3 arrays
// - $input_array
// - $fname_array
// - $open_pixel_array

$number_of_emails_per_request = 1000;

// email chunks
$recipient_chunks = array_chunk($input_array, $number_of_emails_per_request);
// fname chunks
$fname_chunks = array_chunk($fname_array, $number_of_emails_per_request);
// open pixel chunks
$open_pixel_chunks = array_chunk($open_pixel_array, $number_of_emails_per_request);

// the email body contains fname and openpixel custom tags
$body = "Hey [first_name] .... here is you pixel [open_pixel]";
$from = $shopowner . " <" . $email . ">";

// process each chunk
for ($i = 0; $i < count($recipient_chunks); $i++)
{
     // create a new instance of Email inside the loop
     $emailmaster = new SendGrid\Email();
     // add 1k recipients
     $emailmaster->setSmtpapiTos($recipient_chunks[$i])
                 ->setFrom($from)
                 ->setSubject($subject)
                 ->setHtml($body);
     // add first name as substitution tag
     $emailmaster->addSubstitution('[first_name]', $fname_chunks[$i]);
     // add open pixel as substitution tag
     $emailmaster->addSubstitution('[open_pixel]', $open_pixel_chunks[$i]);
     // send 1000 emails at once 
     $sendgrid->send($emailmaster)
 }

Is it possible to use a multidimensional array. Do I still need to make 3 separate index arrays? I have the email and first name in a multidimensional array like this that I'm pulling from:

(
[0] => Array
    (
        [email] => [email protected]
        [first_name] => Omar          

    )

 [1] => Array
    (
        [email] => [email protected]
        [first_name] => Joe

    )
)

@omarel1 you must extract them from your source. You cannot pass in using that format.

Thank you! Is there any reason why a simple php for each loop up to say 2000 recipients wouldn't work smoothly?

I see. Will the chunking work properly when you don't know how many emails you're sending out. Say someone might send 344 emails. And you maybe do a switch statement to see what the number is and have it send 50 emails per request. Will it work properly even though the 344 is not divisible by 50?

@omarel1 yes it will. PHP will take care of that. If you follow @bsorin guide, you will be perfectly fine!

this is my full code, but it's only sending one email to the first person on the list:
$thecustomercm is the customer count
$customermarketingarray is the master multidimensional array that holds the emails and the first names

`switch ($thecustomercm){
    case ($thecustomercm <= 250):
    $number_of_emails_per_request = 50;
    break;
     case ($thecustomercm <= 1000):
 $number_of_emails_per_request = 250;
 break; 
 case ($thecustomercm <= 2000):
 $number_of_emails_per_request = 500;
 break; 
    }
                //extract emails from customers and place in associative array
                $desiredKey = 'email';
                foreach ($customermarketingarray as $key => $value) {
                        $email1 = $value[$desiredKey];
                         $emails[] = $email1;
                    }

                //extract first names from customers and place in associative array
                $desiredKey = 'first_name';
                foreach ($customermarketingarray as $key => $value) {
                        $fname1 = $value[$desiredKey];
                         $fnames[] = $fname1;
                    }

                    // email chunks
                    $email_chunks = array_chunk($emails, $number_of_emails_per_request);
                    // fname chunks
                    $fname_chunks = array_chunk($fnames, $number_of_emails_per_request);


                            // the email body contains fname and openpixel custom tags
                            $from = $shopowner . " <" . $email . ">";
                            $openpixel = "<img src='https://site.net/emailcustomers/actions/trackopens.php?to=[email]' />";

                            /*  */// process each chunk
                            for ($i = 0; $i < count($email_chunks); $i++)
                            {
                                 // create a new instance of Email inside the loop
                                 $emailmaster = new SendGrid\Email();
                                 // add 1k recipients
                                 $emailmaster->setSmtpapiTos($email_chunks[$i])
                                             ->setFrom($from)
                                             ->setSubject($subject)
                                             ->setHtml($body . $openpixel);
                                 // add first name as substitution tag
                                 $emailmaster->addSubstitution('[fname]', $fname_chunks[$i]);
                                 $emailmaster->addSubstitution('[email]', $email_chunks[$i]);
                                 $sendgrid->send($emailmaster);
                             }`

My mistake, this code is actually working! Gmail just wasnt sending me the tests because my one gmail accounts hosts all the test emails and they usually trigger one email in that case.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

iamanupammaity picture iamanupammaity  路  4Comments

solonifer picture solonifer  路  3Comments

atsareva picture atsareva  路  4Comments

Aubynj picture Aubynj  路  3Comments

bjornmann picture bjornmann  路  3Comments