DEV Community

Cover image for Okta Workflows How-To: Send stylized messages with MS Teams
Bryan Barrows for Okta Workflows

Posted on

3

Okta Workflows How-To: Send stylized messages with MS Teams

Okta Workflows makes it easy to build automations that notify or alert your teams with connectors to services like Slack and MS Teams.

Someone recently asked, "Why can't I add line-breaks to my MS Teams messages?"

As it turns out, we need to leverage the Custom API Action card so that we can specify that our content is HTML, rather than text.

With the default Send Message to Channel card, our content is sent as text and line-breaks are ignored. Writing our message in HTML allows us to include line-breaks, lists, headers, style our text with fonts & colors, and more.


We can use the Text - Compose card to write our HTML message.

Text - Compose card with HTML message

We can use a pair of Object - Construct cards to construct our request payload. We create a message object that contains our message content and specifies our contentType as html. We then nest the message object in an object called body.

POST to your Teams endpoint

The payload should look something like:

{
  "body": {
    "contentType": "html",
    "content": "<h1 style=\"color:#FF0000;font-weight:bold\">Attention!</h1> <p>Thanks for reading! &#127867</p>"
  }
}
Enter fullscreen mode Exit fullscreen mode

Finally, we use the Custom API Action card to

POST /teams/{team-id}/channels/{channel-id}/messages
Enter fullscreen mode Exit fullscreen mode

Teams message result


Additional Resources:


Feel free to download my example, import it and try it out - just update the Relative URL in the Custom API Action to point at your own Team and Channel:

