Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sending one email to multiple email addresses without them all appearing in the To line #629

Closed
gavrichards opened this issue Jun 22, 2018 · 18 comments
Labels
difficulty: easy fix is easy in difficulty status: help wanted requesting help from the community type: bug bug in the library

Comments

@gavrichards
Copy link

We're finally upgrading from SDK v2.8 to v7 🎉

In our wrapper for the old version, we had this which handles sending an email either with single/multiple recipients in the 'To' line, or sending the email separately so each recipient only sees their own address in the To line.

if ($separate) {
    if (is_array($to)) {
        foreach($to as $toAddress) {
            $this->email->addSmtpapiTo($toAddress);
        }
    } else {
        $this->email->addSmtpapiTo($to);
    }

} else {
    $this->email->addTo($to);
}

Is there an equivalent for v7? Or should we instead be sending completely independent emails?

Any help would be appreciated.

@thinkingserious
Copy link
Contributor

Hello @gavrichards,

I think this is the use case needed. Please let me know.

With Best Regards,

Elmer

@thinkingserious thinkingserious added type: question question directed at the library status: help wanted requesting help from the community difficulty: unknown or n/a fix is unknown in difficulty labels Jun 26, 2018
@gavrichards
Copy link
Author

Hi Elmer
Is that the same as calling addTo() multiple times? I've written a wrapper which does that, but wanted an option to specify the email must be sent individually to each person in the To line.

@AleMadLei
Copy link

AleMadLei commented Jul 2, 2018

@gavrichards , I'm not sure if this will work for you, but what I've been doing is adding personalizations to the mail object.

  // Previously initializated personalization object. 
  $personalization->addTo($to);
  
  // Adds it to the email. 
  $mail->addPersonalization($personalization);

This way I get the contacts to only see their email address on the message.

@thinkingserious
Copy link
Contributor

Hello @gavrichards,

Please see @alemadlei-tech's response. Thanks!

@alemadlei-tech,

Thanks for taking the time to share your solution!

@gavrichards
Copy link
Author

Thanks both, I'll give this a try and report back.

@gavrichards
Copy link
Author

@alemadlei-tech @thinkingserious Hi
I've tried this, and this is how my code looks now:

// Example data to pass in:
$to = [
  'me@mycompany.com',
  'someone@else.org'
];

$separate = true;

// Send an individual email to each recipient, or send with everyone in the 'to' line?
if ($separate) {
    foreach ($to as $address) 
    {
        //$this->email->addSmtpapiTo($address);

        $personalization = new SendGrid\Mail\Personalization();
        $personalization->addTo(new SendGrid\Mail\To($address));

        $this->email->addPersonalization($personalization);
    }

} else {
    foreach($to as $address) 
    {
        $this->email->addTo($address);
    }
}

However I'm receiving this error:

{"errors":[{"message":"The to array is required for all personalization objects, and must have at least one email object with a valid email address.","field":"personalizations.0.to","help":"http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#message.personalizations.to"}]}

Can you see where I might be going wrong?

@AleMadLei
Copy link

@gavrichards, depending on how you instantiated your mail object, it might contain an empty personalization object.

So, there's a chance your email has 2 personalization objects or more, with the first one with no recipients. Do a print_r() and check the output.

@gavrichards
Copy link
Author

@alemadlei-tech It's instantiated like this. I couldn't find any documentation on how to do the personalization object.

$this->email = new SendGrid\Mail\Mail();

@AleMadLei
Copy link

AleMadLei commented Jul 5, 2018

@gavrichards,

You should be able to do

print_r($this->email)

before sending it and from the output, if i'm not mistaken, you will see that the first item in the personalization contains no recipients.

Also, I didn't find any documentation for it either, but what I did is go trough the code and found about that.

@gavrichards
Copy link
Author

Yes - you're right. In this case, there's 3 personalization objects.
So the first one is provided by default presumably, and then I've added two more. In which case, this approach is probably not going to work.

