Out-Of-Workplace Automated Reply
What a fantastic function, proper? A brief out-of-office e mail that goes out routinely to anybody who sends you a message when you are away for a time period. It notifies the sender that you’re away and will not reply till you come back.
Your out-of-office message often offers vital data akin to:
- Return date
- Backups one who is filling in for you
- Emergency Contact
E mail & WebEx IM (Instantaneous Messaging)
I’m certain that you’re getting many emails every single day. Nonetheless, I’ve observed that I’m getting an increasing number of Webex messages as properly!
To deal with the massive quantity of emails, particularly after I’m away, I created a really environment friendly set of outlook folders and guidelines – Each work completely! Nonetheless, Webex IM doesn’t assist that (for now).
So… I assumed to myself… (problem #1)
- It could be good if WebEx may ship an auto out-of-office reply with my backup individual’s contact.
- Most folk won’t ship repeated messages on the identical topic after they know I’m away.
- That might be skilled, environment friendly and can scale back the variety of messages!
After which I assumed… (problem #2)
- Let’s make it much more fascinating!
- Sure, I might be out-of-office, however since I’m a part of a essential engagement, I wish to be told (ONLY) if the client sends me a direct Webex message.
- However I do know myself, if I’ll open the Webex shopper, I might be tempted to learn different messages…
- It could be nice to auto-forward ONLY the client Webex message as a textual content message (i.e., SMS). That means, I wouldn’t have to open the WebEx shopper!
You might be most likely considering, “Yossi, Webex DOES present your standing as out of workplace! , this cool airplane icon? ✈️” You might be proper. BUT, I can’t share vital data as to who’s filling in for me whereas I’m out, or my contact for pressing issues. Additionally, Webex IM is my (and lots of others) most popular communication technique, so I’d anticipate to have the identical out-of-office future/assist.
So… Let’s have a enjoyable problem! Let’s design and construct one thing cool! A brand new Webex IM function – Automated out-of-office reply!
The Goals
I would like the brand new Webex function to:
- Ship an auto-notification after I’m out of the workplace.
- Ship the notification ONLY to particular person chats and never group chats.
- Ship just one notification (and never each time the identical individual sends a message).
- [stretch-goal.1] Help message markdown format and attachments.
- [stretch-goal.2] Retrieve the Outlook 365 OutOfOffice message and combine it with Webex code.
- Ahead Webex messages from a particular individual (i.e., the client) to my cell phone utilizing Twilio integration.
The Design
The script logic is as follows:
Examine my Webex standing each X seconds/minute leveraging Webex “Checklist Individuals” API name. After some considering, I made a decision NOT to implement this step as a extra correct/scalable means is to arrange a webhook and subscribe for notification. Nonetheless, I couldn’t discover such a Webex webhook but… 🤔 (What’s a Webex Webhook?)- Configure pyngrok to introspect HTTP site visitors operating over port 5000 (What’s ngrok? What’s pyngrok?).
- Configure Webex webhook to ship notifications to ngrok URL when:
- It receives a brand new chat message.
- The message is from a direct room ONLY (i.e., from 1:1 classes and never from n:1 classes).
- As soon as a brand new message is acquired, report the sender title
- If the sender title doesn’t exist within the log file – Ship an out-of-office message.
- If the sender title does exist within the log file – Don’t ship an out-of-office message.
- Add assist for “persona response”.
- Combine with Twilio to ship a textual content message.
… and the plot thickens
Appears easy proper? However what concerning the Webex API tokens limitation? For the script to work, we want a token to:
- Create a webhook
- Ship a message
The problem is that we can’t use the next:
- Webex Bot token to create a webhook because the webhook might be related to messages despatched to the Bot and to not me.
- Private entry token to ship messages because it’s restricted to 12 hours.
- Visitor person token can’t entry the “standing” knowledge because it isn’t a part of the group.
What can we do… Let’s assume… 🤔
Choice #1
For a demo/PoC goal, use the private entry token. Utilizing that token, we will create the webhook and messages. Nonetheless, it’s restricted to 12 hours.x
PROS: Easy to make use of (one token is required).
CONS: The token is restricted to 12 hours.
The Out-Of-Workplace message will appear to be this —>
Choice #2
Combining a private entry token to create the webhook and Webex Bot token to ship the messages (WebEx Bot is a part of the group with a everlasting token).
PROS: Easy to make use of (two tokens are wanted, Bot token is everlasting).
CONS: The Out-Off-Workplace message will seem within the WebEx Bot (new) room and never as a dialog follow-up.
Choice #3
Combining a private entry token to create the webhook and Webex Integration token. This token is legitimate for 14 days, and the refresh token is legitimate for 90 days.
PROS: The really useful means for a Webex integration venture.
CONS: Difficult, A bit complicated to configure (two tokens are wanted, Integration token is as much as 104 days).
My Suggestion
Follow the three choices above 😉
- [Walk] Begin with possibility #1 and get accustomed to Webex private entry token and python code.
- [Run] Proceed with possibility #2 and study Webex Bot token.
- [Fly] Full the apply by implementing a Webex Integration token and an OAuth grant surroundings utilizing an online browser.
The python code of the three choices could be very related. The one distinction is the Webex tokens utilization and a few pre-conf wanted for choices #2 (Easy methods to configure Webex Bot?), and #3 (Easy methods to configure Webex Integration?).
Let’s evaluate the code 👨💻
Step #1 – Import the required python modules.
- The Twilio python library could be downloaded from “twilio.com/docs/libraries/python”.
from pyngrok import conf, ngrok from twilio.relaxation import Shopper from threading import Thread import requests import base64 import time import json import sys import re import os
Step #2 – Arrange the required tokens, log recordsdata, and stderr env.
- I made a decision to suppress the Ngrok “502 Unhealthy Gateway” error messages (that are anticipated, as ngrok isn’t configured to level to an precise listening utility).
- Create a log file to report the message sender title.
- Outline the required Webex and Twilio tokens (Word strains 10 and 11. These are required if utilizing the Bot or Integration tokens).
# Suppress error messages sys.stderr = open(os.devnull, "w") # Create log file log_file = open("/tmp/webexOOO.log", "w") log_file.shut() # Authorization token(s) webex_personal_token = "xxx1" # For possibility #1, #2 and #3 # webex_bot_token = "xxx2" # For possibility #1 and #2 # webex_integration_token = "xxx3" # For possibility #1 and #3 twilio_account_sid = "yyy" twilio_auth_token = "zzz" customer_email = "a@b.c"
Step #3 – A callback perform to floor ngrok logs and export them to a log file.
- I made a decision to suppress the Ngrok “502 Unhealthy Gateway” error messages (that are anticipated, as ngrok isn’t configured to level to an precise listening utility).
- Create a log file to report the message sender title.
- Outline the required Webex and Twilio tokens (Word strains 10 and 11. These are required if utilizing the Bot or Integration tokens).
def log_event_callback(log): with open('/tmp/logFile.log', 'a') as f: print(log, file=f) conf.get_default().log_event_callback = log_event_callback
Step #4 – A perform to:
- Utilizing Webex API GET name, retrieve the client’s newest message.
- Combine with Twilio for sending textual content messages.
- Strains #5 and #6 are required if utilizing the Bot or Integration tokens.
- Strains #21 and #22 configure the Twilio (sending) telephone quantity and the vacation spot telephone quantity.
- Line #24 is a Webex picture file (to be despatched with the textual content message).
def func0(): url = "https://webexapis.com/v1/messages/direct?personEmail=" + customer-email headers = { 'Authorization': 'Bearer ' + webex_personal_token, # For possibility #1, #2 and #3 # 'Authorization': 'Bearer ' + webex_bot_token, # For possibility #2 # 'Authorization': 'Bearer ' + webex_integration token, # For possibility #3 'Content material-Kind': 'utility/json' } response = requests.request("GET", url, headers=headers) r_json = response.json() message = r_json["items"][1]["html"] TAG_RE = re.compile(r'<[^>]+>') message_parsed = TAG_RE.sub('', message) # Twilio Integration shopper = Shopper(twilio_account_sid, twilio_auth_token) message = shopper.api.account.messages.create( to="+1xxxxxxxxx", from_="+1yyyyyyyyy", physique=message_parsed, media_url=['https://images.contentstack.io/v3/assets/bltd14fd2a03236233f/bltab28bd9a758b3f81/60d617644763af56bad5a0d5/download'])
Step #5 – A perform to:
- Create Ngrok tunnel on port 5000.
- Get Ngrok (HTTPS) tunnel data (i.e., the tunnel URL).
- Create Webex webhook.
- Strains #13 to #17 describe the Webex webhook configuration.
- “useful resource”: “messages” -> Seize ONLY Webex messages.
- “occasion”: “created” -> When a brand new occasion (i.e. message) is created.
- “filter”: “roomType=direct” -> ONLY from direct messages and never from group rooms.
- “targetUrl”: tunnel_IP -> Ngrok tunnel URL.
- “title”: “Webex OOO” -> Wehbook title
- Line #20 – To create the webhook, we will use ONLY the webex_personal_token (and never the Bot or Integration tokens).
def func1(): print("n| --> Create ngrok tunnel") ngrok.join(5000, bind_tls=True) tunnels = ngrok.get_tunnels() tunnel_IP = re.findall(r'"(.+?)"', str(tunnels))[0] # Create webex webhook print("| --> Create webex webhook") url = "https://webexapis.com/v1/webhooks" payload = json.dumps({ "useful resource": "messages", "occasion": "created", "filter": "roomType=direct", "targetUrl": tunnel_IP, "title": "Webex OOO" }) headers = { 'Authorization': 'Bearer ' + webex_personal_token, 'Content material-Kind': 'utility/json' } response = requests.request("POST", url, headers=headers, knowledge=payload) r_json = response.json() print("| --> Listening...")
Step #6 – A perform to:
- Tail the log file and verify if a brand new “localhost:5000” entry was added.
- If a brand new entry was added, question Ngrok if the message is from the customer_email (outlined in step #2).
- YES – Use Webex API to retrieve (GET) the customer_email newest message and ship it as a textual content message utilizing Twilio API. Then proceed.
- NO – Examine if the sender’s e mail handle is already saved within the log file.
- YES – Do nothing.
- NO – Use the Webex API to ship (POST) the OutOfOffice message, then add the sender e mail to the log file.
- Line #22 comprise a regex to search out (any) e mail handle. You could change the regex to solely seek for your group emails (e.g., r’w*@cisco.comw*’ will discover ONLY x@cisco.com emails).
- Strains #43 and #44 are required if utilizing the Bot or Integration tokens.
def func2(): whereas True: time.sleep(5) # Examine webhook for brand new messages with open("/tmp/logFile.log", "r+") as file: end result = (checklist(file)[-1]) if "localhost:5000" in end result: file.truncate(0) file.write(str('rolloverLine')) url = "http://localhost:4040/api/requests/http?restrict=1" response = requests.request("GET", url) r_json = response.json() for i in vary(0, len(r_json['requests'])): encrypted_response = r_json["requests"][i]["request"]["raw"] base64_bytes = encrypted_response.encode("ascii") sample_string_bytes = base64.b64decode(base64_bytes) sample_string = sample_string_bytes.decode("ascii") match = re.findall(r'b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Z|a-z]{2,}b', sample_string) if str(match).strip("[']") == customer_email: func0() elif str(match).strip("[']") in open('/tmp/webexOOO.log').learn(): proceed else: log_file = open("/tmp/webexOOO.log", "a") log_file.write(str(match).strip("[']")+ "n") log_file.shut() with open("/tmp/webexOOO.log") as f: personEmail = f.readlines()[-1] url = "https://webexapis.com/v1/messages" payload = json.dumps({ "toPersonEmail": "" + str(personEmail) + "", "markdown": "** Webex OutOfOffice Auto Reply **nnThank you on your message. I’m out of the workplace and might be again at (Date of Return). Throughout this era, I'll have restricted entry to Webex chat.nnFor venture X, please contact (Contacts Title) at (Contacts E mail Handle).nFor venture Y, please contact (Contacts Title) at (Contacts E mail Handle).nnIf you want speedy help, please contact me on my mobile phone at (mobile phone quantity).nnBest regardsnYossi M." }) headers = { 'Authorization': 'Bearer ' + webex_personal_token, # For possibility #1, #2 and #3 # 'Authorization': 'Bearer ' + webex_bot_token, # For possibility #2 # 'Authorization': 'Bearer ' + webex_integration token, # For possibility #3 'Content material-Kind': 'utility/json' } response = requests.request("POST", url, headers=headers, knowledge=payload) else: cross if __name__ == '__main__': Thread(goal = func1).begin() Thread(goal = func2).begin()
The Demo (2:42 Minutes) 🎥
BTW…
- [stretch-goal.1] Help message markdown format and attachments – Webex “Create a Messages” API name helps markdown 👉.
- [stretch-goal.2] Retrieve the Outlook 365 OutOfOffice message and combine it with Webex code – That may be achieved leveraging the “automaticRepliesSetting” name of Microsoft Graph (Workplace 365 API).
- Sure, there are different methods to put in writing the Python code (w/o utilizing the log recordsdata). Nonetheless, my objective was to create a easy and extra comprehensible code.
- Sure, extra options akin to a script scheduler, and a pleasant UI could be added.
- The script could be executed out of your native laptop computer, Raspberry Pi, or a cloud-compute occasion.
Further Sources
Last Ideas
- The facility of automation, innovation, and integration – Cool, proper! 😎
- Consider that… utilizing related integrations, you possibly can:
- Combine with ServiceNow, PagerDuty, and many others., and routinely open a service request primarily based on key phrases straight from Webex chat!
- Create customized responses when you’re away/out-of-office.
- What’s your problem? Are you able to leverage automation/totally different applied sciences/programming languages to mitigate it?
- Wish to study extra about APIs, automation, and Integration? Python programming? Examine the AIDE Consumer Information or get in contact with the Cross-Area TAB crew.
We’d love to listen to what you assume. Ask a query or go away a remark beneath.
And keep linked with Cisco DevNet on social!
LinkedIn | Twitter @CiscoDevNet | Fb | Developer Video Channel
Share: