M365Con 2027 – безкоштовна онлайн-конференція · 11–22 Jan 2027 · 120 sessions→ m365con.net

Блог · Mirko Peters

Створення безпечних рішень для надсилання електронної пошти: надсилання пошти через Microsoft Graph для розробників

By ·

Ласкаво просимо назад до подкасту, друзі! У сьогоднішньому епізоді ми детально розглянули архітектурні особливості сучасних систем доставки електронної пошти. Коли ви створюєте застосунки корпоративного рівня, епоха покладання на застарілі протоколи SMTP — з жорстко закодованими паролями та незашифрованим рукостисканням — нарешті залишилася позаду. Сьогодні ми дивимося в бік сучасних API, в основі

Automatically translated with AI from the original post. Read the English original

▶ BLOGBuilding Secure EmailSolutions: Sending Mail…M365.FM
Titelbild: Building Secure Email Solutions: Sending Mail via Microsoft Graph for Developers

Ласкаво просимо назад до подкасту, друзі! У сьогоднішньому епізоді ми детально розглянули架构ні особливості сучасних систем доставки електронної пошти. Коли ви створюєте застосунки корпоративного рівня, епоха покладання на застарілі протоколи SMTP — з жорстко закодованими паролями та незашифрованим рукостисканням — нарешті залишилася позаду. Сьогодні ми дивимося в бік сучасних API, в основі яких лежить ідентифікація. Зокрема, ми розглянули, як використовувати Microsoft Graph API для безпечного, надійного та масштабованого надсилання листів.

Для тих, хто віддає перевагу читанню з паралельним відкриттям коду, експериментам із фрагментами коду або довідкою щодо шаблонів реалізації під час написання коду, цей супровідний блог-пост значною мірою розширює нашу дискусію з подкасту. Ми пройдемо весь шлях розробника: налаштування постачальника ідентифікації, безпечне отримання токенів, формування тіла запиту, обробку тимчасових мережевих збоїв і захист архітектури для продуктивного розгортання. Почнімо одразу.

Вступ до Microsoft Graph Mail API

Протягом десятиліть надсилання електронної пошти з програми означало підключення до SMTP-сервера, передавання облікових даних базової автентифікації (часто імені користувача й пароля у відкритому тексті, які зберігалися у змінній середовища або, що гірше, у файлі конфігурації) і сподівання на краще. Такий підхід несе серйозні ризики безпеки. Якщо файл конфігурації скомпрометовано, зловмисник отримує повний доступ до цієї поштової скриньки. Крім того, великі хмарні провайдери дедалі частіше відмовляються від базової автентифікації на користь сучасних моделей автентифікації на основі токенів.

Знайомтеся з Microsoft Graph API. Microsoft Graph є шлюзом до даних і можливостей штучного інтелекту в Microsoft 365. Він надає єдину модель програмованості, за допомогою якої можна отримувати доступ до даних, що забезпечують продуктивність у Microsoft 365, Windows і Enterprise Mobility + Security. Що стосується електронної пошти, Microsoft Graph Mail API дозволяє вашій програмі надсилати пошту від імені користувачів або як самій програмі, і все це відбувається за суворими правилами авторизації OAuth 2.0.

Чому розробникам варто перейти на нього? Перш за все, безпека. Використовуючи Azure Active Directory (тепер відомий як Microsoft Entra ID) для автентифікації, ви повністю позбавляєтеся збережених паролів. Натомість ваша програма автентифікується за допомогою криптографічних ключів, сертифікатів або керованих ідентифікацій, отримуючи короткоживучі токени доступу на виконання конкретних завдань. По-друге, Microsoft Graph надає детальну телеметрію, кращий журнал аудиту та глибоку інтеграцію з ширшою екосистемою Microsoft. Надсилаєте автоматичні рахунки, системні сповіщення чи повідомлення для користувачів: Microsoft Graph є надійною сучасною основою для всіх ваших транзакційних листів.

Налаштування реєстрацій застосунків і дозволів в Azure AD / Entra ID

Перш ніж написати хоча б один рядок коду, необхідно створити ідентичність для вашої програми у вашому клієнті Azure. Цей процес починається в центрі адміністрування Microsoft Entra зі створення реєстрації застосунку.

Покрокова реєстрація застосунку

Перейдіть до центру адміністрування Microsoft Entra, оберіть «App registrations» і натисніть «New registration». Дайте застосунку зрозумілу назву, наприклад «Enterprise Notification Service», і оберіть відповідні типи підтримуваних облікових записів. Для більшості серверних служб варто обрати «Accounts in this organizational directory only». Після створення запишіть ідентифікатор застосунку (клієнта) та ідентифікатор каталогу (клієнта); вони знадобляться під час налаштування логіки отримання токенів.