[personalization:SendGrid\Mail\Mail:private] => Array
        (
            [0] => SendGrid\Mail\Personalization Object
                (
                    [tos:SendGrid\Mail\Personalization:private] => 
                    [ccs:SendGrid\Mail\Personalization:private] => 
                    [bccs:SendGrid\Mail\Personalization:private] => 
                    [subject:SendGrid\Mail\Personalization:private] => 
                    [headers:SendGrid\Mail\Personalization:private] => 
                    [substitutions:SendGrid\Mail\Personalization:private] => 
                    [custom_args:SendGrid\Mail\Personalization:private] => 
                    [send_at:SendGrid\Mail\Personalization:private] => 
                )

            [1] => SendGrid\Mail\Personalization Object
                (
                    [tos:SendGrid\Mail\Personalization:private] => Array
                        (
                            [0] => SendGrid\Mail\To Object
                                (
                                    [name:SendGrid\Mail\EmailAddress:private] => 
                                    [email:SendGrid\Mail\EmailAddress:private] => ***@***.com
                                    [substitutions:SendGrid\Mail\EmailAddress:private] => 
                                    [subject:SendGrid\Mail\EmailAddress:private] => 
                                )

                        )

                    [ccs:SendGrid\Mail\Personalization:private] => 
                    [bccs:SendGrid\Mail\Personalization:private] => 
                    [subject:SendGrid\Mail\Personalization:private] => 
                    [headers:SendGrid\Mail\Personalization:private] => 
                    [substitutions:SendGrid\Mail\Personalization:private] => 
                    [custom_args:SendGrid\Mail\Personalization:private] => 
                    [send_at:SendGrid\Mail\Personalization:private] => 
                )

            [2] => SendGrid\Mail\Personalization Object
                (
                    [tos:SendGrid\Mail\Personalization:private] => Array
                        (
                            [0] => SendGrid\Mail\To Object
                                (
                                    [name:SendGrid\Mail\EmailAddress:private] => 
                                    [email:SendGrid\Mail\EmailAddress:private] => ***@***.com
                                    [substitutions:SendGrid\Mail\EmailAddress:private] => 
                                    [subject:SendGrid\Mail\EmailAddress:private] => 
                                )

                        )

                    [ccs:SendGrid\Mail\Personalization:private] => 
                    [bccs:SendGrid\Mail\Personalization:private] => 
                    [subject:SendGrid\Mail\Personalization:private] => 
                    [headers:SendGrid\Mail\Personalization:private] => 
                    [substitutions:SendGrid\Mail\Personalization:private] => 
                    [custom_args:SendGrid\Mail\Personalization:private] => 
                    [send_at:SendGrid\Mail\Personalization:private] => 
                )

        )

@AleMadLei
Copy link

@gavrichards, yes, but you need to add something to the email in the constructor. Check the constructor logic, you should be able to set the subject for the email and that would cause the personalization object to remain empty.

@thinkingserious
Copy link
Contributor

Thanks for helping out @alemadlei-tech!

Please let us know if you run into further issues @gavrichards.

@gavrichards
Copy link
Author

@alemadlei-tech Even if you add the subject to the constructor, you still get an error saying

The to array is required for all personalization objects, and must have at least one email object with a valid email address.

This is because the first personalization object just contains the subject, and then the other two personalization objects contain a populated tos object.

I think ultimately what I set out to do originally isn't going to work with this new SDK. I think it would be best if I reconsidered the approach completely.
My feedback to @thinkingserious would be to perhaps have some upgrade/migration notes, and in this case state that there isn't a direct replacement for the addSmtpapiTo() method seen in the earlier SDK.

@gavrichards
Copy link
Author

gavrichards commented Jul 6, 2018

I've got this working, but it's a bit long-winded.

if ($this->sendSeparately)
{
    $i = 0;
    foreach($this->to as $address)
    {
        if ($i == 0) {
            // Add the first address to the existing personalization that is created by default
            $this->mail
                ->addTo($address);

        } else {
            // Add subsequent addresses to new personalizations
            $personalization = new SendGrid\Mail\Personalization();
            $personalization
                ->addTo(new SendGrid\Mail\To($address));

            $this->mail
                ->addPersonalization($personalization);
        }

        $i++;
    }

} else {
    foreach($this->to as $address)
    {
        $this->mail
            ->addTo($address);
    }
}

I have a related question now though. I'm trying to add a custom arg.
It says in the docblock for addCustomArg:

Add a custom arg to a Personalization or Mail object

If you don't provide a Personalization object or index, the custom arg will be global to entire message. Note that custom args added to Personalization objects override global custom args.

My problem is whenever I call this, it always adds the custom arg to the first personalization object.
But looking at the code for this function, I can't see how it would ever populate the Mail object's custom_args ? It seems to always update either the first personalization object, or whichever is specified. @thinkingserious is there a way to set custom args globally on the Mail object?

@thinkingserious
Copy link
Contributor

Thanks for sharing your solution @gavrichards!

I think this is the function you need for global custom arguments.

@gavrichards
Copy link
Author

@thinkingserious Thanks - so the explanation comment on addCustomArg is incorrect?

@thinkingserious
Copy link
Contributor

Yes, thanks for catching that! I'm going to classify this issue as a bug and put on our backlog for a fix. For this issue to gain priority in our backlog, we need additional +1's or a PR. When we receive a PR, that provides the biggest jump in priority.

@thinkingserious thinkingserious added type: bug bug in the library difficulty: easy fix is easy in difficulty up-for-grabs and removed difficulty: unknown or n/a fix is unknown in difficulty type: question question directed at the library labels Jul 10, 2018
@gavrichards
Copy link
Author

Thanks @thinkingserious :)

thinkingserious added a commit that referenced this issue Aug 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty: easy fix is easy in difficulty status: help wanted requesting help from the community type: bug bug in the library
Projects
None yet
Development

No branches or pull requests

3 participants