Add Message-Id to SentMessage when sending an email
This commit is contained in:
parent
a84ec3a636
commit
b42c269760
@ -14,6 +14,7 @@ namespace Symfony\Component\Mailer\Bridge\Amazon\Transport;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\Exception\HttpTransportException;
|
||||
use Symfony\Component\Mailer\SentMessage;
|
||||
use Symfony\Component\Mailer\Transport\AbstractApiTransport;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
@ -48,7 +49,7 @@ class SesApiTransport extends AbstractApiTransport
|
||||
return sprintf('ses+api://%s@%s', $this->accessKey, $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, Envelope $envelope): ResponseInterface
|
||||
protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface
|
||||
{
|
||||
$date = gmdate('D, d M Y H:i:s e');
|
||||
$auth = sprintf('AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=HmacSHA256,Signature=%s', $this->accessKey, $this->getSignature($date));
|
||||
@ -62,12 +63,13 @@ class SesApiTransport extends AbstractApiTransport
|
||||
'body' => $this->getPayload($email, $envelope),
|
||||
]);
|
||||
|
||||
$result = new \SimpleXMLElement($response->getContent(false));
|
||||
if (200 !== $response->getStatusCode()) {
|
||||
$error = new \SimpleXMLElement($response->getContent(false));
|
||||
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $error->Error->Message, $error->Error->Code), $response);
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $result->Error->Message, $result->Error->Code), $response);
|
||||
}
|
||||
|
||||
$sentMessage->setMessageId($result->SendEmailResult->MessageId);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
@ -63,12 +63,13 @@ class SesHttpTransport extends AbstractHttpTransport
|
||||
],
|
||||
]);
|
||||
|
||||
$result = new \SimpleXMLElement($response->getContent(false));
|
||||
if (200 !== $response->getStatusCode()) {
|
||||
$error = new \SimpleXMLElement($response->getContent(false));
|
||||
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $error->Error->Message, $error->Error->Code), $response);
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $result->Error->Message, $result->Error->Code), $response);
|
||||
}
|
||||
|
||||
$message->setMessageId($result->SendEmailResult->MessageId);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Mailer\Bridge\Mailchimp\Transport;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\Exception\HttpTransportException;
|
||||
use Symfony\Component\Mailer\SentMessage;
|
||||
use Symfony\Component\Mailer\Transport\AbstractApiTransport;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
@ -41,14 +42,14 @@ class MandrillApiTransport extends AbstractApiTransport
|
||||
return sprintf('mandrill+api://%s', $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, Envelope $envelope): ResponseInterface
|
||||
protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface
|
||||
{
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/api/1.0/messages/send.json', [
|
||||
'json' => $this->getPayload($email, $envelope),
|
||||
]);
|
||||
|
||||
$result = $response->toArray(false);
|
||||
if (200 !== $response->getStatusCode()) {
|
||||
$result = $response->toArray(false);
|
||||
if ('error' === ($result['status'] ?? false)) {
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $result['message'], $result['code']), $response);
|
||||
}
|
||||
@ -56,6 +57,8 @@ class MandrillApiTransport extends AbstractApiTransport
|
||||
throw new HttpTransportException(sprintf('Unable to send an email (code %s).', $result['code']), $response);
|
||||
}
|
||||
|
||||
$sentMessage->setMessageId($result['_id']);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,8 @@ class MandrillHttpTransport extends AbstractHttpTransport
|
||||
],
|
||||
]);
|
||||
|
||||
$result = $response->toArray(false);
|
||||
if (200 !== $response->getStatusCode()) {
|
||||
$result = $response->toArray(false);
|
||||
if ('error' === ($result['status'] ?? false)) {
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $result['message'], $result['code']), $response);
|
||||
}
|
||||
@ -60,6 +60,8 @@ class MandrillHttpTransport extends AbstractHttpTransport
|
||||
throw new HttpTransportException(sprintf('Unable to send an email (code %s).', $result['code']), $response);
|
||||
}
|
||||
|
||||
$message->setMessageId($result['_id']);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Mailer\Bridge\Mailgun\Transport;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\Exception\HttpTransportException;
|
||||
use Symfony\Component\Mailer\SentMessage;
|
||||
use Symfony\Component\Mailer\Transport\AbstractApiTransport;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Mime\Part\Multipart\FormDataPart;
|
||||
@ -46,7 +47,7 @@ class MailgunApiTransport extends AbstractApiTransport
|
||||
return sprintf('mailgun+api://%s?domain=%s', $this->getEndpoint(), $this->domain);
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, Envelope $envelope): ResponseInterface
|
||||
protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface
|
||||
{
|
||||
$body = new FormDataPart($this->getPayload($email, $envelope));
|
||||
$headers = [];
|
||||
@ -61,14 +62,17 @@ class MailgunApiTransport extends AbstractApiTransport
|
||||
'body' => $body->bodyToIterable(),
|
||||
]);
|
||||
|
||||
$result = $response->toArray(false);
|
||||
if (200 !== $response->getStatusCode()) {
|
||||
if ('application/json' === $response->getHeaders(false)['content-type'][0]) {
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $response->toArray(false)['message'], $response->getStatusCode()), $response);
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $result['message'], $response->getStatusCode()), $response);
|
||||
}
|
||||
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $response->getContent(false), $response->getStatusCode()), $response);
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $result, $response->getStatusCode()), $response);
|
||||
}
|
||||
|
||||
$sentMessage->setMessageId($result['id']);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
@ -64,14 +64,17 @@ class MailgunHttpTransport extends AbstractHttpTransport
|
||||
'body' => $body->bodyToIterable(),
|
||||
]);
|
||||
|
||||
$result = $response->toArray(false);
|
||||
if (200 !== $response->getStatusCode()) {
|
||||
if ('application/json' === $response->getHeaders(false)['content-type'][0]) {
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $response->toArray(false)['message'], $response->getStatusCode()), $response);
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $result['message'], $response->getStatusCode()), $response);
|
||||
}
|
||||
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $response->getContent(false), $response->getStatusCode()), $response);
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $result, $response->getStatusCode()), $response);
|
||||
}
|
||||
|
||||
$message->setMessageId($result['id']);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Mailer\Bridge\Postmark\Transport;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\Exception\HttpTransportException;
|
||||
use Symfony\Component\Mailer\SentMessage;
|
||||
use Symfony\Component\Mailer\Transport\AbstractApiTransport;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
@ -41,7 +42,7 @@ class PostmarkApiTransport extends AbstractApiTransport
|
||||
return sprintf('postmark+api://%s', $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, Envelope $envelope): ResponseInterface
|
||||
protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface
|
||||
{
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/email', [
|
||||
'headers' => [
|
||||
@ -51,12 +52,13 @@ class PostmarkApiTransport extends AbstractApiTransport
|
||||
'json' => $this->getPayload($email, $envelope),
|
||||
]);
|
||||
|
||||
$result = $response->toArray(false);
|
||||
if (200 !== $response->getStatusCode()) {
|
||||
$error = $response->toArray(false);
|
||||
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $error['Message'], $error['ErrorCode']), $response);
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', $result['Message'], $result['ErrorCode']), $response);
|
||||
}
|
||||
|
||||
$sentMessage->setMessageId($result['MessageID']);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,10 @@ class SendgridApiTransportTest extends TestCase
|
||||
->expects($this->once())
|
||||
->method('getStatusCode')
|
||||
->willReturn(202);
|
||||
$response
|
||||
->expects($this->once())
|
||||
->method('getHeaders')
|
||||
->willReturn(['x-message-id' => '1']);
|
||||
|
||||
$httpClient = $this->createMock(HttpClientInterface::class);
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Mailer\Bridge\Sendgrid\Transport;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\Exception\HttpTransportException;
|
||||
use Symfony\Component\Mailer\SentMessage;
|
||||
use Symfony\Component\Mailer\Transport\AbstractApiTransport;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Email;
|
||||
@ -42,7 +43,7 @@ class SendgridApiTransport extends AbstractApiTransport
|
||||
return sprintf('sendgrid+api://%s', $this->getEndpoint());
|
||||
}
|
||||
|
||||
protected function doSendApi(Email $email, Envelope $envelope): ResponseInterface
|
||||
protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface
|
||||
{
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/v3/mail/send', [
|
||||
'json' => $this->getPayload($email, $envelope),
|
||||
@ -55,6 +56,8 @@ class SendgridApiTransport extends AbstractApiTransport
|
||||
throw new HttpTransportException(sprintf('Unable to send an email: %s (code %s).', implode('; ', array_column($errors['errors'], 'message')), $response->getStatusCode()), $response);
|
||||
}
|
||||
|
||||
$sentMessage->setMessageId($response->getHeaders(false)['x-message-id'][0]);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ class SentMessage
|
||||
private $original;
|
||||
private $raw;
|
||||
private $envelope;
|
||||
private $messageId;
|
||||
private $debug = '';
|
||||
|
||||
/**
|
||||
@ -31,9 +32,20 @@ class SentMessage
|
||||
{
|
||||
$message->ensureValidity();
|
||||
|
||||
$this->raw = $message instanceof Message ? new RawMessage($message->toIterable()) : $message;
|
||||
$this->original = $message;
|
||||
$this->envelope = $envelope;
|
||||
|
||||
if ($message instanceof Message) {
|
||||
$message = clone $message;
|
||||
$headers = $message->getHeaders();
|
||||
if (!$headers->has('Message-ID')) {
|
||||
$headers->addIdHeader('Message-ID', $message->generateMessageId());
|
||||
}
|
||||
$this->messageId = $headers->get('Message-ID')->getId();
|
||||
$this->raw = new RawMessage($message->toIterable());
|
||||
} else {
|
||||
$this->raw = $message;
|
||||
}
|
||||
}
|
||||
|
||||
public function getMessage(): RawMessage
|
||||
@ -51,6 +63,16 @@ class SentMessage
|
||||
return $this->envelope;
|
||||
}
|
||||
|
||||
public function setMessageId(string $id): void
|
||||
{
|
||||
$this->messageId = $id;
|
||||
}
|
||||
|
||||
public function getMessageId(): string
|
||||
{
|
||||
return $this->messageId;
|
||||
}
|
||||
|
||||
public function getDebug(): string
|
||||
{
|
||||
return $this->debug;
|
||||
|
@ -24,7 +24,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
*/
|
||||
abstract class AbstractApiTransport extends AbstractHttpTransport
|
||||
{
|
||||
abstract protected function doSendApi(Email $email, Envelope $envelope): ResponseInterface;
|
||||
abstract protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $envelope): ResponseInterface;
|
||||
|
||||
protected function doSendHttp(SentMessage $message): ResponseInterface
|
||||
{
|
||||
@ -34,7 +34,7 @@ abstract class AbstractApiTransport extends AbstractHttpTransport
|
||||
throw new RuntimeException(sprintf('Unable to send message with the "%s" transport: %s', __CLASS__, $e->getMessage()), 0, $e);
|
||||
}
|
||||
|
||||
return $this->doSendApi($email, $message->getEnvelope());
|
||||
return $this->doSendApi($message, $email, $message->getEnvelope());
|
||||
}
|
||||
|
||||
protected function getRecipients(Email $email, Envelope $envelope): array
|
||||
|
@ -32,9 +32,7 @@ class Message extends RawMessage
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
if (null !== $this->headers) {
|
||||
$this->headers = clone $this->headers;
|
||||
}
|
||||
$this->headers = clone $this->headers;
|
||||
|
||||
if (null !== $this->body) {
|
||||
$this->body = clone $this->body;
|
||||
@ -86,16 +84,12 @@ class Message extends RawMessage
|
||||
}
|
||||
|
||||
// determine the "real" sender
|
||||
$senders = $headers->get('From')->getAddresses();
|
||||
$sender = $senders[0];
|
||||
if ($headers->has('Sender')) {
|
||||
$sender = $headers->get('Sender')->getAddress();
|
||||
} elseif (\count($senders) > 1) {
|
||||
$headers->addMailboxHeader('Sender', $sender);
|
||||
if (!$headers->has('Sender') && \count($froms = $headers->get('From')->getAddresses()) > 1) {
|
||||
$headers->addMailboxHeader('Sender', $froms[0]);
|
||||
}
|
||||
|
||||
if (!$headers->has('Message-ID')) {
|
||||
$headers->addIdHeader('Message-ID', $this->generateMessageId($sender->getAddress()));
|
||||
$headers->addIdHeader('Message-ID', $this->generateMessageId());
|
||||
}
|
||||
|
||||
// remove the Bcc field which should NOT be part of the sent message
|
||||
@ -132,9 +126,17 @@ class Message extends RawMessage
|
||||
parent::ensureValidity();
|
||||
}
|
||||
|
||||
private function generateMessageId(string $email): string
|
||||
public function generateMessageId(): string
|
||||
{
|
||||
return bin2hex(random_bytes(16)).strstr($email, '@');
|
||||
if ($this->headers->has('Sender')) {
|
||||
$sender = $this->headers->get('Sender')->getAddress();
|
||||
} elseif ($this->headers->has('From')) {
|
||||
$sender = $this->headers->get('From')->getAddresses()[0];
|
||||
} else {
|
||||
throw new LogicException('An email must have a "From" or a "Sender" header to compute a Messsage ID.');
|
||||
}
|
||||
|
||||
return bin2hex(random_bytes(16)).strstr($sender->getAddress(), '@');
|
||||
}
|
||||
|
||||
public function __serialize(): array
|
||||
|
Reference in New Issue
Block a user