This site is in read only mode. Please continue to browse, but replying, likes, and other actions are disabled for now.

⚠️ We've moved!

Hi there!

To reduce project dependency on 3rd party paid services the StackStorm TSC has decided to move the Q/A from this forum to Github Discussions. This will make user experience better integrated with the native Github flow, as well as the questions closer to the community where they can provide answers.

Use 🔗 Github Discussions to ask your questions.

Sensor Not working

I have created a sensor which will execute when some one will send mail on particular email id with particular email subject using IMAP.
For this
I have created a gmail account where I have do setting for I map and I have create sensor , rule, and action. Action is running separately
using “st2 run <pack_name>.<action_name>”.
It is working fine. While running sensor
using “sudo /opt/stackstorm/st2/bin/st2sensorcontainer --config-file=/etc/st2/st2.conf --sensor-ref=azure_vm_create.IMAPSensor”
it not showing error.
this is my imap.yaml file

class_name: “IMAPSensor”
entry_point: “imap_sensor.py”
description: “Sensor that emits triggers when e-mail message is received via IMAP”
trigger_types:

name: imap.message
description: "An e-mail receieved via the IMAP sensor"
payload_info:
  - uid
  - from
  - to
  - headers
  - subject
  - date
  - message_id
  - body
  - location
  - vmname
  - group

imap_sensor.py

import hashlib
import base64

import six
import eventlet
import easyimap
from flanker import mime

from st2reactor.sensor.base import PollingSensor

all = [
‘IMAPSensor’
]

eventlet.monkey_patch(
os=True,
select=True,
socket=True,
thread=True,
time=True)

class IMAPSensor(PollingSensor):
def init(self, sensor_service, config=None, poll_interval=10):
super(IMAPSensor, self).init(sensor_service=sensor_service,
config=config,
poll_interval=poll_interval)

    self._trigger = 'azure_vm_create.imap.message'
    self._logger = self._sensor_service.get_logger(__name__)
    self._accounts = {}
    self._logger.debug('[IMAPSensor]: Init executed')
    self._stop = False

def setup(self):
    self._logger.debug('[IMAPSensor]: entering setup')

def poll(self):
    self._logger.debug('[IMAPSensor]: entering poll')

    if 'imap_accounts' in self._config:
        self._parse_accounts(self._config['imap_accounts'])

    for name, values in self._accounts.items():
        mailbox = values['connection']
        mailbox_metadata = values['mailbox_metadata']

        self._poll_for_unread_messages(name=name, mailbox=mailbox,
                                       mailbox_metadata=mailbox_metadata)
        mailbox.quit()

def cleanup(self):
    self._logger.debug('[IMAPSensor]: entering cleanup')
    self._stop = True

    for name, values in self._accounts.items():
        mailbox = values['connection']
        self._logger.debug('[IMAPSensor]: Disconnecting from {0}'.format(name))
        mailbox.quit()

def add_trigger(self, trigger):
    pass

def update_trigger(self, trigger):
    pass

def remove_trigger(self, trigger):
    pass

def _parse_accounts(self, accounts):
    for config in accounts:
        mailbox = config.get('name', 'Mukesh')
        server = config.get('server', 'imap.gmail.com')
        port = config.get('port', 993)
        user = config.get('username', '[email protected]')
        password = config.get('password', 'nihilent@123')
        folder = config.get('folder', 'INBOX')
        ssl = config.get('secure', True)

        if not user or not password:
            self._logger.debug("""[IMAPSensor]: Missing
                username/password for {0}""".format(mailbox))
            continue

        if not server:
            self._logger.debug("""[IMAPSensor]: Missing server
                for {0}""".format(mailbox))
            continue

        try:
            connection = easyimap.connect(server, user, password,
                                          folder, ssl=ssl, port=port)
        except Exception as e:
            message = 'Failed to connect to mailbox "%s": %s' % (mailbox, str(e))
            raise Exception(message)

        item = {
            'connection': connection,
            'mailbox_metadata': {
                'server': server,
                'port': port,
                'user': user,
                'folder': folder,
                'ssl': ssl
            }
        }
        self._accounts[mailbox] = item

def _poll_for_unread_messages(self, name, mailbox, mailbox_metadata):
    self._logger.debug('[IMAPSensor]: polling mailbox {0}'.format(name))

    messages = mailbox.unseen()

    self._logger.debug('[IMAPSensor]: Processing {0} new messages'.format(len(messages)))
    for message in messages:
        self._process_message(uid=message.uid, mailbox=mailbox,
                              mailbox_metadata=mailbox_metadata)

def _process_message(self, uid, mailbox, mailbox_metadata):
    m=[]
    message = mailbox.mail(uid, include_raw=True)
    mime_msg = mime.from_string(message.raw)

    body = message.body
    sent_from = message.from_addr
    sent_to = message.to
    subject = message.title
    date = message.date
    message_id = message.message_id
    headers = mime_msg.headers.items()
    x=body.splitlines()
    for x1 in x:
      res=x1.split('=')
      m.append(res[1])
    location=m[0]
    vmname=m[1]
    group=m[2]

    # Flatten the headers so they can be unpickled
    headers = self._flattern_headers(headers=headers)

    payload = {
        'uid': uid,
        'from': sent_from,
        'to': sent_to,
        'headers': headers,
        'date': date,
        'subject': subject,
        'message_id': message_id,
        'body': body,
        'mailbox_metadata': mailbox_metadata,
        'location': location,
        'vmname': vmname,
        'group': group
    }

    self._sensor_service.dispatch(trigger=self._trigger, payload=payload)

def _flattern_headers(self, headers):
    # Flattern headers and make sure they only contain simple types so they
    # can be serialized in a trigger
    result = []

    for pair in headers:
        name = pair[0]
        value = pair[1]

        if not isinstance(value, six.string_types):
            value = str(value)

        result.append([name, value])

    return result

I dont know where I am lacking. Please tell me how sensor initiate.

Are you able to run the sensor in the debug mode?

1 Like

Yes , Now resolved

Thanks for comment