Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

O365 connectors within Teams will be deprecated #30

Open
xolf opened this issue Jul 5, 2024 · 17 comments
Open

O365 connectors within Teams will be deprecated #30

xolf opened this issue Jul 5, 2024 · 17 comments

Comments

@xolf
Copy link

xolf commented Jul 5, 2024

Hey,

since today Teams appends the following messages automatically to messages send via this package:

Action Required: O365 connectors within Teams will be deprecated and notifications from this service will stop.
Learn more about the timing and how the Workflows app provides a more flexible and secure experience. If you want to continue receiving these types of messages, you can use a workflow to post messages from a webhook request. Set up workflow

Are there any guides or tips for an migration?

@EdyStauch
Copy link

I tried creating a "workflow" as indicated in the message, and using the URL provided but it doesn't seem to work.

@jbraband
Copy link

jbraband commented Jul 8, 2024

I tried creating a "workflow" as indicated in the message, and using the URL provided but it doesn't seem to work.

I did the same and am getting a 400 Rad Request response with nothing else as to the cause.

@xolf
Copy link
Author

xolf commented Jul 9, 2024

Same here. The integrated Workflow in Teams didn't worked for me. I created a Power Automate Flow with an HTTP Endpoint (requires Premium subscription) and then send the messages via the Microsoft Teams connector to Teams.

One benefit of this solution is, you can also target individual users or group chats, in addition to channels.

@OGLECB
Copy link

OGLECB commented Jul 10, 2024

I have done some research, it looks like Microsoft has changed the format of the payload - So I think some changes will need to be made to the code.

@jsandfordhughescoop
Copy link

jsandfordhughescoop commented Jul 11, 2024

I have been doing some research on this, the new 'workflow' way is not very well documented. I have managed to get a JSON webhook to create an 'AdaptiveCard'.

The tricky part is getting the workflow setup correctly.

First head into teams and create a new workflow, start a blank workflow. For the trigger, you want to search for webhook and select the Microsoft Teams Webhook.

Next add a step to the workflow, it should look like this so far:

CleanShot 2024-07-11 at 10 07 53@2x

Now search for "Apply to each" and select it as an action. In the "Select an output" box you want to choose the dynamic content from the righthand side, select "Attachments". It should now look like this:

CleanShot 2024-07-11 at 10 09 17@2x

Next add another action and find "Post card in chat or channel" and fill in the details for your required destination. (Make sure you choose the correct "Post as" option as flow bots cannot post into private channels).

You should now have something like this:

CleanShot 2024-07-11 at 10 12 27@2x

Now in the adaptive chat box you need to create an "expression" and in the expression you need to put the following "item().content". It should look like the following:

CleanShot 2024-07-11 at 10 16 58@2x

Hit okay on the expression and it will put it into the adaptive card box, then save the workflow.

Once saved you can click on the webhook trigger at the top and copy the webhook url.

Now send a POST request to the webhook with the JSON below

{ "attachments": [ { "contentType": "application/vnd.microsoft.card.adaptive", "contentUrl": null, "type": "AdaptiveCard", "content": { "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.2", "body": [ { "type": "TextBlock", "wrap": true, "text": "This is the text of a card" } ], "actions": [ { "type": "Action.OpenUrl", "title": "Github URL", "url": "https://github.com" } ] } } ] }

If you format the JSON you will see that there is an attachments array and the attachment has a content object. This content object is a valid schema for AdaptiveCards.io. You can view the schema here: AdaptiveCards.io.

I know this does not currently fix the issue with the package however it gives a good head start to someone wanting to create a PR. If I can get around to it, I will work on the PR myself.

If anyone needs anymore info, please let me know.

@jbraband
Copy link

jbraband commented Jul 12, 2024

@jsandfordhughescoop awesome tutorial. I was able to build the workflow as you describe and get your test POST request to show the card in the Teams channel.

I could not get the older MessageCard (that is built in the class \NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage) to work through this.

Has anyone used this repo before? https://github.com/sebbmeyer/php-microsoft-teams-connector

It has a class that builds the AdaptiveCard schema and also a way to send it to a Teams webhook endpoint. I like using the Laravel Notification system for things like this, but what would be the chances of a PR using sebbmeyer/php-microsoft-teams-connector to be merged into this repo?

@jbraband
Copy link

Looks like maybe @Tob0t is the main maintainer of this repo. @Tob0t do you have an opinion on expanding this package to handle the AdaptiveCard schema?

@jbraband
Copy link

Just a note that Message Cards are marked as Legacy in the Microsoft documentation

https://learn.microsoft.com/en-us/outlook/actionable-messages/message-card-reference

@jglagrimas
Copy link

So any idea if the workflow is disabled on our organization?
any alternatives?

@jsandfordhughescoop
Copy link

So any idea if the workflow is disabled on our organization? any alternatives?

A quick google and it does not seem disabling workflows is an option in Azure / teams admin

@jglagrimas
Copy link

image
@jsandfordhughescoop

@jsandfordhughescoop
Copy link

Thats interesting! Sorry nothing came up in a google search. As far as I am aware, teams are EOL all "connectors" so the only way going forward are workflows.

Maybe chat to your admins and see what they can do?

@jglagrimas
Copy link

Thats interesting! Sorry nothing came up in a google search. As far as I am aware, teams are EOL all "connectors" so the only way going forward are workflows.

Maybe chat to your admins and see what they can do?

thanks @jsandfordhughescoop

