-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Mailer] Add MSGraph API Transport #52546
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,6 @@ | |
|
||
namespace Symfony\Component\Mailer\Bridge\MicrosoftGraph\Transport; | ||
|
||
use GuzzleHttp\Exception\ClientException; | ||
use GuzzleHttp\Psr7\Stream; | ||
use GuzzleHttp\Psr7\Utils; | ||
use Microsoft\Graph\Generated\Models\BodyType; | ||
|
@@ -26,7 +25,6 @@ | |
use Microsoft\Graph\Generated\Users\Item\SendMail\SendMailPostRequestBody; | ||
use Microsoft\Graph\GraphServiceClient; | ||
use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As you instantiate this class directly which comes from a different package, you should depend on it explicitly instead of relying on the transitive dependency in the microsoft SDK to avoid issues if new major versions are done. |
||
use Safe\Exceptions\JsonException; | ||
use Symfony\Component\Mailer\Bridge\MicrosoftGraph\Exception\SenderNotFoundException; | ||
use Symfony\Component\Mailer\Bridge\MicrosoftGraph\Exception\SendMailException; | ||
use Symfony\Component\Mailer\Envelope; | ||
|
@@ -39,8 +37,6 @@ | |
use Symfony\Component\Mime\RawMessage; | ||
use Symfony\Contracts\Cache\CacheInterface; | ||
|
||
use function Safe\json_decode; | ||
|
||
class MicrosoftGraphTransport implements TransportInterface | ||
{ | ||
private GraphServiceClient $graphServiceClient; | ||
|
@@ -68,7 +64,6 @@ public function send(RawMessage $message, Envelope $envelope = null): ?SentMessa | |
throw new SendEmailError(sprintf("This mailer can only handle mails of class '%s' or it's subclasses, instance of %s passed", Email::class, $message::class)); | ||
} | ||
|
||
|
||
$this->sendMail($message); | ||
|
||
return new SentMessage($message, $envelope); | ||
|
@@ -85,7 +80,7 @@ private function sendMail(Email $message): void | |
try { | ||
$this->graphServiceClient->users()->byUserId($senderAddress)->sendMail()->post($body)->wait(); | ||
} catch (ODataError $error) { | ||
if ('ErrorInvalidUser' === $error->getError()->getCode()){ | ||
if ('ErrorInvalidUser' === $error->getError()->getCode()) { | ||
throw new SenderNotFoundException("Sender email address '".$senderAddress."' could not be found when calling the Graph API. This is usually because the email address doesn't exist in the tenant.", 404, $error); | ||
} | ||
throw new SendMailException('Something went wrong while sending email', $error->getCode(), $error); | ||
|
@@ -104,19 +99,19 @@ private function convertEmailToGraphMessage(Email $source): Message | |
$message->setFrom(self::convertAddressToGraphRecipient($source->getFrom()[0])); | ||
|
||
// to | ||
$message->setToRecipients(\array_map( | ||
$message->setToRecipients(array_map( | ||
static fn (Address $address) => self::convertAddressToGraphRecipient($address), | ||
$source->getTo() | ||
)); | ||
|
||
// CC | ||
$message->setCcRecipients(\array_map( | ||
$message->setCcRecipients(array_map( | ||
static fn (Address $address) => self::convertAddressToGraphRecipient($address), | ||
$source->getCc() | ||
)); | ||
|
||
// BCC | ||
$message->setBccRecipients(\array_map( | ||
$message->setBccRecipients(array_map( | ||
static fn (Address $address) => self::convertAddressToGraphRecipient($address), | ||
$source->getBcc() | ||
)); | ||
|
@@ -128,7 +123,7 @@ private function convertEmailToGraphMessage(Email $source): Message | |
$itemBody->setContentType(new BodyType(BodyType::HTML)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic looks broken in case the Email only has a plaintext body. |
||
$message->setBody($itemBody); | ||
|
||
$message->setAttachments(\array_map( | ||
$message->setAttachments(array_map( | ||
static fn (DataPart $attachment) => self::convertAttachmentGraphAttachment($attachment), | ||
$source->getAttachments() | ||
)); | ||
|
@@ -143,6 +138,7 @@ private static function convertAddressToGraphRecipient(Address $source): Recipie | |
$emailAddress->setAddress($source->getAddress()); | ||
$emailAddress->setName($source->getName()); | ||
$recipient->setEmailAddress($emailAddress); | ||
|
||
return $recipient; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,6 @@ | |
namespace Symfony\Component\Mailer\Bridge\MicrosoftGraph\Transport; | ||
|
||
use Microsoft\Graph\Core\NationalCloud; | ||
use phpDocumentor\Reflection\Exception\PcreException; | ||
use Symfony\Component\Mailer\Exception\IncompleteDsnException; | ||
use Symfony\Component\Mailer\Exception\InvalidArgumentException; | ||
use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; | ||
|
@@ -28,9 +27,9 @@ final class MicrosoftGraphTransportFactory extends AbstractTransportFactory | |
private const CLOUD_MAP = [ | ||
'default' => NationalCloud::GLOBAL, | ||
'germany' => NationalCloud::GERMANY, | ||
'china' => NationalCloud::CHINA, | ||
'us-dod' => NationalCloud::US_DOD, | ||
'us-gov' => NationalCloud::US_GOV, | ||
'china' => NationalCloud::CHINA, | ||
'us-dod' => NationalCloud::US_DOD, | ||
'us-gov' => NationalCloud::US_GOV, | ||
]; | ||
|
||
public function __construct( | ||
|
@@ -56,8 +55,8 @@ public function create(Dsn $dsn): TransportInterface | |
if (null === $tenantId) { | ||
throw new IncompleteDsnException("Transport 'microsoft+graph' requires the 'tenant' option"); | ||
} | ||
if (!isset(self::CLOUD_MAP[$dsn->getHost()])){ | ||
throw new InvalidArgumentException(sprintf("Transport 'microsoft+graph' one of these hosts : '%s'", implode(", ", self::CLOUD_MAP))); | ||
if (!isset(self::CLOUD_MAP[$dsn->getHost()])) { | ||
throw new InvalidArgumentException(sprintf("Transport 'microsoft+graph' one of these hosts : '%s'", implode(', ', self::CLOUD_MAP))); | ||
} | ||
|
||
// This parses the MAILER_DSN containing Microsoft Graph API credentials | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this comment looks wrong to me. |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using guzzle/psr7 without depending on it is a no-go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it looks like the microsoft graph SDK supports any PSR-7 stream, the transport should rather take a StreamFactory in its constructor.