I'm trying to save Outlook email attachments to OneDrive using msgraph-sdk-php. I can pull in the emails and get attachment information but I don't know how to save the attachments.
I tried implementing this solution but I get this error:
Client error: `PUT https:\/\/08fxt-my.sharepoint.com\/personal\/myemail_onmicrosoft_com\/_api\/v2.0\/drive\/items\/01LRAM......` resulted in a `400 Bad Request` response:\n{\"error\":{\"code\":\"invalidRequest\",\"message\":\"The Content-Range header length does not match the provided number of bytes.\"}}\n
This is my code:
$outlook_emails = $this->getEmails();
foreach ($outlook_emails as $outlook_email) {
$email_object = $outlook_email->jsonSerialize();
if ($email_object['hasAttachments'] == true) {
$email_attachments = (new Graph())->setAccessToken($accessToken)
->createCollectionRequest("GET", '/users/' . $userId . '/messages/' . $outlook_email->getId() . '/attachments')
->setReturnType(\Microsoft\Graph\Model\FileAttachment::class)
->execute();
foreach ($email_attachments as $attachment) {
$attachment_object = $attachment->jsonSerialize();
$filename = $attachment->getName();
$uploadsession = $graph->createRequest("POST",
"/users/" . $userId . "/drive/root:/test/" . $filename . ":/createUploadSession")
->attachBody([
"@microsoft.graph.conflictBehavior" => "rename | fail | replace",
"description" => "description",
"fileSystemInfo" => ["@odata.type" => "microsoft.graph.fileSystemInfo"],
"name" => $filename,
])
->setReturnType(\Microsoft\Graph\Model\UploadSession::class)
->execute();
$fragSize = 320 * 1024;// 1024 * 1024 * 4;
$graph_url = $uploadsession->getUploadUrl();
$fileSize = $attachment->getSize();
$numFragments = ceil($fileSize / $fragSize);
$bytesRemaining = $fileSize;
$i = 0;
while ($i < $numFragments) {
$chunkSize = $numBytes = $fragSize;
$start = $i * $fragSize;
$end = $i * $fragSize + $chunkSize - 1;
$offset = $i * $fragSize;
if ($bytesRemaining < $chunkSize) {
$chunkSize = $numBytes = $bytesRemaining;
$end = $fileSize - 1;
}
$content_range = "bytes " . $start . "-" . $end . "/" . $fileSize;
$headers = [
"Content-Length" => $numBytes,
"Content-Range" => $content_range,
];
$uploadByte = $graph->createRequest("PUT", $graph_url)
->addHeaders($headers)
->attachBody($attachment_object['contentBytes'])
->setReturnType(Model\UploadSession::class)
->setTimeout("1000")
->execute();
$bytesRemaining = $bytesRemaining - $chunkSize;
$i++;
}
}
}
}
This is a sample output of $attachment
in the inner foreach
{
"@odata.type": "#microsoft.graph.fileAttachment",
"@odata.mediaContentType": "application/pdf",
"id": "AAMkAGQXXXXXXXX7Op2M8=",
"lastModifiedDateTime": "2023-07-27T19:32:55Z",
"name": "dummy.pdf",
"contentType": "application/pdf",
"size": 13454,
"isInline": false,
"contentId": "f_lkljxgt10",
"contentLocation": null,
"contentBytes": "JVBERi0xLXXXXXXXXXXXXXX="
}
This is what $headers
is set to:
{"Content-Length":13454,"Content-Range":"bytes 0-13453/13454"}