I am encountering an issue while attempting to send a reply via the Microsoft Graph API. The operation fails with a 401 error, indicating that message posting in application-only context is restricted to import purposes.
Granted API Permissions and types:
- ChannelMessage.Read.All Application
- ChannelMessage.ReadWrite Delegated
- ChannelMessage.Send Delegated
- Chat.ReadWrite.All Application
- Group.ReadWrite.All Application
- Teamwork.Migrate.All Application
- User.Read Delegated
python code:
- Generates access token
- use access token to post message in team channel or reply to existing message
import msal
import constants
import requests
def generate_access_token(app_id, client_secret, authority, scopes):
# Create a ConfidentialClientApplication with client credentials
client = msal.ConfidentialClientApplication(
client_id=app_id,
client_credential=client_secret,
authority=authority
)
# Acquire token for client using client credentials
token_response = client.acquire_token_for_client(scopes=scopes)
if 'access_token' in token_response:
# print(f" access_token = {token_response['access_token']}")
return token_response['access_token']
else:
print("Error acquiring token:", token_response.get("error_description"))
return None
def test_post_message_to_channel( app_id, client_secret, authority, scopes, team_id, channel_id, message_content):
access_token = generate_access_token(app_id, client_secret, authority, scopes)
url = f"https://graph.microsoft.com/v1.0/teams/{team_id}/channels/{channel_id}/messages"
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
payload = {
"body": {
"content": message_content
}
}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 201:
print("Message posted successfully!")
return response.json()
else:
print("Failed to post message:", response.status_code, response.text)
return None
def test_reply_message_to_channel(app_id, client_secret, authority, scopes, team_id, channel_id, message_id, reply_content):
# Get access token
access_token = generate_access_token(app_id, client_secret, authority, scopes)
# if 'access_token' not in token_response:
# print("Error acquiring token:", token_response.get("error_description"))
# return
# Define the API endpoint and reply payload
url = f'https://graph.microsoft.com/v1.0/teams/{team_id}/channels/{channel_id}/messages/{message_id}/replies'
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json'
}
payload = {
"body": {
"content": reply_content
}
}
# Send the reply to the existing post
response = requests.post(url, headers=headers, json=payload)
# Check if the reply was sent successfully
if response.status_code == 201:
print("Reply sent successfully!")
else:
print("Failed to send reply:", response.status_code, response.text)
# Usage
if __name__ == "__main__":
test_reply_message_to_channel(
app_id=constants.APP_ID,
client_secret=constants.CLIENT_SECRET,
authority =constants. AUTHORITY,
scopes=constants.SCOPES,
team_id=constants.TEAM_ID,
channel_id=constants.CHANNEL_ID,
message_id=constants.MESSAGE_ID,
reply_content=constants.MESSAGE_CONTENT
)
Error Message Received:
{
"error": {
"code": "Unauthorized",
"message": "Message POST is allowed in application-only context only for import purposes. Refer to https://docs.microsoft.com/microsoftteams/platform/graph-api/import-messages/import-external-messages-to-teams for more details.",
"innerError": {
"date": "2024-11-26T12:10:19",
"request-id": "da3b9b53-43d3-407a-9608-9797217e4909",
"client-request-id": "da3b9b53-43d3-407a-9608-9797217e4909"
}
}
}
I'm afraid we can't use client-credential-flow here for sending message to channel. Or is there another way around this that does not require user sign in.