Легко читайте листи з Outlook за допомогою Microsoft Graph API та зберігайте їх у вашій базі даних за допомогою PHP

pic

Потік дій

Відправка електронних листів є звичайною практикою, але зчитування даних електронної пошти дещо менш знайоме для багатьох. Однак це так само просто, як і відправка листів через SMTP. Хоча це можна зробити з доменними електронними листами, я поділюсь простим скриптом, який використовує Microsoft Graph API для зчитування електронних листів з Outlook.

"Служба IMAP має бути увімкнена на вашому сервері."

КРОК 1: Щоб використовувати Microsoft Graph API, вам потрібно додати необхідні дозволи для послуг, до яких ви хочете отримати доступ. Додайте ці дозволи в розділі API permissions порталу Azure.

pic

Список дозволів

КРОК 2: Після додавання дозволів, вам потрібно створити секретний токен для авторизації. Будьте обережні, оскільки він відображається лише один раз. При генерації токена обов'язково скопіюйте його та збережіть у безпечному місці для подальшого використання.

pic

Генерація секретного токена

КРОК 3: Тепер встановіть Composer, а потім додайте пакет microsoft graph

composer require microsoft/microsoft-graph:^1.110

КРОК 4: Далі спробуємо встановити з’єднання з Azure через Microsoft Graph API. Після успішного з’єднання ми зможемо перейти до наступного кроку — зчитування електронної пошти. Якщо все успішно, відобразиться

Токен доступу успішно згенеровано!

 'client_credentials',  
 'client_id' => $clientId,  
 'client_secret' => $clientSecret,  
 'scope' => 'https://graph.microsoft.com/.default'  
 ];  

 $ch = curl_init();  
 curl_setopt($ch, CURLOPT_URL, $url);  
 curl_setopt($ch, CURLOPT_POST, true);  
 curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));  
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  

 $response = curl_exec($ch);  

 if (curl_errno($ch)) {  
 throw new Exception('Curl error: ' . curl_error($ch));  
 }  

 curl_close($ch);  

 $responseData = json_decode($response, true);  

 if (isset($responseData['error'])) {  
 throw new Exception('Error getting access token: ' . $responseData['error_description']);  
 }  

 echo "Access token generated successfully!.\n";  
 return $responseData['access_token'];  
}  


try {  
 $tenantId = 'Your Directory (tenant) ID';  
 $clientId = 'Your Application (client) ID';  
 $clientSecret = 'Your client secret';  
 $userId = '[email protected]';  

 //calling the access token function  
 $accessToken = getAccessToken($tenantId, $clientId, $clientSecret);  
} catch (\Exception $e) {  
 echo "Error: " . $e->getMessage() . "\n";  
}

КРОК 5: Тепер напишемо скрипт для отримання списку електронних листів. Для автоматизації скрипт позначатиме електронні листи як “прочитані” після їх успішної обробки. Після зчитування листа, скрипт оновить його статус на “прочитано”. Це має бути викликано в блоці try, згаданому вище.

Після успішного з’єднання буде відображена кількість повідомлень, разом з темою повідомлення, ідентифікатором повідомлення та вмістом тіла.

function fetchEmailsAndAttachments($accessToken, $userId)  
{  
 $graph = new Graph();  
 $graph->setAccessToken($accessToken);  

 $url = "/users/$userId/messages?\$top=10&\$filter=isRead eq false&\$orderby=receivedDateTime desc";  

 try {  
 $messages = $graph->createRequest("GET", $url)  
 ->setReturnType(Model\Message::class)  
 ->execute();  

 echo "Fetched " . count($messages) .
" messages.\n";  

 foreach ($messages as $message) {  
 echo "Тема повідомлення: " . $message->getSubject() . "\n";  
 echo "ID повідомлення: " . $message->getId() . "\n";  

 // Отримати вміст повідомлення  
 $bodyContent = $message->getBody()->getContent();  

 $from = $message->getFrom();  
 $emailFrom = $from->getEmailAddress()->getAddress();   
 echo "Email відправника: " . $emailFrom . "\n";  

 // Оновити позначку листа як прочитано  
 $patchUrl = "/users/$userId/messages/" . $message->getId();  
 $updatePayload = [  
 "isRead" => true  
 ];  

 $graph->createRequest("PATCH", $patchUrl)  
 ->attachBody($updatePayload)  
 ->execute();  

 echo "Позначено повідомлення як прочитане.\n";  
 }  
 } catch (Exception $e) {  
 echo "Помилка при отриманні повідомлень або вкладень: " . $e->getMessage() . "\n";  
 }  
}