Делеговані та додаткові дозволи застосунку

Одне з найважливіших архітектурних рішень на цьому етапі — вибір між делегованими дозволами та дозволами застосунку.

  • Делеговані дозволи: використовуються застосунками, у яких присутній авторизований користувач. Застосунок діє від імені користувача. Для надсилання пошти зазвичай потрібен дозвіл Mail.Send. Коли користувач запускає застосунок, він має надати згоду на надсилання пошти від свого імені.
  • Дозволи для застосунків: використовуються фоновими службами, демонами або запланованими завданнями, які працюють без присутнього користувача, що ввійшов в систему. Застосунок діє як власна ідентичність. Для надсилання пошти потрібен дозвіл застосунку Mail.Send. Оскільки він дає застосунку змогу надсилати пошту від імені будь-якого користувача організації (залежно від конфігурації), для нього потрібна згода адміністратора.

Для фонових демонів і мікросервісів автоматизованих сповіщень ви неминуче використовуватимете дозволи застосунків. Після того як ви призначите дозвіл застосунку Mail.Send в Azure portal, адміністратор клієнта має явно натиснути кнопку «Grant admin consent». Без цього адміністративного підтвердження ваш застосунок отримуватиме відповіді HTTP 403 Forbidden під час спроб викликати Graph API.

Безпечне автентифікування та отримання токенів

Після того як реєстрацію застосунку налаштовано і дозволи надано, наступним завданням стане безпечне отримання токенів доступу OAuth 2.0. Ніколи не жорсткодьте секрети і уникайте клієнтських секретів, якщо доступна безпечніша альтернатива.

Потік облікових даних клієнта

Оскільки серверні застосунки працюють без користувацького інтерфейсу, вони використовують потік OAuth 2.0 Client Credentials Grant. У цьому потоці ваш застосунок передає свій ідентифікатор клієнта та доказ автентичності (клієнтський секрет або, що краще, асиметричний сертифікат) безпосередньо до кінцевої точки видачі токенів платформи Microsoft identity.

Клієнтські секрети поширені, але вони спливають і їх потрібно вручну перевипускати, що створює операційні витрати та ризик простою. Ми настійно рекомендуємо автентифікацію на основі сертифікатів (CBA) або, якщо ваш застосунок працює в Azure, керовані ідентичності. Керовані ідентичності повністю усувають потребу керувати обліковими даними в коді, оскільки Azure автоматично керує життєвим циклом токенів у фоновому режимі.

Реалізація отримання токенів у коді

Стандартний спосіб отримання токенів в екосистемі .NET — використання Microsoft Authentication Library (MSAL). MSAL з коробки обробляє кешування токенів, логіку автоматичного оновлення та деталі протоколу.

Ось концептуальний приклад того, як ініціалізувати Confidential Client Application і отримати токен:

// Conceptual initialization using MSAL
var confidentialClientApp = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithClientSecret(clientSecret)
    .WithTenantId(tenantId)
    .Build();

string[] scopes = new[] { "https://graph.microsoft.com/.default" };

var authResult = await confidentialClientApp.AcquireTokenForClient(scopes)
    .ExecuteAsync();

string accessToken = authResult.AccessToken;

Зверніть увагу на рядок області дії: https://graph.microsoft.com/.default. Під час використання дозволів застосунків запит області дії .default вказує платформі identity видати токен, що містить усі дозволи застосунку, які були статично налаштовані та погоджені під час етапу реєстрації застосунку.

Формування та надсилання корисного навантаження листа

Коли у вас є дійсний токен доступу JWT, можна формувати HTTP-запит до Microsoft Graph API. Кінцева точка для надсилання пошти залежить від того, чи використовуєте ви делеговані дозволи чи дозволи застосунків.

Структура кінцевої точки

Якщо ви надсилаєте пошту від імені конкретного користувача через дозволи застосунків, кінцева точка має таку структуру:

POST https://graph.microsoft.com/v1.0/users/{id-or-user-principal-name}/sendMail

Це дає змогу вашій фоновій службі надсилати лист із призначеного службового облікового запису, наприклад notifications@yourcompany.com.

Формування JSON-навантаження

Microsoft Graph очікує JSON-навантаження, яке чітко визначає властивості повідомлення, зокрема отримувачів, тему, тип вмісту тіла (текст або HTML) і необов'язкові вкладення. Ось приклад коректно сформованого навантаження листа:

