Search code examples
pythonemailbotframeworkchatbotmicrosoft-teams

Botframework send proactive message then string not empty


I have a problem sending proactive messages using the Bot Framework with Python. First what I need is to get the message body from Outlook, and then the bot must send that as a message to all the chats where it was added.

To do that, first I created a new file and called it Email.py.

To read every incoming message body I simply used while true: and time.sleep()

Here is my code example:

import imaplib, email, getpass
from email import policy
import json
import time

imap_host = 'outlook.office365.com'
imap_user = '[email protected]'

# init imap connection
mail = imaplib.IMAP4_SSL(imap_host, 993)
rc, resp = mail.login(imap_user, 'xxxxxx')
while True:
    # select only unread messages from inbox
    mail.select('Inbox')
    status, data = mail.search(None, '(UNSEEN)')

   if not data[0].split():
         time.sleep(120) 
    # Bot message variable
    Message_for_bot = ''
    # for each e-mail messages
    for num in data[0].split():
        # get a single message and parse it by policy.SMTP (RFC compliant)
        status, data = mail.fetch(num, '(RFC822)')
        email_msg = data[0][1]
        email_msg = email.message_from_bytes(email_msg, policy=policy.SMTP)

    # print only message parts that contain text data
        for part in email_msg.walk():
            if part.get_content_type() == "text/plain":
                for line in part.get_content().splitlines():
                   Message_for_bot += '\n' + line             
        print(Message_for_bot)

After I successfully created a program to read and print all incoming messages, I tried to build my bot. I found a proactive message bot on the Internet and used it as an example.

First I thought to just run this file with os in the background, but then my bot wasn't running. So then I tried adding an async function in the bot file but it didn't work. My bot just ignores that function. (Then I found the async functions in activity_handler.py, but I didn't find any that could help me.)

Then I tried adding an on_message_activity function and thought maybe it will start working if I call the bot like "@bot hi" for example in Teams. For that idea I must always run the while cycle and never stop the bot, but then I just get a message, and if there's a new incoming message then the bot doesn't write it anymore, and it's not a solution because if the bot is used for multiple chats then it simply doesn't work this way.

Then I try include my code on on_members_added_activity it seems working on azure test in web chat perfectly, but in teams after 1-2 messages stopping to work. my code

async def on_members_added_activity(
        self, members_added: [ChannelAccount], turn_context: TurnContext
    ):
    
        imap_host = 'outlook.office365.com'
        imap_user = '[email protected]'

        # init imap connection
        mail = imaplib.IMAP4_SSL(imap_host, 993)
        rc, resp = mail.login(imap_user, 'xxxxxx')
        while True:
            # select only unread messages from inbox
            mail.select('Inbox')
            status, data = mail.search(None, '(UNSEEN)')

            if not data[0].split():
                time.sleep(5) 
            # Bot message variable
            Message_for_bot = ''
            # for each e-mail messages
            for num in data[0].split():
                # get a single message and parse it by policy.SMTP (RFC compliant)
                status, data = mail.fetch(num, '(RFC822)')
                email_msg = data[0][1]
                email_msg = email.message_from_bytes(email_msg, policy=policy.SMTP)

            # print only message parts that contain text data
                for part in email_msg.walk():
                 if part.get_content_type() == "text/plain":
                    for line in part.get_content().splitlines():
                        Message_for_bot += '\n' + line       
                                
                await turn_context.send_activity(f"{Message_for_bot}")
        for member in members_added:
            if member.id != turn_context.activity.recipient.id:
                await turn_context.send_activity(
                    "bot starting work..."
                )
 
 

So maybe it's possible to send a message to wherever the bot is added (it needs to get this information somehow, maybe it's kept in the bot memory) whenever Message_for_bot is not empty.

All help will be appreciated.


Solution

  • As we have discussed some logic has to change

    1. Move your code out of the on_members_added_activity function
    2. Use Proactive concept to send the message

    -Vinoth