i will reach to them.

@OGLECB
Copy link

OGLECB commented Jul 15, 2024

Thats interesting! Sorry nothing came up in a google search. As far as I am aware, teams are EOL all "connectors" so the only way going forward are workflows.
Maybe chat to your admins and see what they can do?

thanks @jsandfordhughescoop

i will reach to them.

@jglagrimas Your organisation looks like they have set up conditional access to the Power Automate Workflows - hence why you are seeing it as disabled by the orgainisation.

image

@Issa-projects
Copy link

Issa-projects commented Jul 16, 2024

I have a current working workarround.
Create a new class to extend MicrosoftTeamsMessage:

<?php

namespace App\Services\MicrosoftTeams;

use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;

class TeamsNotification extends MicrosoftTeamsMessage
{
    protected $payload = [];
    protected string $type = "Good";

    /** @var string webhook url of recipient. */
    protected $webhookUrl = null;

    public function __construct()
    {
        parent::__construct();
        $this->payload = [
            "\$schema" => "https://adaptivecards.io/schemas/adaptive-card.json",
            "type" => "AdaptiveCard",
            "version" => "1.0",
        ];


    }

    public static function create(string $content = ''): self
    {
        return new self();
    }

    public function title(string $title, array $params = []): self
    {
        $this->payload["body"][] = [
            "type" => "TextBlock",
            "wrap" => true,
            "style" => "heading",
            "text" => $title,
            "weight" => "bolder",
            "size" => "large",
        ];

        return $this;
    }

    public function type(string $type): self
    {
        $types = ["info" => "Good", "error" => "Attention", "warning" => "Warning", "success" => "Good"];
        $this->type = $types[$type];

        return $this;
    }

    /**
     * @throws \Exception
     */
    public function to(?string $webhookUrl): self
    {
        if (!$webhookUrl) {
            throw new \Exception("Webhook url is required. Tried to send a teams notification without a webhook url.");
        }
        $this->webhookUrl = $webhookUrl;

        return $this;
    }

    public function content(string $content, array $params = []): self
    {
        // add the content as a new text block
        $this->payload["body"][] = [
            "type" => "TextBlock",
            "wrap" => true,
            "text" => $content,
            "size" => "medium",
            "separator" => true,

        ];
        return $this;
    }

    public function button(string $text, string $url = '', array $params = []): self
    {
        $this->payload["actions"][] = [
            "type" => "Action.OpenUrl",
            "title" => $text,
            "url" => $url,
            "style" => "positive",
        ];

        return $this;
    }

    public function addStartGroupToSection($sectionId = 'standard_section'): self
    {

        return $this;
    }

    public function fact(string $name, string $value, $sectionId = 'standard_section'): self
    {
        $factset = collect($this->payload['body'])->filter(function ($item) {
            return $item['type'] === "FactSet";
        });
        if($factset->isEmpty()) {
            $factset = [
                "type" => "FactSet",
                "facts" => [],
            ];
        }
        $factset['facts'][] = [
            "title" => $name,
            "value" => $value,
        ];

        $this->payload['body'][] = $factset;
        return $this;
    }
    public function getWebhookUrl(): string
    {
        info("Sending to teams wb: $this->webhookUrl");
        return $this->webhookUrl;
    }
    public function toArray(): array
    {
        // check and get the first text block and set the color to the type
         if($this->payload["body"][0] && $this->payload["body"][0]["type"] === "TextBlock") {
             $this->payload["body"][0]["color"] = $this->type;
         }

        return $this->payload;
    }
}

And now, instead of:

return MicrosoftTeamsMessage::create()
    ->to(config('services.microsoft_teams.sales_url'))
    ->type('success')
    ->title('Subscription Created')
    ->content('Yey, you got a **new subscription**. Maybe you want to contact him if he needs any support?')
    ->button('Check User', 'https://foo.bar/users/123');

Do this:

return TeamsNotification::create()
    ->to(config('services.microsoft_teams.sales_url'))
    ->type('success')
    ->title('Subscription Created')
    ->content('Yey, you got a **new subscription**. Maybe you want to contact him if he needs any support?')
    ->button('Check User', 'https://foo.bar/users/123');

For creating a new workflow in teams:

Go to teams -> click on the three dots on the left side and select workflows>
image

image

In the "Adaptive Card" field, make sure to choose expression and use triggerBody() as value.

@peterthomson
Copy link

peterthomson commented Aug 25, 2024

Ok, so it seems that we've all been granted a reprieve by Microsoft from August 2024 until December 2025 (although we'll have to make a URL change in December 2024 to opt-in). But long-term, it certainly sounds like the Webhook to Workflow pathway is going to be the only option for sending notifications to Teams. And that will in turn probably require the Adaptive Card format. More info here: https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/

In terms of a way forwards for the Notification Channel driver approach (this package) we can take inspiration from a couple of packages that have leaned into the Workflow pattern (and Adaptive Cards):
https://github.com/osa-eg/laravel-teams-notification
https://github.com/sebbmeyer/php-microsoft-teams-connector/

@Tob0t
Copy link
Collaborator

Tob0t commented Aug 31, 2024

Hi, sorry for the late response 🙈
Since I am no longer actively using teams, I could not find (free)time to migrate to prepare an alternative method.
I have no strong opinion towards which way to go, but I am open to suggestions (or even better, a PR ;))
This package is open source, so feel free to create a PR - I am willing to review and merge it if it is a satisfying solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants