Repository: symfony/symfony
File: src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php (PHP)

Code before:
        }
        if ($emails = array_map($addressStringifier, $email->getBcc())) {
            $personalization['bcc'] = $emails;
        }
        if ($emails = array_map($addressStringifier, $email->getReplyTo())) {
            // Email class supports an array of reply-to addresses,
            // but SendGrid only supports a single address
            $payload['reply_to'] = $emails[0];
        }

        $customArguments = [];
        $categories = [];

        // these headers can't be overwritten according to Sendgrid docs
        // see https://sendgrid.api-docs.io/v3.0/mail-send/mail-send-errors#-Headers-Errors
        $headersToBypass = ['x-sg-id', 'x-sg-eid', 'received', 'dkim-signature', 'content-transfer-encoding', 'from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'reply-to'];
        foreach ($email->getHeaders()->all() as $name => $header) {
            if (\in_array($name, $headersToBypass, true)) {
                continue;
            }

            if ($name === 'send-at') {
                if (!$header instanceof DateHeader) {
                    throw new TransportException(sprintf('The Send-At header should be a "%s" instance to deduce the correct timestamp.', DateHeader::class));
                }
                // the documentation shows parameter names in camelCase but the expected JSON keys should be in snake_case
                $payload['send_at'] = $header->getDateTime()->getTimestamp();
            } elseif ($header instanceof TagHeader) {
                if (10 === \count($categories)) {
                    throw new TransportException(sprintf('Too many "%s" instances present in the email headers. Sendgrid does not accept more than 10 categories on an email.', TagHeader::class));
                }
                $categories[] = mb_substr($header->getValue(), 0, 255);
            } elseif ($header instanceof MetadataHeader) {
                $customArguments[$header->getKey()] = $header->getValue();
            } else {
                $payload['headers'][$header->getName()] = $header->getBodyAsString();
            }
        }

        if (\count($categories) > 0) {
            $payload['categories'] = $categories;
        }

        if (\count($customArguments) > 0) {
            $personalization['custom_args'] = $customArguments;
        }

        $payload['personalizations'][] = $personalization;

        return $payload;
    }

Review comment (suggestion):
```suggestion
```

There seems to be no point in explaining this for a specific case, since this rule applies to all parameters.

In addition, the documentation has an example of how to use:
https://www.twilio.com/docs/sendgrid/api-reference/mail-send/mail-send#request-body

Code after:
        if ($emails = array_map($addressStringifier, $email->getCc())) {
            $personalization['cc'] = $emails;
        }
        if ($emails = array_map($addressStringifier, $email->getBcc())) {
            $personalization['bcc'] = $emails;
        }
        if ($emails = array_map($addressStringifier, $email->getReplyTo())) {
            // Email class supports an array of reply-to addresses,
            // but SendGrid only supports a single address
            $payload['reply_to'] = $emails[0];
        }

        $customArguments = [];
        $categories = [];

        foreach ($email->getHeaders()->all() as $name => $header) {
            // these headers can't be overwritten according to Sendgrid docs
            // see https://sendgrid.api-docs.io/v3.0/mail-send/mail-send-errors#-Headers-Errors
            if (\in_array($name, ['x-sg-id', 'x-sg-eid', 'received', 'dkim-signature', 'content-transfer-encoding', 'from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'reply-to'], true)) {
                continue;
            }

            if ('send-at' === $name) {
                if (!$header instanceof DateHeader) {
                    throw new TransportException(\sprintf('The "Send-At" header must be a "%s" instance.', DateHeader::class));
                }
                $payload['send_at'] = $header->getDateTime()->getTimestamp();
            } elseif ($header instanceof TagHeader) {
                if (10 === \count($categories)) {
                    throw new TransportException(\sprintf('Too many "%s" instances present in the email headers. Sendgrid does not accept more than 10 categories on an email.', TagHeader::class));
                }
                $categories[] = mb_substr($header->getValue(), 0, 255);
            } elseif ($header instanceof MetadataHeader) {
                $customArguments[$header->getKey()] = $header->getValue();
            } elseif ($header instanceof SuppressionGroupHeader) {
                $payload['asm'] = [
                    'group_id' => $header->getGroupId(),
                ];
                if ($groupsToDisplay = $header->getGroupsToDisplay()) {
                    $payload['asm']['groups_to_display'] = $groupsToDisplay;
                }
            } else {
                $payload['headers'][$header->getName()] = $header->getBodyAsString();
            }
        }

        if ($categories) {
            $payload['categories'] = $categories;
        }

        if ($customArguments) {