Файл: vendor/laravel/framework/src/Illuminate/Mail/Transport/CloudflareTransport.php
Строк: 235
<?php
namespace IlluminateMailTransport;
use Exception;
use SensitiveParameter;
use SymfonyComponentHttpClientHttpClient;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentMailerEnvelope;
use SymfonyComponentMailerExceptionTransportException;
use SymfonyComponentMailerSentMessage;
use SymfonyComponentMailerTransportAbstractTransport;
use SymfonyComponentMimeAddress;
use SymfonyComponentMimeEmail;
use SymfonyComponentMimeMessageConverter;
use SymfonyContractsHttpClientHttpClientInterface;
class CloudflareTransport extends AbstractTransport
{
/**
* The HTTP Client instance.
*/
protected HttpClientInterface $client;
/**
* Create a new Cloudflare transport instance.
*/
public function __construct(
protected string $accountId,
#[SensitiveParameter] protected string $key,
?HttpClientInterface $client = null,
) {
parent::__construct();
$this->client = $client ?? HttpClient::create();
}
/**
* {@inheritDoc}
*
* @throws TransportException
*/
protected function doSend(SentMessage $message): void
{
try {
$response = $this->client->request('POST', sprintf(
'https://api.cloudflare.com/client/v4/accounts/%s/email/sending/send',
$this->accountId,
), [
'auth_bearer' => $this->key,
'headers' => ['Accept' => 'application/json'],
'json' => $this->getPayload($message),
]);
$result = $response->toArray(false);
} catch (Exception $exception) {
throw new TransportException(
sprintf('Request to Cloudflare API failed. Reason: %s.', $exception->getMessage()),
is_int($exception->getCode()) ? $exception->getCode() : 0,
$exception,
);
}
throw_if(
$response->getStatusCode() !== Response::HTTP_OK,
TransportException::class,
$result['errors'][0]['message'] ?? 'Unknown error',
$response->getStatusCode(),
);
}
/**
* Get the Cloudflare payload for the given message.
*/
protected function getPayload(SentMessage $message): array
{
$email = MessageConverter::toEmail($message->getOriginalMessage());
$envelope = $message->getEnvelope();
return array_filter([
'from' => $this->formatAddress($envelope->getSender()),
'to' => $this->stringifyAddresses($this->getRecipients($email, $envelope)),
'cc' => $this->stringifyAddresses($email->getCc()),
'bcc' => $this->stringifyAddresses($email->getBcc()),
'reply_to' => ($replyTo = $email->getReplyTo()) ? $this->formatAddress($replyTo[0]) : null,
'subject' => $email->getSubject(),
'html' => $email->getHtmlBody(),
'text' => $email->getTextBody(),
'headers' => $this->getCustomHeaders($email),
'attachments' => $this->getAttachments($email),
], fn ($value) => $value !== null && $value !== [] && $value !== '');
}
/**
* Get the recipients without CC or BCC.
*/
protected function getRecipients(Email $email, Envelope $envelope): array
{
return array_filter($envelope->getRecipients(), function (Address $address) use ($email) {
return in_array($address, array_merge($email->getCc(), $email->getBcc()), true) === false;
});
}
/**
* Get the custom headers for the email, excluding the standard ones.
*/
protected function getCustomHeaders(Email $email): array
{
$headers = [];
$headersToBypass = ['from', 'to', 'cc', 'bcc', 'reply-to', 'sender', 'subject', 'content-type'];
foreach ($email->getHeaders()->all() as $name => $header) {
if (in_array($name, $headersToBypass, true)) {
continue;
}
$headers[$header->getName()] = $header->getBodyAsString();
}
return $headers;
}
/**
* Get the attachments formatted for the Cloudflare API.
*/
protected function getAttachments(Email $email): array
{
$attachments = [];
foreach ($email->getAttachments() as $attachment) {
$headers = $attachment->getPreparedHeaders();
$disposition = $headers->getHeaderBody('Content-Disposition') ?: 'attachment';
$filename = $headers->getHeaderParameter('Content-Disposition', 'filename');
$item = [
'content' => str_replace("rn", '', $attachment->bodyToString()),
'filename' => $filename,
'type' => $headers->get('Content-Type')->getBody(),
'disposition' => $disposition,
];
if ($disposition === 'inline') {
$item['content_id'] = $attachment->hasContentId() ? $attachment->getContentId() : $filename;
}
$attachments[] = $item;
}
return $attachments;
}
/**
* Get the address formatted for the Cloudflare API.
*
* @return string|array
*/
protected function formatAddress(Address $address)
{
if ($address->getName()) {
return [
'name' => $address->getName(),
'address' => $address->getAddress(),
];
}
return $address->getAddress();
}
/**
* Get multiple addresses formatted as strings for the Cloudflare API.
*/
protected function stringifyAddresses(array $addresses): array
{
return array_map(fn (Address $a) => $a->getAddress(), $addresses);
}
/**
* Get the string representation of the transport.
*/
public function __toString(): string
{
return 'cloudflare';
}
}