{"type":"flopack","version":"1.3.0","created":"2022-10-14T18:33:43.431Z","flags":{"auto-transform":true,"looseBooleans":true,"looseStrings":true,"looseNulls":true},"data":{"flos":{"f838207c-ea09-41bb-9d2f-b44bbe482a37":{"id":"f838207c-ea09-41bb-9d2f-b44bbe482a37","name":"MS Teams HTML CAPIA","description":"How to construct a body and use the Custom API Action card to send customized messages with MS Teams. ","data":{"id":null,"uuid":"f838207c-ea09-41bb-9d2f-b44bbe482a37","display":{"preview":[{"module":"string","name":"compose","kernel":true},{"module":"microsoftteams","name":"customAPIAction","kernel":false},{"module":"object","name":"construct","kernel":true},{"module":"object","name":"construct","kernel":true},{"module":"control","name":"noop","kernel":true},{"module":"control","name":"comment","kernel":true},{"module":"control","name":"comment","kernel":true},{"module":"control","name":"comment","kernel":true}],"isCallable":false},"tree":{"id":2,"name":"empty","description":"This flow has been build w/o a tree and uses the newer, async, Addressing module."},"methods":[{"joins":{},"address":"root:kernel:string:0.0.1:compose","parents":{"version":{"address":"root:kernel:string:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:string","key":"string","data":{"name":"string"}}},"uuid":"kt1sryRSk","branches":{},"node":{"key":"compose","data":{"name":"Compose"},"model":{"type":"method","_v":2,"key":"compose","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Compose","description":"Enter free form text and optionally drag fields into your text like a mail merge."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":true,"rules":{"*":{"types":["string"],"collection":false}},"data":{"wfVtqsFzE7":{"id":"wfVtqsFzE7","group":null,"key":"_text_","value":{"type":"string","collection":false,"data":"<h1 style=\"color:#FF0000;font-weight:bold\">Attention!</h1>\n<h2>You can style your Teams messages &#127881</h2>\n<p> Try it out yourself, you can: </p>\n<ul>\n<li>Include bullet-point lists.</li>\n<li>Include line-breaks :) Here, we'll try one <br> out</li>\n<li>Style your text with <span style=\"color:blue\">color</span>, <span style=\"font:courier\">fonts, <i>italics</i>, etc. </li>\n</ul>\n<p>Thanks for reading! &#127867</p>","available":[],"error":false},"required":true,"ref":false,"metadata":{"index":0},"flags":"d"}}},"outputs":{"extensible":false,"data":{"WrkEos1mBl":{"id":"WrkEos1mBl","group":null,"key":"output","value":{"type":"string","collection":false,"data":"","available":[],"error":false},"ref":false,"metadata":{"index":0,"description":"","displayname":"HTML Message Content"},"_used":true}}},"runtime":{}}},"pins":{"WrkEos1mBl":{"jBP-u5Pg0":[{"input":"TdpOmJU6a","transform":null}]}}},{"joins":{},"address":"root:channels:http:microsoftteams:1.0.372:customAPIAction","parents":{"version":{"address":"root:channels:http:microsoftteams:1.0.372","key":"1.0.372","data":{"name":"1.0.372","id":736}},"channel":{"address":"root:channels:http:microsoftteams","key":"microsoftteams","data":{"name":"microsoftteams","id":113}}},"uuid":"tXhEuIzlo","branches":{},"node":{"key":"customAPIAction","data":{"name":"Custom API Action"},"model":{"type":"method","_v":2,"key":"customAPIAction","executable":true,"displayed":true,"async":true,"cooperative":false,"mirrored":false,"compat":false,"inlined":false,"dependencies":[],"timeout":30000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":33604,"name":"Custom API Action","description":null},"meta":{"703e4b3e-08e5-4e3f-a85b-e43984235aa1":{"id":"_A1bWv5mAW7","address":{"key":null,"group":"Request","fieldIndex":0,"defaultValue":{"path":[],"method":"getHttpInputs","data":{}},"namespace":"input"}}},"config":"4de3d294-ac61-48ef-af42-6aa336042eda","partnerChannelKeys":227,"inputs":{"extensible":false,"rules":{},"groupRules":{"Request":{"extensible":false,"reserved":{},"index":0,"type":"object"}},"data":{"r8Cf5gTtV6":{"id":"r8Cf5gTtV6","group":"parameters","key":"requestType","value":{"error":false,"proxy":false,"check":false,"type":"string","collection":false,"data":"POST","available":[]},"required":false,"ref":false,"metadata":{"type":"list","displayname":"Request Type","choices":[{"label":"GET","value":"GET"},{"label":"POST","value":"POST"},{"label":"PUT","value":"PUT"},{"label":"PATCH","value":"PATCH"},{"label":"DELETE","value":"DELETE"}],"dependencies":[],"optional":false,"ordering":0,"index":0},"flags":"p"},"Ss6eCzWP_":{"id":"Ss6eCzWP_","group":"Request","key":"Relative URL","value":{"error":false,"proxy":false,"check":false,"type":"string","collection":false,"data":"/teams/3ca570b9-93bb-4433-8119-afd971d64443/channels/19:a2a94a4f46334c2da2533c17152a9b78@thread.tacv2/messages","available":["string"]},"required":true,"ref":false,"metadata":{"index":1,"optional":false},"flags":"d"},"q-qI9mugPz":{"id":"q-qI9mugPz","group":"Request","key":"Query","value":{"error":false,"proxy":false,"check":false,"type":"object","collection":false,"data":{},"available":["string","object"]},"required":false,"ref":false,"metadata":{"index":2,"optional":false},"flags":"d"},"S2E33emtLq":{"id":"S2E33emtLq","group":"Request","key":"Headers","value":{"error":false,"proxy":false,"check":false,"type":"object","collection":false,"data":{},"available":["object"]},"required":false,"ref":false,"metadata":{"index":3,"optional":false},"flags":"d"},"1WW0uTBJ9":{"id":"1WW0uTBJ9","group":"Request","key":"Body","value":{"error":false,"proxy":false,"check":false,"type":"object","collection":false,"data":{},"available":["string","object"]},"required":false,"ref":false,"metadata":{"index":4,"optional":false},"flags":"d"}}},"outputs":{"extensible":false,"rules":{},"groupRules":{"Response":{"extensible":false,"reserved":{},"index":0,"type":"object"}},"data":{"SmRRJwggPQ":{"id":"SmRRJwggPQ","group":"Response","key":"Status Code","value":{"error":false,"type":"number","collection":false,"data":0,"available":["number"]},"ref":false,"metadata":{"index":0}},"_Mb5AqkPe0":{"id":"_Mb5AqkPe0","group":"Response","key":"Headers","value":{"error":false,"type":"object","collection":false,"data":{},"available":["object"]},"ref":false,"metadata":{"index":1}},"6QJmTFgOC_":{"id":"6QJmTFgOC_","group":"Response","key":"Body","value":{"error":false,"type":"object","collection":false,"data":{},"available":["object"]},"ref":false,"metadata":{"index":2}}}},"runtime":{},"display":{},"comments":"Makes an authenticated HTTP request to the Microsoft Teams Microsoft Graph API.","enableNewMetadata":true}},"pins":{}},{"joins":{},"address":"root:kernel:object:0.0.1:construct","parents":{"version":{"address":"root:kernel:object:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:object","key":"object","data":{"name":"object"}}},"uuid":"jBP-u5Pg0","branches":{},"node":{"key":"construct","data":{"name":"Construct"},"model":{"type":"method","_v":2,"key":"construct","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Construct","description":"Create an object from multiple inputs."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":true,"rules":{"*":{"types":["*"],"collection":"*"}},"data":{"BMYu42Vjm":{"id":"BMYu42Vjm","group":null,"key":"contentType","value":{"error":false,"proxy":false,"check":false,"type":"string","collection":false,"data":"html","available":["string","number","boolean","Date","Array","object","file","flo","folder"]},"required":false,"ref":false,"metadata":{"index":0,"custom":true},"flags":"d"},"TdpOmJU6a":{"id":"TdpOmJU6a","group":null,"key":"content","value":{"error":false,"proxy":false,"check":false,"type":"string","collection":false,"data":"","available":["string","number","boolean","Date","Array","object","file","flo","folder"]},"required":false,"ref":false,"metadata":{"index":1,"custom":true},"flags":"d"}}},"outputs":{"extensible":false,"data":{"Oc0SwZZIe2":{"id":"Oc0SwZZIe2","group":null,"key":"output","value":{"type":"object","collection":false,"data":{},"available":[],"error":false},"ref":false,"metadata":{"index":0,"description":"","displayname":"messageObject"},"_used":true}}},"runtime":{}}},"pins":{"Oc0SwZZIe2":{"YXOCDErQE":[{"input":"scnMgWv2y","transform":null}]}}},{"joins":{},"address":"root:kernel:object:0.0.1:construct","parents":{"version":{"address":"root:kernel:object:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:object","key":"object","data":{"name":"object"}}},"uuid":"YXOCDErQE","branches":{},"node":{"key":"construct","data":{"name":"Construct"},"model":{"type":"method","_v":2,"key":"construct","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Construct","description":"Create an object from multiple inputs."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":true,"rules":{"*":{"types":["*"],"collection":"*"}},"data":{"scnMgWv2y":{"id":"scnMgWv2y","group":null,"key":"body","value":{"error":false,"proxy":false,"check":false,"type":"object","collection":false,"data":{},"available":["string","number","boolean","Date","Array","object","file","flo","folder"]},"required":false,"ref":false,"metadata":{"index":0,"custom":true},"flags":"d"}}},"outputs":{"extensible":false,"data":{"Z6W6YHlW-N":{"id":"Z6W6YHlW-N","group":null,"key":"output","value":{"type":"object","collection":false,"data":{},"available":[],"error":false},"ref":false,"metadata":{"index":0,"description":"","displayname":"requestBody"},"_used":true}}},"runtime":{}}},"pins":{"Z6W6YHlW-N":{"tXhEuIzlo":[{"input":"1WW0uTBJ9","transform":null}]}}},{"joins":{},"address":"root:kernel:control:0.0.1:noop","parents":{"version":{"address":"root:kernel:control:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:control","key":"control","data":{"name":"control"}}},"uuid":"mgE-yllLA","branches":{},"node":{"key":"noop","data":{"name":"Noop"},"model":{"type":"method","_v":2,"key":"noop","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Noop","description":"No-op. Does not do anything."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":true,"data":{}},"outputs":{"extensible":true,"data":{}},"runtime":{}}},"pins":{}},{"joins":{},"address":"root:kernel:control:0.0.1:comment","parents":{"version":{"address":"root:kernel:control:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:control","key":"control","data":{"name":"control"}}},"uuid":"vTBPWs7-s","branches":{},"node":{"key":"comment","data":{"name":"Comment"},"model":{"type":"method","_v":2,"key":"comment","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Comment","description":"Leave a comment."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":false,"data":{}},"outputs":{"extensible":false,"data":{}},"runtime":{},"display":{},"comments":{"title":"POST to your relative URL:","markdown":"**POST** `/teams/{team-id}/channels/{channel-id}/messages`"}}},"pins":{}},{"joins":{},"address":"root:kernel:control:0.0.1:comment","parents":{"version":{"address":"root:kernel:control:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:control","key":"control","data":{"name":"control"}}},"uuid":"8R0gMwUDr","branches":{},"node":{"key":"comment","data":{"name":"Comment"},"model":{"type":"method","_v":2,"key":"comment","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Comment","description":"Leave a comment."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":false,"data":{}},"outputs":{"extensible":false,"data":{}},"runtime":{},"display":{},"comments":{"title":"Write HTML, Construct JSON","markdown":"We use the `Text - Compose` Card to craft our message. Feel free to experiment with the styles, there are a number of HTML editors you can find online that should help."}}},"pins":{}},{"joins":{},"address":"root:kernel:control:0.0.1:comment","parents":{"version":{"address":"root:kernel:control:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:control","key":"control","data":{"name":"control"}}},"uuid":"k6yRJO1Ha","branches":{},"node":{"key":"comment","data":{"name":"Comment"},"model":{"type":"method","_v":2,"key":"comment","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Comment","description":"Leave a comment."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":false,"data":{}},"outputs":{"extensible":false,"data":{}},"runtime":{},"display":{},"comments":{"title":"Why is this useful?","markdown":"Currently, the MS Teams connector only sends messages as `text` which means things like line breaks are ignored. \n\nWith a little extra work, we can create much more exciting and customized messages in MS Teams."}}},"pins":{}}],"model":{},"orderings":{"ilyygFurh":["mgE-yllLA","k6yRJO1Ha"],"HZYj0tWMme":["k6yRJO1Ha","kt1sryRSk"],"M7h57cjqoi":["kt1sryRSk","8R0gMwUDr"],"6OXHMIuk_h":["8R0gMwUDr","jBP-u5Pg0"],"tIQGRugoCR":["jBP-u5Pg0","YXOCDErQE"],"AUn80p85N1":["YXOCDErQE","vTBPWs7-s"],"Zeon6zilPd":["vTBPWs7-s","tXhEuIzlo"]},"cron":{},"security_level":null,"log":true,"inheritLog":true,"scheduled":false,"group":"704635ef-4f68-4dda-8f85-c990ff0c3b65","templateName":null,"connector_method_meta":{"inputs":{},"outputs":{},"options":{}},"monitor_flo":false}}},"configs":{"4de3d294-ac61-48ef-af42-6aa336042eda":{"id":"4de3d294-ac61-48ef-af42-6aa336042eda","name":"Microsoft Teams","module":"microsoftteams","data":null}},"tables":{},"groups":{"704635ef-4f68-4dda-8f85-c990ff0c3b65":{"id":"704635ef-4f68-4dda-8f85-c990ff0c3b65","data":{"name":"OIG Test","description":"","media_uri":""}}}},"checksum":"fb2d34a3d53132ae8072e97c3f0be49d57f73710073b7be606c731d44cf4ce04"}

Download steps:

  • right click "view raw" in the panel above on the right
  • click "Save Link As"
  • be sure the filename ends in .flow

or check out my other guides and Workflows content (more coming soon!) here:

GitHub logo bbarrows89 / oktaworkflows

tips, flows, and more related to Okta Workflows

Okta Workflows Guides and Resources

Okta Workflows Logo

Free Training - Foundations for Flowgrammers

Guides

Office Hours

  • Come join us in Community Office Hours!
  • We meet 3x a week and are here to help answer questions and get you unblocked while you're building.
  • Come with questions or just listen in to what other folks are building and working on.
  • Book a session

Dev.to

Max Katz

  • Max Katz blog
  • Max Katz is in charge of Community for Okta Workflows and has an excellent collection of tips and guides.

IAMSE.blog

Contact Bryan





Hope this helps! Find me on LinkedIn or shoot me an email if you have any questions.

You can also join us at a Community Office Hours session to work through problems and ask questions - I'd love to see you there.

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up