Залиште функцію getAccessToken, а блок try оновіть наступним чином:

try {  
 $tenantId = 'Ваш ID каталогу (tenant)';  
 $clientId = 'Ваш ID додатку (client)';  
 $clientSecret = 'Ваш клієнтський секрет';  
 $userId = '[email protected]';  

 // виклик функції отримання токена доступу  
 $accessToken = getAccessToken($tenantId, $clientId, $clientSecret);  

 // виклик функції для читання електронної пошти  
 fetchEmailsAndAttachments($accessToken, $userId);  
} catch (\Exception $e) {  
 echo "Помилка: " . $e->getMessage() . "\n";  
}

КРОК 6: Тепер зробимо це ще цікавішим, зберігаючи вкладення електронної пошти на сервері. Наступний скрипт допоможе нам завантажити та зберегти вкладення. Для цього ми використовуємо функцію fetchEmailsAndAttachments, яка викликає функцію saveAttachment для обробки завантаження та збереження.

function saveAttachment($fileName, $content)  
{  
 $safeFileName = preg_replace('/[^A-Za-z0-9_\-\.]/', '_', $fileName);  
 $uniqueFileName = pathinfo($safeFileName, PATHINFO_FILENAME) . '_' . time() . '.' . pathinfo($safeFileName, PATHINFO_EXTENSION);  

 $savePath = __DIR__ . '/mail_attachment/' . $uniqueFileName;  

 if (!is_dir(__DIR__ . '/mail_attachment')) {  
 mkdir(__DIR__ . '/mail_attachment', 0777, true);  
 }  

 if (file_put_contents($savePath, $content) === false) {  
 echo "Не вдалося зберегти вкладення: $uniqueFileName\n";  
 return null;  
 } else {  
 echo "Вкладення успішно збережено: $savePath\n";  
 return $uniqueFileName;  
 }  
}  

