Files

144 lines
4.4 KiB
Python

"""The smtp integration."""
import logging
from smtplib import SMTPAuthenticationError
from socket import gaierror
from homeassistant.components.notify import DOMAIN as NOTIFY_DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_NAME,
CONF_PASSWORD,
CONF_PORT,
CONF_RECIPIENT,
CONF_SENDER,
CONF_TIMEOUT,
CONF_USERNAME,
CONF_VERIFY_SSL,
Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import (
config_validation as cv,
discovery,
entity_registry as er,
)
from homeassistant.helpers.typing import ConfigType
from homeassistant.util.ssl import create_client_context
from .const import (
CONF_ENCRYPTION,
CONF_ENTRY,
CONF_OLD_RECIPIENT,
CONF_SENDER_NAME,
CONF_SERVER,
DEFAULT_TIMEOUT,
DOMAIN,
)
from .helpers import SmtpClient
from .services import async_setup_services
_LOGGER = logging.getLogger(__name__)
type SmtpConfigEntry = ConfigEntry[SmtpClient]
PLATFORMS: list[Platform] = [Platform.NOTIFY]
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the SMTP services."""
async_setup_services(hass)
return True
async def async_setup_entry(hass: HomeAssistant, entry: SmtpConfigEntry) -> bool:
"""Set up SMTP from a config entry."""
await async_migrate_subentries(hass, entry)
hass.async_create_task(
discovery.async_load_platform(
hass,
Platform.NOTIFY,
DOMAIN,
{
CONF_NAME: entry.title,
CONF_RECIPIENT: [
subentry.unique_id for subentry in entry.subentries.values()
],
CONF_ENTRY: entry,
},
{},
)
)
client = SmtpClient(
server=entry.data[CONF_SERVER],
port=entry.data[CONF_PORT],
timeout=entry.options.get(CONF_TIMEOUT, DEFAULT_TIMEOUT),
sender=entry.data[CONF_SENDER],
encryption=entry.data[CONF_ENCRYPTION],
username=entry.data.get(CONF_USERNAME),
password=entry.data.get(CONF_PASSWORD),
sender_name=entry.data.get(CONF_SENDER_NAME),
verify_ssl=entry.data[CONF_VERIFY_SSL],
ssl_context=(
await hass.async_add_executor_job(create_client_context)
if entry.data[CONF_VERIFY_SSL]
else None
),
)
try:
await hass.async_add_executor_job(lambda: client.connect().quit())
except SMTPAuthenticationError as e:
raise ConfigEntryAuthFailed(
translation_domain=DOMAIN,
translation_key="authentication_error",
) from e
except (gaierror, ConnectionRefusedError) as e:
_LOGGER.debug("Full exception:", exc_info=True)
raise ConfigEntryNotReady(
translation_domain=DOMAIN,
translation_key="connection_error",
) from e
entry.runtime_data = client
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(entry.add_update_listener(_async_update_listener))
return True
async def _async_update_listener(hass: HomeAssistant, entry: SmtpConfigEntry) -> None:
"""Handle update."""
hass.config_entries.async_schedule_reload(entry.entry_id)
async def async_unload_entry(hass: HomeAssistant, entry: SmtpConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
async def async_migrate_subentries(hass: HomeAssistant, entry: SmtpConfigEntry) -> None:
"""Migrate entity unique_id after subentry reconfiguration."""
for subentry in entry.subentries.values():
if (
(old_unique_id := subentry.data.get(CONF_OLD_RECIPIENT)) is not None
and old_unique_id != subentry.unique_id
and (
entity := er.async_get(hass).async_get_entity_id(
NOTIFY_DOMAIN, DOMAIN, f"{entry.entry_id}_{old_unique_id}"
)
)
):
er.async_get(hass).async_update_entity(
entity,
new_unique_id=f"{entry.entry_id}_{subentry.unique_id}",
)
hass.config_entries.async_update_subentry(entry, subentry, data={})