text: """
  IMAP sensor support.
  
  For more details about this platform, please refer to the documentation at
  https://home-assistant.io/components/sensor.imap/
  """
  import asyncio
  import logging
  
  import async_timeout
  import voluptuous as vol
  
  from homeassistant.components.sensor import PLATFORM_SCHEMA
  from homeassistant.const import (
      CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_USERNAME,
      EVENT_HOMEASSISTANT_STOP)
  from homeassistant.exceptions import PlatformNotReady
  import homeassistant.helpers.config_validation as cv
  from homeassistant.helpers.entity import Entity
  
  _LOGGER = logging.getLogger(__name__)
  
  REQUIREMENTS = ['aioimaplib==0.7.13']
  
  CONF_SERVER = 'server'
  CONF_FOLDER = 'folder'
  
  DEFAULT_PORT = 993
  
  ICON = 'mdi:email-outline'
  
  PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
      vol.Optional(CONF_NAME): cv.string,
      vol.Required(CONF_USERNAME): cv.string,
      vol.Required(CONF_PASSWORD): cv.string,
      vol.Required(CONF_SERVER): cv.string,
      vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
      vol.Optional(CONF_FOLDER, default='INBOX'): cv.string,
  })
  
  
  async def async_setup_platform(hass,
                                 config,
                                 async_add_entities,
                                 discovery_info=None):
      """Set up the IMAP platform."""
      sensor = ImapSensor(config.get(CONF_NAME),
                          config.get(CONF_USERNAME),
                          config.get(CONF_PASSWORD),
                          config.get(CONF_SERVER),
                          config.get(CONF_PORT),
                          config.get(CONF_FOLDER))
      if not await sensor.connection():
          raise PlatformNotReady
  
      hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, sensor.shutdown())
      async_add_entities([sensor], True)
  
  
  class ImapSensor(Entity):
      """Representation of an IMAP sensor."""
  
      def __init__(self, name, user, password, server, port, folder):
          """Initialize the sensor."""
          self._name = name or user
          self._user = user
          self._password = password
          self._server = server
          self._port = port
          self._folder = folder
          self._unread_count = 0
          self._connection = None
          self._does_push = None
          self._idle_loop_task = None
  
      async def async_added_to_hass(self):
          """Handle when an entity is about to be added to Home Assistant."""
          if not self.should_poll:
              self._idle_loop_task = self.hass.loop.create_task(self.idle_loop())
  
      @property
      def name(self):
          """Return the name of the sensor."""
          return self._name
  
      @property
      def icon(self):
          """Return the icon to use in the frontend."""
          return ICON
  
      @property
      def state(self):
          """Return the number of unread emails."""
          return self._unread_count
  
      @property
      def available(self):
          """Return the availability of the device."""
          return self._connection is not None
  
      @property
      def should_poll(self):
          """Return if polling is needed."""
          return not self._does_push
  
      async def connection(self):
          """Return a connection to the server, establishing it if necessary."""
          import aioimaplib
  
          if self._connection is None:
              try:
                  self._connection = aioimaplib.IMAP4_SSL(
                      self._server, self._port)
                  await self._connection.wait_hello_from_server()
                  await self._connection.login(self._user, self._password)
                  await self._connection.select(self._folder)
                  self._does_push = self._connection.has_capability('IDLE')
              except (aioimaplib.AioImapException, asyncio.TimeoutError):
                  self._connection = None
  
          return self._connection
  
      async def idle_loop(self):
          """Wait for data pushed from server."""
          import aioimaplib
  
          while True:
              try:
                  if await self.connection():
                      await self.refresh_unread_count()
                      await self.async_update_ha_state()
  
                      idle = await self._connection.idle_start()
                      await self._connection.wait_server_push()
                      self._connection.idle_done()
                      with async_timeout.timeout(10):
                          await idle
                  else:
                      await self.async_update_ha_state()
              except (aioimaplib.AioImapException, asyncio.TimeoutError):
                  self.disconnected()
  
      async def async_update(self):
          """Periodic polling of state."""
          import aioimaplib
  
          try:
              if await self.connection():
                  await self.refresh_unread_count()
          except (aioimaplib.AioImapException, asyncio.TimeoutError):
              self.disconnected()
  
      async def refresh_unread_count(self):
          """Check the number of unread emails."""
          if self._connection:
              await self._connection.noop()
              _, lines = await self._connection.search('UnSeen UnDeleted')
              self._unread_count = len(lines[0].split())
  
      def disconnected(self):
          """Forget the connection after it was lost."""
          _LOGGER.warning("Lost %s (will attempt to reconnect)", self._server)
          self._connection = None
  
      async def shutdown(self):
          """Close resources."""
          if self._connection:
              if self._connection.has_pending_idle():
                  self._connection.idle_done()
              await self._connection.logout()
          if self._idle_loop_task:
              self._idle_loop_task.cancel()
  