{
  "message": {
    "subject": "System Status Update: Deployment Successful",
    "body": {
      "contentType": "HTML",
      "content": "The scheduled deployment to the production cluster completed successfully at 03:00 UTC."
    },
    "toRecipients": [
      {
        "emailAddress": {
          "address": "engineering-team@yourcompany.com"
        }
      }
    ],
    "attachments": []
  },
  "saveToSentItems": "true"
}

Зверніть особливу увагу на властивість saveToSentItems. Якщо встановити її в true, копія вихідного повідомлення автоматично потрапить до папки «Надіслані» поштової скриньки відправника, що надзвичайно корисно для аудиту та налагодження.

Реалізація стійкої обробки збоїв і повторних спроб

Мережеві виклики до хмарних API за своєю природою вразливі до тимчасових збоїв. Збої DNS, короткочасні проблеми з маршрутизацією, обмеження частоти запитів (HTTP 429 Too Many Requests) або тимчасове обмеження з боку сервера (помилки HTTP 5xx) рано чи пізно траплятимуться у продуктивному середовищі. Якщо логіка надсилання пошти не враховує ці збої, ваш застосунок втрачатиме повідомлення, що призводитиме до зламаного користувацького досвіду та незадоволених стейкхолдерів.

Побудова надійної політики повторних спроб

Щоб досягти високої доступності, обгорніть виклики Microsoft Graph API у стійку політику повторних спроб. Бібліотеки на кшталт Polly в екосистемі .NET або еквівалентні фреймворки стійкості в Node.js, Python і Java роблять це простим.

Розробляючи стратегію повторних спроб, дотримуйтеся таких ключових принципів:

  • Експоненційна затримка (exponential backoff): Не намагайтеся одразу знову звернутися до API після збою. Почекайте дві секунди, потім чотири, потім вісім, збільшуючи затримку з кожною наступною спробою, щоб дати залежному сервісу змогу відновитися.
  • Джиттер (jitter): Додавайте випадкові інтервали до часу затримки між повторними спробами. Якщо сотня мікросервісів одночасно зазнає збою і всі повторять запит через однакові фіксовані інтервали, ви самі створите розподілену атаку типу «відмова в обслуговуванні» (DDoS) на Graph API. Джиттер розподіляє трафік повторних запитів у часі.
  • Враховуйте заголовки Retry-After: Коли Microsoft Graph обмежує частоту запитів вашого застосунку, він повертає код стану HTTP 429 із заголовком Retry-After, який вказує, скільки секунд застосунок має зачекати перед наступним запитом. Ваш HTTP-клієнт мусить перевіряти цей заголовок і дотримуватися його значення.

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

Найкращі практики для промислового середовища

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

1. Асинхронна обробка через черги повідомлень

Ніколи не надсилайте електронні листи синхронно всередині вхідного веб-запиту чи виклику API. Якщо HTTP-запит одразу викликає Microsoft Graph, користувачеві доводиться чекати завершення мережевого обміну, а якщо Graph на мить стане недоступним, ваш веб-запит завершиться помилкою. Натомість надсилайте корисне навантаження листів у чергу повідомлень (наприклад, Azure Service Bus, RabbitMQ або AWS SQS), а окремий фоновий робочий процес вибиратиме завдання з черги та асинхронно виконуватиме виклик Graph API.

2. Моніторинг і сповіщення

Інструментуйте конвеєр надсилання електронних листів надійним журналюванням і метриками. Відстежуйте такі показники, як загальна кількість надісланих повідомлень, частка помилок, середня кількість повторних спроб і затримка отримання токенів. Налаштуйте сповіщення про аномальні сплески помилок: наприклад, якщо частка помилок HTTP 403 або 429 перевищує певний поріг, команда експлуатації має отримати сповіщення негайно.

3. Принцип найменших привілеїв

Регулярно перевіряйте реєстрації застосунків в Azure AD. Чи справді вашому застосунку потрібні широкі дозволи на рівні організації, чи можна обмежити доступ до конкретних поштових скриньок? Періодично переглядайте надані згоди, щоб вилучати застосунки, які вже не використовуються, і відкликати їхній доступ.

Висновок

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

Дякуємо, що слухали подкаст і читали цю статтю. Якщо вам сподобався цей посібник, обов’язково підпишіться на подкаст, поділіться статтею з колегами-інженерами та залиште коментар із темами, які ви хотіли б почути в наступних випусках. Гарного коду!

Entities in this article

Microsoft Graph Microsoft Entra ID HTTP Application registration OAuth 2.0 Client secret Microsoft Entra Microsoft .NET JSON

Related articles

RSS