Reputation: 996
I want to run a script of Python and in the end send the results in a text format to a couple of employees through MS Teams
Is there any already build library that would allow me to send a message in Microsoft Teams through Python code?
Upvotes: 64
Views: 171631
Reputation: 31
I encapsulated a class based on pyteams, which can easily send messages with titles, text, links and mentions.
First see the test result:
Instruction is bellow:
Refer to the official doc: https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook?tabs=newteams%2Cjavascript
Ensure you have saved your webhook url after created successfully.
Refer to the officail doc: https://pypi.org/project/pymsteams/
pip install pymsteams pydantic
from pymsteams import connectorcard, TeamsWebhookException
import logging
from typing import List, Optional
import copy
from pydantic import BaseModel
# Initialize logging
logger = logging.getLogger(__name__)
# Define the default message payload template to send to Teams
DEFAULT_PAYLOAD_TEMPLATE = {
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"type": "AdaptiveCard",
"body": [],
"actions": [],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0",
"msteams": {"width": "Full"}
}
}]
}
class User(BaseModel):
"""
User class representing a user to be mentioned in the message,
with optional fields for email and oid.
"""
name: str
email: Optional[str] = ""
oid: Optional[str] = ""
class MessageDTO(BaseModel):
"""
MessageDTO class is a Data Transfer Object for encapsulating the details of the message.
"""
text: str
title: Optional[str] = None
mention_users: Optional[List[User]] = None
link_title: Optional[str] = None
link_url: Optional[str] = None
class TeamsMessenger:
"""
Implementation of Messenger for Microsoft Teams.
"""
def __init__(self, webhook_url, messageDTO: MessageDTO):
self.messageDTO = messageDTO
self.my_messenger = connectorcard(hookurl=webhook_url) # Initialize Teams connector with the webhook URL
def send_message(self):
"""Construct and send a message to Teams using the connector card."""
try:
# Initialize the default payload template
self.my_messenger.payload = copy.deepcopy(DEFAULT_PAYLOAD_TEMPLATE)
# Add message title if provided
if self.messageDTO.title:
self.my_messenger.payload["attachments"][0]["content"]["body"].append({
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"text": self.messageDTO.title
})
# Add message text
self.my_messenger.payload["attachments"][0]["content"]["body"].append({
"type": "TextBlock",
"size": "Medium",
"text": self.messageDTO.text,
"wrap": True
})
# Add mentions based on provided users
if self.messageDTO.mention_users:
mentions_entities = [] # List to hold mention entities
mention_text = "" # Accumulate mention text for display in message
for mention_user in self.messageDTO.mention_users:
mentions_entities.append({
"type": "mention",
"text": f"<at>{mention_user.name}</at>", # Use markdown format for mentions
"mentioned": {
"id": mention_user.email, # User identifier (assumed to be email)
"name": mention_user.name
}
})
# Format the mention text
mention_text += f"@<at>{mention_user.name}</at> "
self.my_messenger.payload["attachments"][0]["content"]["body"].append({
"type": "TextBlock",
"text": mention_text
})
self.my_messenger.payload["attachments"][0]["content"]["msteams"]["entities"] = mentions_entities
# Add action link if title and URL are provided
if self.messageDTO.link_title and self.messageDTO.link_url:
self.my_messenger.payload["attachments"][0]["content"]["actions"].append({
"type": "Action.OpenUrl",
"title": self.messageDTO.link_title,
"url": self.messageDTO.link_url
})
# Send the constructed message to Microsoft Teams
self.my_messenger.send()
except TeamsWebhookException as e: # Handle specific Teams webhook exceptions
logger.error(f"An error occurred while sending Teams message. {e}")
except Exception as e: # Handle any other exceptions
logger.error(f"An error occurred while processing the sending of the Teams message. {e}")
In your place that need to send Teams message, you can simply use the messenger class like bellow:
from msteams.messenger import TeamsMessenger, MessageDTO, User # Import TeamsMessenger, MessageDTO, and User classes
if __name__ == '__main__':
TEST_MESSENGER_WEBHOOK_URL = "your webhook url" # Set the webhook URL for testing
# Create an instance of MessageDTO to encapsulate the message to be sent
messageDTO = MessageDTO(
title="This is title", # Message title
text="This is content", # Message content
link_title="Visit xxx", # Link title
link_url="xxx", # Link URL
mention_users=[User(name="lerry", email="xxx")] # List of users to mention; contains one user here
)
# Create an instance of TeamsMessenger, passing the webhook URL and the messageDTO
my_messenger = TeamsMessenger(webhook_url=TEST_MESSENGER_WEBHOOK_URL,
messageDTO=messageDTO)
# Send the message
my_messenger.send_message()
Upvotes: 2
Reputation: 309
Adding a code snippet based on Python's requests library for completeness.
Compared to the other answers this is useful as all major Linux distros provide a python3-requests
package but not a python3-msteams
package.
#!/usr/bin/env python3
import requests
WEBHOOK_URL = "https://..."
def postTeamsMessage(text):
jsonData = {
"text": text
}
requests.post(WEBHOOK_URL, json=jsonData)
postTeamsMessage("Hello there")
Upvotes: 10
Reputation: 1134
Here's a simple, third-party package-free solution inspired by @nirojshrestha019's solution, with fewer steps and updated instructions for Microsoft's ever-changing UIs:
1. Create a webhook in MS Teams
Add an incoming webhook to a Teams channel:
2. Make a script!
import json
import sys
from urllib import request as req
class TeamsWebhookException(Exception):
pass
WEBHOOK_URL = "https://myco.webhook.office.com/webhookb2/abc-def-ghi/IncomingWebhook/blahblah42/jkl-mno"
def post_message(message: str) -> None:
request = req.Request(url=WEBHOOK_URL, method="POST")
request.add_header(key="Content-Type", val="application/json")
data = json.dumps({"text": message}).encode()
with req.urlopen(url=request, data=data) as response:
if response.status != 200:
raise TeamsWebhookException(response.reason)
if __name__ == "__main__":
post_message("hey this is my message")
Upvotes: 17
Reputation: 9823
1. Create a webhook in MS Teams
Add an incoming webhook to a Teams channel:
2. Install pymsteams
pip install pymsteams
3. Create your python script
import pymsteams
myTeamsMessage = pymsteams.connectorcard("<Microsoft Webhook URL>")
myTeamsMessage.text("this is my text")
myTeamsMessage.send()
More information available here:
Upvotes: 132
Reputation: 2955
A simple way to send messages to teams without using any external modules. This is basically under the hood of pymsteams module. It is more useful when you are using AWS Lambda as you don't have to add layers in Lambda or supply pymsteams module as a deployment package.
import urllib3
import json
class TeamsWebhookException(Exception):
"""custom exception for failed webhook call"""
pass
class ConnectorCard:
def __init__(self, hookurl, http_timeout=60):
self.http = urllib3.PoolManager()
self.payload = {}
self.hookurl = hookurl
self.http_timeout = http_timeout
def text(self, mtext):
self.payload["text"] = mtext
return self
def send(self):
headers = {"Content-Type":"application/json"}
r = self.http.request(
'POST',
f'{self.hookurl}',
body=json.dumps(self.payload).encode('utf-8'),
headers=headers, timeout=self.http_timeout)
if r.status == 200:
return True
else:
raise TeamsWebhookException(r.reason)
if __name__ == "__main__":
myTeamsMessage = ConnectorCard(MSTEAMS_WEBHOOK)
myTeamsMessage.text("this is my test message to the teams channel.")
myTeamsMessage.send()
reference: pymsteams
Upvotes: 25