Отправка содержимого MIME с помощью Microsoft Graph на Python: пошаговое руководство по подписанию S/MIMEPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Отправка содержимого MIME с помощью Microsoft Graph на Python: пошаговое руководство по подписанию S/MIME

Сообщение Anonymous »

Если вы хотите отправить содержимое MIME (например, HTML и обычный текст) с помощью Microsoft Graph на Python, вот руководство о том, как подписать сообщение MIME с помощью S/MIME и отправить его в Microsoft Graph. Этот код демонстрирует, как обрабатывать аутентификацию OAuth, подписывать электронное письмо с помощью S/MIME и кодировать его для совместимости с Graph API.
Для этого процесса требуется:
  • Получение токена OAuth: используйте учетные данные на основе сертификата для
    получения токена доступа.
  • Создание MIME-сообщения: создайте MIME
    сообщение с альтернативным открытым текстом и частями HTML.
  • Подписание S/MIME:
    Подпишите сообщение MIME с помощью закрытого ключа и сертификата.
  • Создание черновика: создайте черновик электронного письма с подписанным содержимым MIME, используя
    Microsoft Graph.
Вот полный код:

Код: Выделить всё

from azure.identity import CertificateCredential
from azure.core.credentials import AccessToken
import base64
import httpx
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from smail import sign_message

# Step 1: Retrieve OAuth token using Certificate-based credential
def __get_graph_oauth_token(self) -> str:
credential: CertificateCredential = self.__get_graph_credential()
token: AccessToken = credential.get_token(self.scope)
return token.token

def __get_graph_credential(self) -> CertificateCredential:
crypto_utils: CryptoUtils = CryptoUtils()
certificate_data: bytes = crypto_utils.get_pfx_certificate(cert_name=self.domain_cert_name)
return CertificateCredential(
tenant_id=self.tenant_id,
client_id=self.client_id,
certificate_data=certificate_data
)

# Step 2: Create MIME message with S/MIME signing
def create_signed_mime_message(self, subject: str, body: str, to_email: str, from_email: str):
# Retrieve the private key, main certificate, and additional certs in PEM format
private_key_pem, main_certificate_pem, additional_certs_pem = self.__get_auth_priv_rep_certificate_chain()

# Step 2.1: Create inner alternative part for plain text and HTML
inner_alternative = MIMEMultipart("alternative")
inner_alternative.attach(MIMEText(body, "plain", "utf-8"))
inner_alternative.attach(MIMEText(body, "html", "utf-8"))
inner_alternative["From"] = from_email
inner_alternative["To"] = to_email
inner_alternative["Subject"] = subject

# Step 2.2: Sign the message with temporary key and cert files
signed_msg = sign_message(
message=inner_alternative,
key_signer=private_key_pem,
cert_signer=main_certificate_pem,
additional_certs=[additional_certs_pem]
)
return signed_msg

# Step 3: Create a draft email with MIME content using Microsoft Graph
async def create_draft_email_with_mime(self, subject: str, body: str, to_email: str):
access_token: str = self.__get_graph_oauth_token()
url: str = f"https://graph.microsoft.com/v1.0/users/{self.from_email}/messages"

headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "text/plain",
"Prefer": 'IdType="ImmutableId"'
}

# Step 3.1: Create and sign MIME message
signed_mime_message = self.create_signed_mime_message(
subject=subject,
body=body,
to_email=to_email,
from_email=self.from_email
)

# **CRUCIAL STEP**: Encode the MIME message in base64 and replace line breaks to ensure compatibility with Graph API
mime_base64 = base64.encodebytes(signed_mime_message.as_string().encode().replace(b'\n', b'\r\n'))

# Step 3.3: Send the signed MIME content as draft to Microsoft Graph
async with httpx.AsyncClient() as client:
response = await client.post(url, headers=headers, content=mime_base64)

if response.status_code == 201:
return response.json()
else:
self.logger.error(f"Error creating draft! Status: {response.status_code}.  Response: {response.text}")
Объяснение
  • Генерация токена OAuth: функция __get_graph_oauth_token извлекает токен доступа, необходимый для Microsoft Graph использует учетные данные на основе сертификата.
  • Подписание S/MIME:
    • Функция create_signed_mime_message создает альтернативное сообщение MIME с обоими простыми текстовую и HTML-части.
    • Это сообщение затем подписывается с помощью Sign_message с соответствующим секретным ключом и цепочкой сертификатов в формате PEM.
  • Кодировка Crucial Base64 для графика:
    • Строка кодирования mime_base64 = base64.encodebytes(signed_mime_message.as_string().encode().replace(b'\n', b'\r\n')) необходим для обеспечения совместимости с API Graph.< /li>
      Microsoft Graph ожидает содержимое MIME в формате Base64 с окончаниями строк \r\n, поэтому эта настройка является ключом к успешной передаче.
    • Если если этот шаг выполнен неправильно, Outlook может не интерпретировать подпись S/MIME должным образом. Вместо этого электронное письмо можно преобразовать в формат winmail.dat (Тип контента: application/ms-tnef), который является форматом расширенного текста Outlook. Это препятствует правильному отображению подписи S/MIME. Кроме того, результаты аутентификации могут показывать dkim=none и dmarc=none, что указывает на то, что Outlook неправильно интерпретировал подпись S/MIME.
Ключевые моменты
  • Сообщение, подписанное S/MIME: Подписание помогает проверить подлинность отправителя, а этот код обеспечивает безопасную подпись содержимого MIME.
  • Асинхронный запрос POST: использование httpx.AsyncClient для эффективных неблокирующих HTTP-запросов.
  • Обработка ошибок: ответы об ошибках API Graph регистрируются для устранения неполадок.


Подробнее здесь: https://stackoverflow.com/questions/791 ... e-with-s-m
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»