-
Notifications
You must be signed in to change notification settings - Fork 153
Description
Using v1.81.0 of the SDK, trying to add attachments to an email fails when providing the Microsoft\Graph\Model\FileAttachment::setContentBytes() method a GuzzleHttp\Psr7\Stream instance as its single parameter. Passing through a string results in things working correctly.
Minimal reproducer:
function send_email(\Symfony\Component\Mime\Email $email): void
{
$graph = new \Microsoft\Graph\Graph();
$graph->setAccessToken($accessToken);
$graphMessageResponse = $graph->createRequest('POST', sprintf('/users/%s/messages', $userEmail))
->attachBody(build_graph_message_request($email))
->setReturnType(\Microsoft\Graph\Model\Message::class)
->execute();
foreach ($email->getAttachments() as $dataPart) {
$attachmentStream = \GuzzleHttp\Psr7\UtilsUtils::streamFor(base64_encode($dataPart->getBody()));
$attachmentSize = $attachmentStream->getSize();
if ($attachmentSize <= (MEGABYTE_IN_BYTES * 3)) {
$attachment = new \Microsoft\Graph\Model\FileAttachment();
$attachment->setODataType('#microsoft.graph.fileAttachment');
$attachment->setName($dataPart->getFilename());
$attachment->setContentType($dataPart->getContentType());
$attachment->setContentBytes($attachmentStream);
// $attachment->setContentBytes(base64_encode($dataPart->getBody())); <-- This version works
$attachment->setContentId(\Illuminate\Support\Str::random(10));
$graph->createRequest('POST', sprintf('/users/%s/messages/%s/attachments', $userEmail, $graphMessageResponse->getId()))
->attachBody($attachment)
->setReturnType(\Microsoft\Graph\Model\FileAttachment::class)
->execute();
} else {
// Large file upload branch, not related to this issue
}
}
$graph->createRequest('POST', sprintf('/users/%s/messages/%s/send', $userEmail, $graphMessageResponse->getId()))
->execute();
}Suggested fixes:
Option 1 - The Microsoft\Graph\Model\FileAttachment::setContentBytes() method should be documented as requiring a string instead of a GuzzleHttp\Psr7\Stream instance if it is not intended for developers to pass through a stream they've created themselves
Option 2 - The Microsoft\Graph\Model\Entity::jsonSerialize() method should be updated to include another condition for a GuzzleHttp\Psr7\Stream instance and manually typecast it to a string:
public function jsonSerialize()
{
$serializableProperties = $this->getProperties();
foreach ($serializableProperties as $property => $val) {
if (is_a($val, "\DateTime")) {
$serializableProperties[$property] = $val->format(\DateTime::RFC3339);
} else if (is_a($val, "\Microsoft\Graph\Core\Enum")) {
$serializableProperties[$property] = $val->value();
} else if (is_a($val, "\Entity")) {
$serializableProperties[$property] = $val->jsonSerialize();
} else if (is_a($val, "\GuzzleHttp\Psr7\Stream")) {
$serializableProperties[$property] = (string) $val;
}
}
return $serializableProperties;
}