Если вы хотите отправить содержимое 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 регистрируются для устранения неполадок.
Если вы хотите отправить содержимое MIME (например, HTML и обычный текст) с помощью Microsoft Graph на Python, вот руководство о том, как подписать сообщение MIME с помощью S/MIME и отправить его в Microsoft Graph. Этот код демонстрирует, как обрабатывать аутентификацию OAuth, подписывать электронное письмо с помощью S/MIME и кодировать его для совместимости с Graph API. Для этого процесса требуется: [list] [*]Получение токена OAuth: используйте учетные данные на основе сертификата для получения токена доступа. [*]Создание MIME-сообщения: создайте MIME сообщение с альтернативным открытым текстом и частями HTML. [*]Подписание S/MIME: Подпишите сообщение MIME с помощью закрытого ключа и сертификата. [*]Создание черновика: создайте черновик электронного письма с подписанным содержимым MIME, используя Microsoft Graph. [/list] Вот полный код:[code]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 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"
# **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}") [/code] [b]Объяснение[/b] [list] [*]Генерация токена OAuth: функция __get_graph_oauth_token извлекает токен доступа, необходимый для Microsoft Graph использует учетные данные на основе сертификата. [*]Подписание S/MIME: [list] Функция create_signed_mime_message создает альтернативное сообщение MIME с обоими простыми текстовую и HTML-части. [*]Это сообщение затем подписывается с помощью Sign_message с соответствующим секретным ключом и цепочкой сертификатов в формате PEM. [/list]
[*][b]Кодировка Crucial Base64 для графика:[/b] [list] Строка кодирования [b]mime_base64 = base64.encodebytes(signed_mime_message.as_string().encode().replace(b'\n', b'\r\n'))[/b] необходим для обеспечения совместимости с API Graph.< /li> Microsoft Graph ожидает содержимое MIME в формате Base64 с окончаниями строк \r\n, поэтому эта настройка является ключом к успешной передаче. [*][b]Если если этот шаг выполнен неправильно, Outlook может не интерпретировать подпись S/MIME должным образом. Вместо этого электронное письмо можно преобразовать в формат winmail.dat (Тип контента: application/ms-tnef), который является форматом расширенного текста Outlook. Это препятствует правильному отображению подписи S/MIME. Кроме того, результаты аутентификации могут показывать dkim=none и dmarc=none, что указывает на то, что Outlook неправильно интерпретировал подпись S/MIME.[/b] [/list]
[/list] [b]Ключевые моменты[/b] [list] [*]Сообщение, подписанное S/MIME: Подписание помогает проверить подлинность отправителя, а этот код обеспечивает безопасную подпись содержимого MIME. [*]Асинхронный запрос POST: использование httpx.AsyncClient для эффективных неблокирующих HTTP-запросов. [*]Обработка ошибок: ответы об ошибках API Graph регистрируются для устранения неполадок. [/list]
В настоящее время мы используем базовый код Google Appengine Flex для среды выполнения Java8, и нам необходимо перенести его как минимум на Java 17, поскольку в этом месяце поддержка прекращается. Не могли бы вы дать пошаговое руководство по...
Как открыть Google Play Store напрямую из приложения Android, не показывая опцию браузера? Я попробовал следующий код, но все равно вижу приглашение выбрать приложение:
final String appPackageName = getPackageName(); // or replace with your app...
expedia Main Service Number Service-1-800-Expedia® или 🔰1-877- (747) -6^909 или 🔰1-877- (747) -6^909 OTA (живое лицо), доступно 24/7. В этом руководстве объясняется, как эффективно связаться с обслуживанием клиентов Expedia с помощью вариантов...