Add OptionsFlow to SMTP integration (#173386)

This commit is contained in:
Manu
2026-06-10 12:00:28 +02:00
committed by GitHub
parent 102cb4b69e
commit 158a8b8c69
6 changed files with 100 additions and 3 deletions
@@ -22,6 +22,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
CONF_RECIPIENT: [
subentry.unique_id for subentry in entry.subentries.values()
],
**entry.options,
},
{},
)
@@ -16,6 +16,7 @@ from homeassistant.config_entries import (
ConfigSubentryData,
ConfigSubentryFlow,
FlowType,
OptionsFlow,
SubentryFlowContext,
SubentryFlowResult,
)
@@ -25,12 +26,17 @@ from homeassistant.const import (
CONF_PORT,
CONF_RECIPIENT,
CONF_SENDER,
CONF_TIMEOUT,
CONF_USERNAME,
CONF_VERIFY_SSL,
UnitOfTime,
)
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.selector import (
NumberSelector,
NumberSelectorConfig,
NumberSelectorMode,
SelectSelector,
SelectSelectorConfig,
SelectSelectorMode,
@@ -90,6 +96,23 @@ STEP_USER_DATA_SCHEMA = vol.Schema(
}
)
OPTIONS_SCHEMA = vol.Schema(
{
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.All(
NumberSelector(
NumberSelectorConfig(
min=1,
max=1800,
step=1,
unit_of_measurement=UnitOfTime.SECONDS,
mode=NumberSelectorMode.BOX,
)
),
vol.Coerce(int),
)
}
)
class MailConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for SMTP."""
@@ -102,6 +125,12 @@ class MailConfigFlow(ConfigFlow, domain=DOMAIN):
"""Return subentries supported by this integration."""
return {SUBENTRY_TYPE_RECIPIENT: RecipientSubentryFlowHandler}
@staticmethod
@callback
def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlowHandler:
"""Get the options flow for this handler."""
return OptionsFlowHandler()
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
@@ -144,6 +173,7 @@ class MailConfigFlow(ConfigFlow, domain=DOMAIN):
async def async_step_import(self, import_info: dict[str, Any]) -> ConfigFlowResult:
"""Import config from yaml."""
options = {CONF_TIMEOUT: import_info.pop(CONF_TIMEOUT, DEFAULT_TIMEOUT)}
self._async_abort_entries_match(import_info)
errors = await self.hass.async_add_executor_job(validate_input, import_info)
@@ -156,6 +186,7 @@ class MailConfigFlow(ConfigFlow, domain=DOMAIN):
return self.async_create_entry(
title=title,
data=import_info,
options=options,
subentries=[
ConfigSubentryData(
subentry_type=SUBENTRY_TYPE_RECIPIENT,
@@ -238,3 +269,21 @@ class RecipientSubentryFlowHandler(ConfigSubentryFlow):
}
),
)
class OptionsFlowHandler(OptionsFlow):
"""Handle options flow."""
async def async_step_init(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Manage the options."""
if user_input is not None:
return self.async_create_entry(data=user_input)
return self.async_show_form(
step_id="init",
data_schema=self.add_suggested_values_to_schema(
OPTIONS_SCHEMA, self.config_entry.options
),
)
@@ -70,6 +70,18 @@
"title": "Failed to import SMTP YAML configuration"
}
},
"options": {
"step": {
"init": {
"data": {
"timeout": "Connection timeout"
},
"data_description": {
"timeout": "Maximum time to wait for a response from the SMTP server before the connection attempt is aborted."
}
}
}
},
"selector": {
"encryption": {
"options": {
+4
View File
@@ -17,6 +17,7 @@ from homeassistant.const import (
CONF_PASSWORD,
CONF_PORT,
CONF_SENDER,
CONF_TIMEOUT,
CONF_USERNAME,
CONF_VERIFY_SSL,
)
@@ -74,6 +75,9 @@ def mock_config_entry() -> MockConfigEntry:
CONF_PASSWORD: "test-password",
CONF_VERIFY_SSL: True,
},
options={
CONF_TIMEOUT: 5,
},
entry_id="123456789",
subentries_data=[
ConfigSubentryData(
+32 -1
View File
@@ -14,13 +14,14 @@ from homeassistant.components.smtp.const import (
DOMAIN,
SUBENTRY_TYPE_RECIPIENT,
)
from homeassistant.config_entries import SOURCE_USER, FlowType
from homeassistant.config_entries import SOURCE_USER, ConfigEntryState, FlowType
from homeassistant.const import (
CONF_NAME,
CONF_PASSWORD,
CONF_PORT,
CONF_RECIPIENT,
CONF_SENDER,
CONF_TIMEOUT,
CONF_USERNAME,
CONF_VERIFY_SSL,
)
@@ -221,3 +222,33 @@ async def test_form_recipient_already_configured(
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
async def test_options_flow(
hass: HomeAssistant,
config_entry: MockConfigEntry,
) -> None:
"""Test options flow."""
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
result = await hass.config_entries.options.async_init(config_entry.entry_id)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "init"
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
CONF_TIMEOUT: 10,
},
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert config_entry.options == {
CONF_TIMEOUT: 10,
}
+2 -2
View File
@@ -73,6 +73,7 @@ async def test_import(
CONF_PASSWORD: "test-password",
CONF_VERIFY_SSL: True,
CONF_RECIPIENT: "recipient@example.com",
CONF_TIMEOUT: 10,
}
]
},
@@ -98,9 +99,9 @@ async def test_import(
CONF_PASSWORD: "test-password",
CONF_VERIFY_SSL: True,
CONF_RECIPIENT: ["recipient@example.com"],
CONF_TIMEOUT: 5,
CONF_DEBUG: False,
}
assert entries[0].options == {CONF_TIMEOUT: 10}
assert list(entries[0].subentries.values())[0].unique_id == "recipient@example.com"
@@ -133,7 +134,6 @@ async def test_import_already_configured(
CONF_VERIFY_SSL: True,
CONF_RECIPIENT: ["recipient@example.com"],
CONF_DEBUG: False,
CONF_TIMEOUT: 5,
},
entry_id="123456789",
)