Ricardo Vilaça
Ricardo Vilaça

Reputation: 996

Send automated messages to Microsoft Teams using Python

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

Answers (5)

lerry.lca
lerry.lca

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:

enter image description here

Instruction is bellow:

  1. Creatge a webhook in MS Teams

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.

  1. Install pyteams(required packages)

Refer to the officail doc: https://pypi.org/project/pymsteams/

pip install pymsteams pydantic

  1. Create a module named messenger.py
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}")
  1. Use example

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

NrY
NrY

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

Zev Averbach
Zev Averbach

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:

  1. Navigate to the channel where you want to add the webhook and select (•••) Connectors from the top navigation bar.
  2. Search for Incoming Webhook, and add it.
  3. Click Configure and provide a name for your webhook.
  4. Copy the URL which appears and click "OK".

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

AlanK
AlanK

Reputation: 9823

1. Create a webhook in MS Teams

Add an incoming webhook to a Teams channel:

  1. Navigate to the channel where you want to add the webhook and select (•••) Connectors from the top navigation bar.
  2. Search for Incoming Webhook, and add it.
  3. Click Configure and provide a name for your webhook.
  4. Copy the URL which appears and click "OK".

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:

Add a webook to MS Teams

Python pymsteams library

Upvotes: 132

nirojshrestha019
nirojshrestha019

Reputation: 2955

Send Msteams notification without an additional package.

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

Related Questions