// Оновлена функція fetchEmailsAndAttachments  
function fetchEmailsAndAttachments($accessToken, $userId)  
{  
 $graph = new Graph();  
 $graph->setAccessToken($accessToken);  

 $url = "/users/$userId/messages?\$top=10&\$filter=isRead eq false&\$orderby=receivedDateTime desc";  

 try {  
 $messages = $graph->createRequest("GET", $url)  
 ->setReturnType(Model\Message::class)  
 ->execute();  

 echo "Отримано " . count($messages) . " повідомлень.\n";  

 foreach ($messages as $message) {  
 echo "Тема повідомлення: " . $message->getSubject() . "\n";  
 echo "ID повідомлення: " . $message->getId() . "\n";  

 // Отримати вміст повідомлення  
 $bodyContent = $message->getBody()->getContent();  

 $from = $message->getFrom();  
 $emailFrom = $from->getEmailAddress()->getAddress();   
 echo "Email відправника: " . $emailFrom . "\n";  

 $parsedData = parseEmailBody($bodyContent);  

 $attachmentUrl = "/users/$userId/messages/" . $message->getId() . "/attachments";  
 $attachments = $graph->createRequest("GET", $attachmentUrl)  
 ->setReturnType(Model\Attachment::class)  
 ->execute();  

 echo "Знайдено " . count($attachments) . " вкладень.\n";  

 if(count($attachments) > 0){  
 foreach ($attachments as $attachment) {  
 echo "Тип вкладення: " . get_class($attachment) . "\n";  

 if ($attachment->getODataType() === '#microsoft.graph.fileAttachment') {  
 echo "Назва вкладення: " . $attachment->getName() . "\n";  

 $attachmentId = $attachment->getId();  
 $attachmentContentUrl = "/users/$userId/messages/" . $message->getId() .
"/attachments/$attachmentId/\$value";  

 try {  
 // Явне отримання вмісту вкладення  
 $attachmentContentResponse = $graph->createRequest("GET", $attachmentContentUrl)  
 ->execute();  

 $fileContent = $attachmentContentResponse->getRawBody(); // Отримати сирий бінарний вміст  
 $fileName = $attachment->getName();  

 // Зберігаємо вкладення та отримуємо шлях до файлу  
 $attachmentFilePath = saveAttachment($fileName, $fileContent);  
 echo "Вкладення завантажено та збережено: $attachmentFilePath\n";  
 } catch (Exception $e) {  
 echo "Не вдалося отримати вміст вкладення: " . $e->getMessage() . "\n";  
 }  
 } else {  
 echo "Невідомий тип вкладення або це не файл.\n";  
 echo "Тип вкладення @odata.type: " . $attachment->getODataType() . "\n";  
 }  
 }  
 }  

 $patchUrl = "/users/$userId/messages/" . $message->getId();  
 $updatePayload = [  
 "isRead" => true  
 ];  

 $graph->createRequest("PATCH", $patchUrl)  
 ->attachBody($updatePayload)  
 ->execute();  

 echo "Позначено повідомлення як прочитане.\n";  
 }  
 } catch (Exception $e) {  
 echo "Помилка при отриманні повідомлень або вкладень: " . $e->getMessage() . "\n";  
 }  
}

Якщо все вдалося, вкладений файл буде збережений у вказаному шляху на сервері.

КРОК 7: Тепер, на останньому етапі, ми збережемо тему листа, вміст та шлях до вкладення в базі даних. Припускаючи, що конфігурація бази даних вже налаштована, я використаю сирий запит для вставки даних.

function storeEmailData($db, $subject, $sender, $body, $attachmentFilePath)  
{  
 // Припускаючи, що конфігурація бази даних вже доступна  
 $query = "INSERT INTO emails_data (subject, sender, body, attachment_file_path)   
 VALUES (:subject, :sender, :body, :attachment_file_path)";  

 $stmt = $db->prepare($query);  
 $stmt->bindParam(':subject', $subject);  
 $stmt->bindParam(':sender', $sender);  
 $stmt->bindParam(':body', $body);  
 $stmt->bindParam(':attachment_file_path', $attachmentFilePath);  

 try {  
 $stmt->execute();  
 echo "Дані листа успішно збережено.\n";  
 } catch (Exception $e) {  
 echo "Помилка при збереженні даних листа: " . $e->getMessage() . "\n";  
 }  
}

Викликайте функцію storeEmailData всередині функції fetchEmailsAndAttachments, щоб зберегти деталі листа, включаючи тему, відправника, вміст та шлях до вкладення. Крім того, переконайтеся, що параметр db передається до функції fetchEmailsAndAttachments, щоб його можна було використовувати при виклику storeEmailData.
Наприклад, fetchEmailsAndAttachments($accessToken, $userId, $db)

storeEmailData($db, $message->getSubject(), $emailFrom, $bodyContent, $attachmentFilePath);

Підсумок:

Ця стаття пояснює, як використовувати Microsoft Graph API для отримання непрочитаних листів з Outlook, завантаження вкладень та збереження даних листа в базі даних. Процес включає підключення до Azure, отримання листів, збереження вкладень на сервері та збереження теми листа, відправника, вмісту та шляху до вкладення в базі даних. Після обробки листи позначаються як прочитані, щоб уникнути повторної обробки. Стаття надає функції для автоматизації цих кроків для ефективного управління електронною поштою.

Перекладено з: Effortlessly Read Outlook Emails with Microsoft Graph API and Save Them to Your Database Using PHP

Leave a Reply

Your email address will not be published. Required fields are marked *