updated apps

This commit is contained in:
2026-07-14 23:57:03 -04:00
parent 6cc7212cef
commit 010e828e9c
797 changed files with 45153 additions and 4246 deletions
+13 -14
View File
@@ -6,8 +6,12 @@ import logging
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_RESOURCES
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers import (
config_validation as cv,
)
from homeassistant.helpers import (
device_registry as dr,
)
from . import const
from .const import (
@@ -103,6 +107,9 @@ __all__ = [
_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
async def async_setup(hass: HomeAssistant, config_entry: MailAndPackagesConfigEntry): # pylint: disable=unused-argument
"""Disallow configuration via YAML."""
return True
@@ -133,21 +140,13 @@ async def async_setup_entry(
# Setup the data coordinator
coordinator = MailDataUpdateCoordinator(hass, config, config_entry)
# Fetch initial data so we have data when entities subscribe
await coordinator.async_refresh()
# Raise ConfigEntryNotReady if coordinator didn't update
if not coordinator.last_update_success:
if isinstance(coordinator.last_exception, ConfigEntryAuthFailed):
raise coordinator.last_exception
exc = coordinator.last_exception
detail = (str(exc) or type(exc).__name__) if exc else "unknown error"
_LOGGER.error("Error updating sensor data: %s", detail)
raise ConfigEntryNotReady
config_entry.runtime_data = MailAndPackagesData(coordinator=coordinator, cameras=[])
# Fetch initial data in the background so setup doesn't block
hass.async_create_task(coordinator.async_refresh())
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
return True
@@ -78,6 +78,8 @@ class PackagesBinarySensor(CoordinatorEntity, BinarySensorEntity):
@property
def is_on(self) -> bool:
"""Return True if the image is updated."""
if self.coordinator.data is None:
return False
if self._type in self.coordinator.data:
_LOGGER.debug(
"binary_sensor: %s value: %s",
+11 -5
View File
@@ -182,7 +182,13 @@ class MailCam(CoordinatorEntity, Camera):
def _read_file(path: str) -> bytes:
with Path(path).open("rb") as f:
return f.read()
data = f.read()
if not data:
# A 0-byte image (e.g. a failed extraction that wrote an empty
# file) is as unservable as a missing one — raise so it routes
# through the same placeholder fallback below.
raise FileNotFoundError(f"empty image file: {path}")
return data
try:
image_bytes = await self.hass.async_add_executor_job(
@@ -273,7 +279,7 @@ class MailCam(CoordinatorEntity, Camera):
if required_keys.issubset(self.coordinator.data):
image = self.coordinator.data[ATTR_USPS_IMAGE]
path = self.coordinator.data[ATTR_IMAGE_PATH]
self._file_path = f"{self.hass.config.path()}/{path}{image}"
self._file_path = self.hass.config.path(path, image)
self._is_generic = not self.coordinator.data.get("usps_update", False)
_LOGGER.debug(
"usps_camera camera - file path set to: %s",
@@ -313,7 +319,7 @@ class MailCam(CoordinatorEntity, Camera):
return
image_path = self.coordinator.data.get(ATTR_IMAGE_PATH, "")
full_storage_path = Path(f"{self.hass.config.path()}/{image_path}")
full_storage_path = Path(self.hass.config.path(image_path))
gif_path = str(full_storage_path / "generic_deliveries.gif")
resized_images = await self.hass.async_add_executor_job(
@@ -383,7 +389,7 @@ class MailCam(CoordinatorEntity, Camera):
image = self.coordinator.data[image_attr]
path = f"{self.coordinator.data[ATTR_IMAGE_PATH]}{path_suffix}"
delivery_file_path = f"{self.hass.config.path()}/{path}{image}"
delivery_file_path = self.hass.config.path(path, image)
is_no_mail = image.startswith(
no_mail_check,
@@ -448,7 +454,7 @@ class MailCam(CoordinatorEntity, Camera):
image = self.coordinator.data[image_attr]
image_path = self.coordinator.data[ATTR_IMAGE_PATH].rstrip("/") + "/"
path = f"{image_path}{base_name}/"
coordinator_file_path = f"{self.hass.config.path()}/{path}{image}"
coordinator_file_path = self.hass.config.path(path, image)
_LOGGER.debug(
"=== %s CAMERA UPDATE === coordinator %s = '%s'",
@@ -57,6 +57,7 @@ from .const import (
CONF_STORAGE,
CONF_UPS_CUSTOM_IMG,
CONF_UPS_CUSTOM_IMG_FILE,
CONF_USPS_PLACEHOLDER,
CONF_VERIFY_SSL,
CONF_WALMART_CUSTOM_IMG,
CONF_WALMART_CUSTOM_IMG_FILE,
@@ -89,6 +90,7 @@ from .const import (
DEFAULT_STORAGE,
DEFAULT_UPS_CUSTOM_IMG,
DEFAULT_UPS_CUSTOM_IMG_FILE,
DEFAULT_USPS_PLACEHOLDER,
DEFAULT_WALMART_CUSTOM_IMG,
DEFAULT_WALMART_CUSTOM_IMG_FILE,
DOMAIN,
@@ -198,7 +200,9 @@ async def _check_forwarded_emails(user_input: dict[str, Any]) -> list[str]:
return errors
def _validate_path_input(user_input: dict, errors: dict) -> None:
def _validate_path_input(
user_input: dict, errors: dict, hass: HomeAssistant | None = None
) -> None:
"""Validate path and file inputs."""
# List of (Toggle Key, File Key, Error Key)
file_checks = [
@@ -233,11 +237,17 @@ def _validate_path_input(user_input: dict, errors: dict) -> None:
for toggle, file_key, error_key in file_checks:
if user_input.get(toggle) and file_key in user_input:
if not Path(user_input[file_key]).is_file():
path = user_input[file_key]
if hass:
path = hass.config.path(path)
if not Path(path).is_file():
errors[error_key] = "file_not_found"
if CONF_STORAGE in user_input:
if not Path(user_input[CONF_STORAGE]).exists():
path = user_input[CONF_STORAGE]
if hass:
path = hass.config.path(path)
if not Path(path).exists():
errors[CONF_STORAGE] = "path_not_found"
@@ -275,7 +285,9 @@ async def _validate_forwarded_emails(user_input: dict, errors: dict) -> None:
errors[CONF_FORWARDED_EMAILS] = status[0]
async def _validate_user_input(user_input: dict) -> tuple:
async def _validate_user_input(
user_input: dict, hass: HomeAssistant | None = None
) -> tuple:
"""Validate user input from config flow.
Returns tuple with error messages and modified user_input
@@ -303,7 +315,7 @@ async def _validate_user_input(user_input: dict) -> tuple:
errors[CONF_GENERATE_MP4] = "ffmpeg_not_found"
# Validate file paths
_validate_path_input(user_input, errors)
_validate_path_input(user_input, errors, hass)
# Normalize CONF_FOLDER: if it has exactly 1 folder, store as string
if CONF_FOLDER in user_input:
@@ -555,6 +567,10 @@ async def _get_schema_step_2(
CONF_GENERATE_MP4,
default=_get_default(CONF_GENERATE_MP4, False),
): cv.boolean,
vol.Optional(
CONF_USPS_PLACEHOLDER,
default=_get_default(CONF_USPS_PLACEHOLDER, DEFAULT_USPS_PLACEHOLDER),
): cv.boolean,
vol.Optional(
CONF_ALLOW_EXTERNAL,
default=_get_default(CONF_ALLOW_EXTERNAL, False),
@@ -975,7 +991,7 @@ class MailAndPackagesFlowHandler(
"""Configure form step 2."""
self._errors = {}
if user_input is not None:
self._errors, user_input = await _validate_user_input(user_input)
self._errors, user_input = await _validate_user_input(user_input, self.hass)
self._data.update(user_input)
_LOGGER.debug("RESOURCES: %s", self._data[CONF_RESOURCES])
if len(self._errors) == 0:
@@ -1012,12 +1028,13 @@ class MailAndPackagesFlowHandler(
CONF_FOLDER: DEFAULT_FOLDER,
CONF_SCAN_INTERVAL: DEFAULT_SCAN_INTERVAL,
CONF_CUSTOM_DAYS: DEFAULT_CUSTOM_DAYS,
CONF_PATH: self.hass.config.path() + DEFAULT_PATH,
CONF_PATH: self.hass.config.path(DEFAULT_PATH),
CONF_DURATION: DEFAULT_GIF_DURATION,
CONF_IMAGE_SECURITY: DEFAULT_IMAGE_SECURITY,
CONF_IMAP_TIMEOUT: DEFAULT_IMAP_TIMEOUT,
CONF_GENERATE_GRID: False,
CONF_GENERATE_MP4: False,
CONF_USPS_PLACEHOLDER: DEFAULT_USPS_PLACEHOLDER,
CONF_ALLOW_EXTERNAL: DEFAULT_ALLOW_EXTERNAL,
CONF_CUSTOM_IMG: DEFAULT_CUSTOM_IMG,
CONF_AMAZON_CUSTOM_IMG: DEFAULT_AMAZON_CUSTOM_IMG,
@@ -1045,7 +1062,7 @@ class MailAndPackagesFlowHandler(
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
self._errors, user_input = await _validate_user_input(self._data, self.hass)
if len(self._errors) == 0:
return await self.async_step_config_storage()
return await self._show_config_3(user_input)
@@ -1076,7 +1093,7 @@ class MailAndPackagesFlowHandler(
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
self._errors, user_input = await _validate_user_input(self._data, self.hass)
if len(self._errors) == 0:
if (
self._data.get(CONF_CUSTOM_IMG)
@@ -1117,7 +1134,7 @@ class MailAndPackagesFlowHandler(
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
self._errors, user_input = await _validate_user_input(self._data, self.hass)
if len(self._errors) == 0:
if any(
sensor in self._data[CONF_RESOURCES] for sensor in AMAZON_SENSORS
@@ -1150,7 +1167,7 @@ class MailAndPackagesFlowHandler(
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
self._errors, user_input = await _validate_user_input(self._data, self.hass)
if len(self._errors) == 0:
return self.async_create_entry(
title=f"Mail and Packages ({self._data[CONF_HOST]})",
@@ -1254,7 +1271,7 @@ class MailAndPackagesFlowHandler(
_LOGGER.debug("Loading step 2...")
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(user_input)
self._errors, user_input = await _validate_user_input(user_input, self.hass)
if len(self._errors) == 0:
if self._data.get(CONF_ALLOW_FORWARDED_EMAILS, False):
return await self.async_step_reconfig_forwarded_emails()
@@ -1300,7 +1317,7 @@ class MailAndPackagesFlowHandler(
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
self._errors, user_input = await _validate_user_input(self._data, self.hass)
if len(self._errors) == 0:
return await self.async_step_reconfig_storage()
@@ -1332,7 +1349,7 @@ class MailAndPackagesFlowHandler(
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
self._errors, user_input = await _validate_user_input(self._data, self.hass)
if len(self._errors) == 0:
has_custom_image = (
self._data.get(CONF_CUSTOM_IMG)
@@ -1375,7 +1392,7 @@ class MailAndPackagesFlowHandler(
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
self._errors, user_input = await _validate_user_input(self._data, self.hass)
if len(self._errors) == 0:
if any(
sensor in self._data.get(CONF_RESOURCES, [])
@@ -1404,7 +1421,7 @@ class MailAndPackagesFlowHandler(
self._errors = {}
if user_input is not None:
self._data.update(user_input)
self._errors, user_input = await _validate_user_input(self._data)
self._errors, user_input = await _validate_user_input(self._data, self.hass)
if len(self._errors) == 0:
self.hass.config_entries.async_update_entry(
self._entry,
+13 -1
View File
@@ -12,7 +12,7 @@ from .entity import MailandPackagesBinarySensorEntityDescription
DOMAIN = "mail_and_packages"
DOMAIN_DATA = f"{DOMAIN}_data"
VERSION = "0.5.9"
VERSION = "0.5.15"
ISSUE_URL = "http://github.com/moralmunky/Home-Assistant-Mail-And-Packages"
PLATFORM = "sensor"
PLATFORMS = ["binary_sensor", "camera", "sensor"]
@@ -83,6 +83,7 @@ CONF_ALLOW_FORWARDED_EMAILS = "allow_forwarded_emails"
CONF_FORWARDED_EMAILS = "forwarded_emails"
CONF_FORWARDING_HEADER = "forwarding_header"
CONF_CUSTOM_DAYS = "custom_days"
CONF_USPS_PLACEHOLDER = "usps_placeholder"
# Defaults
DEFAULT_CAMERA_NAME = "Mail USPS Camera"
@@ -130,6 +131,7 @@ DEFAULT_STORAGE = "custom_components/mail_and_packages/images/"
DEFAULT_ALLOW_FORWARDED_EMAILS = False
DEFAULT_FORWARDED_EMAILS = "(none)"
DEFAULT_FORWARDING_HEADER = "(none)"
DEFAULT_USPS_PLACEHOLDER = True
# Amazon
AMAZON_DOMAINS = [
@@ -173,6 +175,7 @@ AMAZON_SHIPMENT_SUBJECT = [
"Shipped:",
"Enviado:",
"Out for delivery:",
"Spedito:",
]
AMAZON_ORDERED_SUBJECT = ["Ordered:", "Pedido efetuado:"]
AMAZON_EMAIL = [
@@ -218,6 +221,7 @@ AMAZON_TIME_PATTERN = [
"Chega ",
"Verwachte bezorgdatum:",
"Votre date de livraison prévue est :",
"In arrivo",
]
AMAZON_TIME_PATTERN_END = [
"Previously expected:",
@@ -252,6 +256,10 @@ AMAZON_TIME_PATTERN_REGEX = [
"Wordt bezorgd op (\\w+ \\d+ \\w+)",
"Wordt bezorgd op (\\w+ \\d+)",
"Wordt (\\w+) bezorgd",
"In arrivo (\\w+ \\d+) - (\\w+ \\d+)",
"In arrivo (\\w+ \\d+)",
"In arrivo (\\w+ \\d*)",
"In arrivo (\\w+)",
]
AMAZON_EXCEPTION_SUBJECT = "Delivery update:"
AMAZON_EXCEPTION_BODY = "running late"
@@ -435,6 +443,7 @@ SENSOR_DATA = {
"donotreply_odd@dhl.com",
"NoReply.ODD@dhl.com",
"noreply@dhl.de",
"no-reply@dhl.de",
"pl.no.reply@dhl.com",
"support@dhl.com",
"noreply@dhlecommerce.nl",
@@ -448,6 +457,7 @@ SENSOR_DATA = {
"liegt am gewünschten Ablageort",
"Ihre Sendung liegt im Briefkasten",
"Zustellung an Ablageort",
"Ablageort",
"Sendung zugestellt",
"Paket wurde zugestellt",
"Ihre AliExpress Sendung liegt im Briefkasten",
@@ -474,6 +484,7 @@ SENSOR_DATA = {
"donotreply_odd@dhl.com",
"NoReply.ODD@dhl.com",
"noreply@dhl.de",
"no-reply@dhl.de",
"pl.no.reply@dhl.com",
"support@dhl.com",
"noreply@dhlecommerce.nl",
@@ -500,6 +511,7 @@ SENSOR_DATA = {
"scheduled for delivery TODAY",
"zostanie dziś do Państwa doręczona",
"wird Ihnen heute",
"wird Ihnen voraussichtlich",
"heute zwischen",
" - Shipment is out with courier for delivery - ",
"Shipment is scheduled for delivery",
@@ -23,6 +23,7 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_entry_oauth2_flow
from homeassistant.helpers import issue_registry as ir
from homeassistant.helpers.update_coordinator import (
ConfigEntryAuthFailed,
DataUpdateCoordinator,
@@ -249,21 +250,35 @@ class MailDataUpdateCoordinator(DataUpdateCoordinator):
)
except InvalidAuth as err:
_LOGGER.error("Authentication failed: %s", err)
# Create a repairs issue for authentication failure
ir.async_create_issue(
self.hass,
DOMAIN,
"auth_failed",
is_fixable=True,
severity=ir.IssueSeverity.ERROR,
translation_key="auth_failed",
data={"entry_id": self.config_entry.entry_id}
if self.config_entry
else None,
)
raise ConfigEntryAuthFailed from err
except Exception as err:
_LOGGER.error("Error logging into IMAP: %s", err)
raise UpdateFailed(f"Login failed: {err}") from err
# Login succeeded, delete the issue if it exists
issue_registry = ir.async_get(self.hass)
if (DOMAIN, "auth_failed") in issue_registry.issues:
ir.async_delete_issue(self.hass, DOMAIN, "auth_failed")
folders = config.get(CONF_FOLDER)
if not folders:
folders = ["INBOX"]
elif isinstance(folders, str):
if isinstance(folders, str):
folders = [folders]
elif isinstance(folders, (list, tuple, set)):
folders = [f for f in folders if isinstance(f, str) and f]
if not folders:
folders = ["INBOX"]
else:
folders = []
if not folders:
folders = ["INBOX"]
account._folders = folders # noqa: SLF001
account._current_folder = None # noqa: SLF001
@@ -365,9 +380,34 @@ class MailDataUpdateCoordinator(DataUpdateCoordinator):
)
in_transit = self._in_transit_tracking.get(prefix, {})
if in_transit:
# A carrier that reported DELIVERING/EXCEPTION tracking details
# this scan must have its count overridden even when the
# in-transit map ends up EMPTY: when every tracked package has a
# delivered notification, the raw IMAP count (which cannot dedup
# prior-day deliveries) would otherwise leak through as the
# sensor value. Batch-level dedup already zeroes the count for
# shippers that emit tracking details, so this is defense in
# depth at the state-machine layer. Delivered-only details must
# NOT trigger the override: a carrier whose delivering emails
# yielded no extractable tracking numbers has a legitimate
# email-based count that tracking-level dedup cannot verify —
# and carriers with no tracking details at all keep their
# email-count value untouched.
has_details = any(
f"{prefix}_{suffix}" in tracking_details
for suffix in ("delivering", "exception")
)
if in_transit or has_details:
if not in_transit and data.get(f"{prefix}_delivering"):
_LOGGER.debug(
"Prefix '%s': no tracked packages remain in transit — "
"overriding delivering count %s -> 0",
prefix,
data.get(f"{prefix}_delivering"),
)
data[f"{prefix}_tracking"] = list(in_transit.keys())
data[f"{prefix}_delivering"] = len(in_transit)
if in_transit:
delivered_count = data.get(f"{prefix}_delivered", 0)
data[f"{prefix}_packages"] = len(in_transit) + (
delivered_count if isinstance(delivered_count, int) else 0
@@ -523,7 +563,7 @@ class MailDataUpdateCoordinator(DataUpdateCoordinator):
path = f"{image_path}{base_name}/"
# Use absolute path for file existence check
delivery_image_relative = f"{path}{image}"
delivery_image = f"{self.hass.config.path()}/{delivery_image_relative}"
delivery_image = self.hass.config.path(delivery_image_relative)
_LOGGER.debug(
"Full %s image path: %s",
base_name.title(),
@@ -114,7 +114,7 @@ def get_resources(hass: HomeAssistant | None = None) -> dict:
def copy_images(hass: HomeAssistant, config: ConfigEntry) -> None:
"""Copy processed images to www directory."""
image_path = Path(hass.config.path()) / default_image_path(hass, config)
image_path = Path(hass.config.path(default_image_path(hass, config)))
www_path = Path(hass.config.path()) / "www" / "mail_and_packages"
if not www_path.is_dir():
@@ -18,5 +18,5 @@
"dateparser",
"aioimaplib"
],
"version": "0.5.9"
"version": "0.5.15"
}
@@ -0,0 +1,58 @@
"""Repairs platform for Mail and Packages."""
from __future__ import annotations
from typing import Any
import voluptuous as vol
from homeassistant.components.repairs import RepairsFlow
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult
from .const import DOMAIN
class AuthRepairFlow(RepairsFlow):
"""Handler for repairs flow."""
def __init__(self, entry_id: str | None) -> None:
"""Initialize."""
self.entry_id = entry_id
async def async_step_init(
self, user_input: dict[str, str] | None = None
) -> FlowResult:
"""Handle the first step of a repair flow."""
return await self.async_step_confirm(user_input)
async def async_step_confirm(
self, user_input: dict[str, str] | None = None
) -> FlowResult:
"""Handle confirm step."""
if user_input is not None:
if self.entry_id:
entry = self.hass.config_entries.async_get_entry(self.entry_id)
else:
entries = self.hass.config_entries.async_entries(DOMAIN)
entry = entries[0] if entries else None
if entry:
entry.async_start_reauth(self.hass)
return self.async_create_entry(title="", data={})
return self.async_show_form(
step_id="confirm",
data_schema=vol.Schema({}),
)
async def async_create_fix_flow(
hass: HomeAssistant,
issue_id: str,
data: dict[str, Any] | None,
) -> RepairsFlow:
"""Create a flow to fix a specific issue."""
if issue_id == "auth_failed":
entry_id = data.get("entry_id") if data else None
return AuthRepairFlow(entry_id)
raise ValueError(f"Unknown issue {issue_id}")
+15 -32
View File
@@ -12,6 +12,7 @@ from homeassistant.components.sensor import SensorEntity, SensorEntityDescriptio
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_RESOURCES
from homeassistant.core import HomeAssistant
from homeassistant.helpers.network import NoURLAvailableError, get_url
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import MailAndPackagesConfigEntry
@@ -118,6 +119,8 @@ class PackagesSensor(CoordinatorEntity, SensorEntity):
@property
def native_value(self) -> Any:
"""Return the state of the sensor."""
if self.coordinator.data is None:
return None
value = self.coordinator.data.get(self.type)
if self.type == "mail_updated":
@@ -146,6 +149,8 @@ class PackagesSensor(CoordinatorEntity, SensorEntity):
"""Return device specific state attributes."""
attr = {}
data = self.coordinator.data
if data is None:
return attr
if any(
sensor in self.type
@@ -154,10 +159,6 @@ class PackagesSensor(CoordinatorEntity, SensorEntity):
if tracking := data.get(self._tracking_key):
attr[ATTR_TRACKING_NUM] = tracking
# Catch no data entries
if self.data is None:
return attr
if "Amazon" in self._name:
self._add_amazon_attributes(attr, data)
elif self._name == "Mail USPS Mail":
@@ -225,6 +226,9 @@ class ImagePathSensors(CoordinatorEntity, SensorEntity):
@property
def native_value(self) -> str | None:
"""Return the state of the sensor."""
if self.coordinator.data is None:
return None
image = ""
the_path = None
@@ -239,10 +243,10 @@ class ImagePathSensors(CoordinatorEntity, SensorEntity):
if self.type == "usps_mail_image_system_path" and image:
_LOGGER.debug("Updating system image path to: %s", path)
the_path = f"{self.hass.config.path()}/{path}{image}"
the_path = self.hass.config.path(path, image)
elif self.type == "usps_mail_grid_image_path" and grid_image:
_LOGGER.debug("Updating grid image path to: %s", path)
the_path = f"{self.hass.config.path()}/{path}{grid_image}"
the_path = self.hass.config.path(path, grid_image)
elif self.type == "usps_mail_image_url" and image:
url = self._get_base_url()
if url:
@@ -250,33 +254,12 @@ class ImagePathSensors(CoordinatorEntity, SensorEntity):
return the_path
def _get_base_url(self) -> str | None:
"""Return the best available base URL for building image links.
Priority: explicit external URL → HA Cloud remote URL → internal URL.
"""
if self.hass.config.external_url:
return self.hass.config.external_url
# Try Home Assistant Cloud (Nabu Casa) — its remote URL is not exposed via
# hass.config.external_url when "Use Home Assistant Cloud" is selected.
"""Return the best available base URL for building image links."""
try:
from homeassistant.components.cloud import ( # noqa: PLC0415
CloudNotAvailable,
async_remote_ui_url,
)
except ImportError:
pass
else:
try:
return async_remote_ui_url(self.hass)
except (CloudNotAvailable, KeyError):
_LOGGER.debug("HA Cloud remote URL not available.")
if self.hass.config.internal_url:
_LOGGER.debug("Falling back to internal URL for image link.")
return self.hass.config.internal_url
return None
return get_url(self.hass, prefer_external=True)
except NoURLAvailableError:
_LOGGER.debug("No URL available for image link.")
return None
@property
def should_poll(self) -> bool:
@@ -104,12 +104,23 @@ class AmazonShipper(Shipper):
days = self.config.get(CONF_AMAZON_DAYS, DEFAULT_AMAZON_DAYS)
domain = self.config.get(CONF_AMAZON_DOMAIN)
if sensor_type in [AMAZON_PACKAGES, AMAZON_ORDER]:
param = "count" if sensor_type == AMAZON_PACKAGES else "order"
result = await self._parse_amazon_emails(
account, param, fwds, days, domain, cache, forwarding_header
if sensor_type == AMAZON_PACKAGES:
count = await self._parse_amazon_emails(
account, "count", fwds, days, domain, cache, forwarding_header
)
return {sensor_type: result}
orders = await self._parse_amazon_emails(
account, "order", fwds, days, domain, cache, forwarding_header
)
return {
AMAZON_PACKAGES: count,
AMAZON_ORDER: orders,
}
if sensor_type == AMAZON_ORDER:
result = await self._parse_amazon_emails(
account, "order", fwds, days, domain, cache, forwarding_header
)
return {AMAZON_ORDER: result}
if sensor_type == AMAZON_HUB:
return await self._amazon_hub(account, fwds, cache, forwarding_header)
@@ -199,7 +210,17 @@ class AmazonShipper(Shipper):
if param == "count":
return final_count
return list(context["all_shipped_orders"])
return [
order_id
for order_id in context["all_shipped_orders"]
if context["packages_arriving_today"].get(order_id, 0)
> context["delivered_packages"].get(order_id, 0)
or (
context["packages_arriving_today"].get(order_id, 0) == 0
and context["delivered_packages"].get(order_id, 0) == 0
)
]
async def _process_amazon_email(
self,
@@ -297,7 +297,14 @@ class GenericShipper(Shipper):
tracking = set(sensor_res.get(ATTR_TRACKING, []))
if sensor.endswith("_delivered"):
shippers[prefix]["delivered"].update(tracking)
# ATTR_TRACKING on _delivered sensors holds only TODAY's
# deliveries (so the sensor resets at midnight); dedup must
# use the extended-window list or packages delivered on a
# previous day are never subtracted from _delivering.
extended = sensor_res.get("pre_filtered_tracking")
shippers[prefix]["delivered"].update(
tracking if extended is None else set(extended)
)
elif sensor.endswith(("_delivering", "_exception")):
shippers[prefix]["delivering"].update(tracking)
shippers[prefix]["update_targets"].append((sensor, sensor_res))
@@ -662,7 +669,11 @@ class GenericShipper(Shipper):
msg_parts = (await email_fetch(account, eid, "(RFC822)"))[1]
for response_part in msg_parts:
if isinstance(response_part, (bytes, bytearray)):
if generic_delivery_image_extraction(
# The extraction does blocking file I/O (the image
# write) and CPU-heavy email parsing — run the whole
# sync function off the event loop.
if await self.hass.async_add_executor_job(
generic_delivery_image_extraction,
response_part,
s_config["image_path"],
s_config["image_name"],
@@ -27,6 +27,7 @@ from custom_components.mail_and_packages.const import (
CONF_FORWARDING_HEADER,
CONF_GENERATE_GRID,
CONF_GENERATE_MP4,
CONF_USPS_PLACEHOLDER,
DEFAULT_CUSTOM_IMG_FILE,
SENSOR_DATA,
)
@@ -103,32 +104,17 @@ class USPSShipper(Shipper):
images = await self._process_usps_images(all_msg_content, images)
image_count = len(images)
if image_count > 0:
await self._generate_mail_image(
images,
config["image_output_path"],
config["image_name"],
config["gif_duration"],
images_delete,
)
elif image_count == 0:
await self._copy_nomail_image(
config["image_output_path"],
config["image_name"],
config["custom_img"],
# Generate filtered list for GIF/MP4/Grid
gif_images = images.copy()
if not config.get("usps_placeholder", True):
placeholder_str = str(
Path(__file__).parent.parent / "image-no-mailpieces700.jpg"
)
if placeholder_str in gif_images:
gif_images.remove(placeholder_str)
if config["gen_mp4"]:
await self._generate_mp4_video(
config["image_output_path"],
config["image_name"],
)
if config["gen_grid"]:
await self._generate_grid_image(
config["image_output_path"],
config["image_name"],
image_count,
)
# Generate camera media
await self._create_camera_media(gif_images, config, images_delete)
return {
ATTR_COUNT: image_count,
@@ -159,6 +145,40 @@ class USPSShipper(Shipper):
return res
async def _create_camera_media(
self,
gif_images: list,
config: dict,
images_delete: list,
):
"""Create camera media (GIF, MP4, and Grid)."""
if len(gif_images) > 0:
await self._generate_mail_image(
gif_images,
config["image_output_path"],
config["image_name"],
config["gif_duration"],
images_delete,
)
else:
await self._copy_nomail_image(
config["image_output_path"],
config["image_name"],
config["custom_img"],
)
if config["gen_mp4"]:
await self._generate_mp4_video(
config["image_output_path"],
config["image_name"],
)
if config["gen_grid"]:
await self._generate_grid_image(
config["image_output_path"],
config["image_name"],
len(gif_images),
)
async def _generate_mp4_video(self, path: str, name: str):
"""Generate MP4 video from images."""
await self.hass.async_add_executor_job(_generate_mp4, path, name)
@@ -260,6 +280,7 @@ class USPSShipper(Shipper):
"custom_img": self.config.get(CONF_CUSTOM_IMG_FILE)
or DEFAULT_CUSTOM_IMG_FILE,
"gen_grid": self.config.get(CONF_GENERATE_GRID),
"usps_placeholder": self.config.get(CONF_USPS_PLACEHOLDER, True),
}
async def _search_informed_delivery(self, account: IMAP4_SSL) -> tuple:
@@ -48,6 +48,7 @@
"generate_grid": "Create image grid for LLM vision models",
"generate_mp4": "Create mp4 from images",
"allow_external": "Create image for notification apps",
"usps_placeholder": "Include USPS no-image placeholder in GIF?",
"custom_img": "Use custom USPS 'no mail' image?",
"amazon_custom_img": "Use custom 'no Amazon delivery' image?",
"ups_custom_img": "Use custom 'no UPS delivery' image?",
@@ -121,6 +122,7 @@
"resources": "Sensors List",
"imap_timeout": "Mailbox scan time limit (seconds, minimum 10)",
"allow_external": "Create image for notification apps",
"usps_placeholder": "Include USPS no-image placeholder in GIF?",
"custom_img": "Use custom USPS 'no mail' image?",
"amazon_custom_img": "Use custom 'no Amazon delivery' image?",
"ups_custom_img": "Use custom 'no UPS delivery' image?",
@@ -195,5 +197,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Mail and Packages authentication failed",
"fix_flow": {
"step": {
"confirm": {
"title": "Re-authenticate Mail Server",
"description": "Authentication to your IMAP mail server has failed. Click submit to start the re-authentication flow."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Utilitza la imatge personalitzada genèrica 'no hi ha lliurament'?",
"generate_grid": "Crea una quadrícula d'imatges per a models de visió LLM",
"allow_forwarded_emails": "Permet els correus electrònics reenviats a més del valor predeterminat d'un servei (p. ex., no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Incloure la imatge de substitució de l'USPS sense imatge al GIF?"
},
"description": "Finalitzeu la configuració personalitzant la següent en funció de la vostra instal·lació de correu electrònic i la instal·lació d'assistència a casa. \n\n Per obtenir més informació sobre les opcions [Integració de paquets i correus] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), reviseu les opcions [configuració, plantilles , secció i automatitzacions] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) a GitHub.",
"title": "Correu i paquets (pas 2 de 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Utilitza la imatge personalitzada genèrica 'no hi ha lliurament'?",
"generate_grid": "Crea una quadrícula d'imatges per a models de visió LLM",
"allow_forwarded_emails": "Permet els correus electrònics reenviats a més del valor predeterminat d'un servei (p. ex., no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Incloure la imatge de substitució de l'USPS sense imatge al GIF?"
},
"description": "Acabeu la configuració personalitzant el següent en funció de l'estructura del vostre correu electrònic i de la instal·lació de Home Assistant.\n\nPer obtenir més detalls sobre les opcions d'[integració de correu i paquets](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), consulteu la [secció de configuració, plantilles i automatitzacions](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) a GitHub.\n\nSi utilitzeu correus electrònics reenviats d'Amazon, separeu cada adreça amb una coma o introduïu (none) per esborrar aquesta configuració.",
"title": "Correu i paquets (pas 2 de 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "L'autenticació de Mail and Packages ha fallat",
"fix_flow": {
"step": {
"confirm": {
"title": "Tornar a autenticar el servidor de correu",
"description": "L'autenticació amb el vostre servidor de correu IMAP ha fallat. Feu clic a envia per iniciar el flux de reautenticació."
}
}
}
}
}
}
@@ -40,7 +40,8 @@
"generic_custom_img": "Použít vlastní obrázek obecný 'bez dodání'?",
"allow_forwarded_emails": "Povolit přeposílané e-maily kromě výchozí hodnoty služby (např. no-reply@usps.com)",
"generate_grid": "Create image grid for LLM vision models",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Zahrnout zástupný symbol USPS bez obrázku do GIF?"
},
"description": "Dokončete konfiguraci přizpůsobením následujících položek na základě struktury e-mailu a instalace Home Assistant.\n\nPodrobnosti o [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) můžete zkontrolovat na [configurace, styly a automatizace](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHubu.",
"title": "Mail and Packages (Krok 2 ze 3)"
@@ -152,7 +153,8 @@
"walmart_custom_img": "Use custom 'no Walmart delivery' image?",
"fedex_custom_img": "Use custom 'no FedEx delivery' image?",
"allow_forwarded_emails": "Allow forwarded emails in addition to a service's default (e.g. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Zahrnout zástupný symbol USPS bez obrázku do GIF?"
},
"description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nIf using Amazon forwarded emails please separate each address with a comma or enter (none) to clear this setting.",
"title": "Mail and Packages (Step 2 of 2)"
@@ -265,5 +267,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Ověření Mail and Packages selhalo",
"fix_flow": {
"step": {
"confirm": {
"title": "Znovu ověřit poštovní server",
"description": "Ověření k vašemu poštovnímu serveru IMAP selhalo. Kliknutím na odeslat spustíte proces opětovného ověření."
}
}
}
}
}
}
@@ -37,7 +37,8 @@
"post_de_custom_img": "Benutzerdefiniertes Post DE 'keine Post' Bild verwenden?",
"generate_grid": "Erstellen Sie ein Bildraster für LLM-Vision-Modelle",
"allow_forwarded_emails": "Weitergeleitete E-Mails zusätzlich zu den Standardwerten eines Dienstes zulassen (z. B. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "USPS-Platzhalter ohne Bild im GIF einschließen?"
},
"description": "Beenden Sie die Konfiguration, indem Sie Folgendes basierend auf Ihrer E-Mail-Struktur und der Installation von Home Assistant anpassen. \n\n Weitere Informationen zu den Optionen [Mail- und Paketintegration] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) finden Sie in den [Konfiguration, Vorlagen und Abschnitt Automatisierungen] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) auf GitHub.",
"title": "Briefe und Pakete (Schritt 2 von 2)"
@@ -83,7 +84,8 @@
"post_de_custom_img": "Benutzerdefiniertes Post DE 'keine Post' Bild verwenden?",
"generate_grid": "Erstellen Sie ein Bildraster für LLM-Vision-Modelle",
"allow_forwarded_emails": "Weitergeleitete E-Mails zusätzlich zu den Standardwerten eines Dienstes zulassen (z. B. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "USPS-Platzhalter ohne Bild im GIF einschließen?"
},
"description": "Schließen Sie die Konfiguration ab, indem Sie das Folgende an Ihre E-Mail-Struktur und Home Assistant-Installation anpassen.\n\nWeitere Informationen zu den [Mail und Packages Integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) Optionen finden Sie im [Konfigurations-, Vorlagen- und Automatisierungsabschnitt](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) auf GitHub.\n\nWenn Sie weitergeleitete E-Mails von Amazon verwenden, trennen Sie bitte jede Adresse durch ein Komma oder geben Sie (keine) ein, um diese Einstellung zu löschen.",
"title": "Briefe und Pakete (Schritt 2 von 2)"
@@ -203,5 +205,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Mail and Packages Authentifizierung fehlgeschlagen",
"fix_flow": {
"step": {
"confirm": {
"title": "Mailserver neu authentifizieren",
"description": "Die Authentifizierung bei Ihrem IMAP-Mailserver ist fehlgeschlagen. Klicken Sie auf Senden, um den Reauthentifizierungs-Flow zu starten."
}
}
}
}
}
}
@@ -48,6 +48,7 @@
"imap_timeout": "Mailbox scan time limit (seconds, minimum 10)",
"generate_mp4": "Create mp4 from images",
"allow_external": "Create image for notification apps",
"usps_placeholder": "Include USPS no-image placeholder in GIF?",
"custom_img": "Use custom USPS 'no mail' image?",
"amazon_custom_img": "Use custom 'no Amazon delivery' image?",
"ups_custom_img": "Use custom 'no UPS delivery' image?",
@@ -116,6 +117,7 @@
"resources": "Sensors List",
"imap_timeout": "Mailbox scan time limit (seconds, minimum 10)",
"allow_external": "Create image for notification apps",
"usps_placeholder": "Include USPS no-image placeholder in GIF?",
"custom_img": "Use custom USPS 'no mail' image?",
"amazon_custom_img": "Use custom 'no Amazon delivery' image?",
"ups_custom_img": "Use custom 'no UPS delivery' image?",
@@ -209,5 +211,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Mail and Packages authentication failed",
"fix_flow": {
"step": {
"confirm": {
"title": "Re-authenticate Mail Server",
"description": "Authentication to your IMAP mail server has failed. Click submit to start the re-authentication flow."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "¿Usar imagen personalizada genérica 'sin entrega'?",
"generate_grid": "Crear cuadrícula de imágenes para modelos de visión LLM",
"allow_forwarded_emails": "Permitir correos electrónicos reenviados además del valor predeterminado de un servicio (p. ej., no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "¿Incluir marcador de posición sin imagen de USPS en el GIF?"
},
"description": "Termine la configuración personalizando lo siguiente según su estructura de correo electrónico y la instalación de Home Assistant. \n\n Para obtener detalles sobre las opciones [Integración de correo y paquetes] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) revise las [configuración, plantillas , y la sección de automatizaciones] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) en GitHub.",
"title": "Correo y paquetes (Paso 2 de 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "¿Usar imagen personalizada genérica 'sin entrega'?",
"generate_grid": "Crear cuadrícula de imágenes para modelos de visión LLM",
"allow_forwarded_emails": "Permitir correos electrónicos reenviados además del valor predeterminado de un servicio (p. ej., no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "¿Incluir marcador de posición sin imagen de USPS en el GIF?"
},
"description": "Finalice la configuración personalizando lo siguiente en función de la estructura de su correo electrónico y la instalación de Home Assistant.\n\nPara obtener detalles sobre las opciones de [integración de correo y paquetes](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), revise la [sección de configuración, plantillas y automatizaciones](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) en GitHub.\n\nSi utiliza correos electrónicos reenviados de Amazon, separe cada dirección con una coma o ingrese (ninguno) para borrar esta configuración.",
"title": "Correo y paquetes (Paso 2 de 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Error de autenticación de Mail and Packages",
"fix_flow": {
"step": {
"confirm": {
"title": "Volver a autenticar el servidor de correo",
"description": "Error al autenticar en su servidor de correo IMAP. Haga clic en enviar para iniciar el flujo de reautenticación."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "¿Usar imagen personalizada genérica 'sin entrega'?",
"generate_grid": "Crear cuadrícula de imágenes para modelos de visión LLM",
"allow_forwarded_emails": "Permitir correos electrónicos reenviados además del valor predeterminado de un servicio (p. ej., no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "¿Incluir marcador de posición sin imagen de USPS en el GIF?"
},
"description": "Termine la configuración personalizando lo siguiente según su estructura de correo electrónico y la instalación de Home Assistant. \n\n Para obtener detalles sobre las opciones [Integración de correo y paquetes] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) revise las [configuración, plantillas , y la sección de automatizaciones] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) en GitHub.",
"title": "Correo y paquetes (Paso 2 de 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "¿Usar imagen personalizada genérica 'sin entrega'?",
"generate_grid": "Crear cuadrícula de imágenes para modelos de visión LLM",
"allow_forwarded_emails": "Permitir correos electrónicos reenviados además del valor predeterminado de un servicio (p. ej., no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "¿Incluir marcador de posición sin imagen de USPS en el GIF?"
},
"description": "Finalice la configuración personalizando lo siguiente en función de la estructura de su correo electrónico y la instalación de Home Assistant.\n\nPara obtener detalles sobre las opciones de [integración de correo y paquetes](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), revise la [sección de configuración, plantillas y automatizaciones](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) en GitHub.\n\nSi utiliza correos electrónicos reenviados de Amazon, separe cada dirección con una coma o ingrese (ninguno) para borrar esta configuración.",
"title": "Correo y paquetes (Paso 2 de 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Error de autenticación de Mail and Packages",
"fix_flow": {
"step": {
"confirm": {
"title": "Volver a autenticar el servidor de correo",
"description": "Error al autenticar en su servidor de correo IMAP. Haga clic en enviar para iniciar el flujo de reautenticación."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Käytä mukautettua yleistä 'ei toimituksia' kuvaa?",
"generate_grid": "Luo kuvaverkko LLM-näkömalleille",
"allow_forwarded_emails": "Salli edelleenlähetetyt sähköpostit palvelun oletusarvon lisäksi (esim. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Sisällytä USPS:n ei-kuvaa -paikkamerkki GIF-tiedostoon?"
},
"description": "Viimeistele kokoonpano mukauttamalla seuraava sähköpostirakenteen ja Home Assistant -asennuksen perusteella. \n\n Lisätietoja [Posti ja paketit-integroinnista] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) -asetuksista on [kokoonpano, mallit , ja automaatiot-osio] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) GitHubissa.",
"title": "Posti ja paketit (vaihe 2/2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Käytä mukautettua yleistä 'ei toimituksia' kuvaa?",
"generate_grid": "Luo kuvaverkko LLM-näkömalleille",
"allow_forwarded_emails": "Salli edelleenlähetetyt sähköpostit palvelun oletusarvon lisäksi (esim. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Sisällytä USPS:n ei-kuvaa -paikkamerkki GIF-tiedostoon?"
},
"description": "Suorita määritys loppuun mukauttamalla seuraavat sähköpostirakenteeseesi ja Home Assistant -asennukseesi perustuen.\n\nLisätietoja [Mail and Packages -integraation](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) vaihtoehdoista löydät GitHubista [määritys-, mallit- ja automaatiot-osiossa](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration).\n\nJos käytät Amazonin välittämiä sähköposteja, erottele jokainen osoite pilkulla tai syötä (none) tyhjentääksesi tämän asetuksen.",
"title": "Posti ja paketit (vaihe 2/2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Mail and Packages -autentikointi epäonnistui",
"fix_flow": {
"step": {
"confirm": {
"title": "Tunnistaudu uudelleen sähköpostipalvelimeen",
"description": "Autentikointi IMAP-sähköpostipalvelimeesi epäonnistui. Napsauta Lähetä aloittaaksesi uudelleentunnistautumisen."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Utiliser une image personnalisée générique 'pas de livraison' ?",
"generate_grid": "Créer une grille d'images pour les modèles de vision LLM",
"allow_forwarded_emails": "Autoriser les e-mails transférés en plus de la valeur par défaut d'un service (par ex. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Inclure l'image d'emplacement sans image USPS dans le GIF ?"
},
"description": "Terminez la configuration en personnalisant les éléments suivants en fonction de votre structure de messagerie et de l'installation de Home Assistant. \n\n Pour plus de détails sur les [Intégration de messagerie et de packages] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), passez en revue les [configuration, modèles et section automatisations] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) sur GitHub.",
"title": "Courrier et colis (étape 2 sur 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Utiliser une image personnalisée générique 'pas de livraison' ?",
"generate_grid": "Créer une grille d'images pour les modèles de vision LLM",
"allow_forwarded_emails": "Autoriser les e-mails transférés en plus de la valeur par défaut d'un service (par ex. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Inclure l'image d'emplacement sans image USPS dans le GIF ?"
},
"description": "Terminez la configuration en personnalisant ce qui suit en fonction de la structure de votre courrier électronique et de l'installation de Home Assistant.\n\nPour plus de détails sur les options d'[intégration de courrier et de colis](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), consultez la [section configuration, modèles et automatisations](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) sur GitHub.\n\nSi vous utilisez des courriels transférés par Amazon, veuillez séparer chaque adresse par une virgule ou entrer (aucun) pour effacer ce paramètre.",
"title": "Courrier et colis (étape 2 sur 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Échec de l'authentification de Mail and Packages",
"fix_flow": {
"step": {
"confirm": {
"title": "Ré-authentifier le serveur de messagerie",
"description": "L'authentification sur votre serveur de messagerie IMAP a échoué. Cliquez sur soumettre pour démarrer le flux de ré-authentification."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Használjon egyéni általános 'nincs szállítás' képet?",
"generate_grid": "Kép rács létrehozása LLM látásmodellekhez",
"allow_forwarded_emails": "Engedélyezze a továbbított e-maileket a szolgáltatás alapértelmezett értékén kívül (pl. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Tartalmazza az USPS kép nélküli helyőrzőjét a GIF-ben?"
},
"description": "Végezze el a konfigurációt az alábbiak testreszabásával az e-mail struktúrája és a Home Assistant telepítése alapján. \n\n A [Levelek és csomagok integrációja] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) opciókkal kapcsolatban tekintse meg a [konfiguráció, sablonok , és az automatizálás szakasz] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) a GitHubon.",
"title": "Levél és csomagok (2. lépés a 2-ből)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Használjon egyéni általános 'nincs szállítás' képet?",
"generate_grid": "Kép rács létrehozása LLM látásmodellekhez",
"allow_forwarded_emails": "Engedélyezze a továbbított e-maileket a szolgáltatás alapértelmezett értékén kívül (pl. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Tartalmazza az USPS kép nélküli helyőrzőjét a GIF-ben?"
},
"description": "Fejezze be a konfigurációt a következők testreszabásával az e-mail struktúrája és a Home Assistant telepítése alapján.\n\nA [Mail and Packages integráció](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) lehetőségeinek részleteiről a GitHub-on található [konfiguráció, sablonok és automatizálások szekcióban](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) található információkat.\n\nHa Amazon továbbított e-maileket használ, kérjük, válassza el minden címet vesszővel, vagy írja be a (none) opciót, hogy törölje ezt a beállítást.",
"title": "Levél és csomagok (2. lépés a 2-ből)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Mail and Packages hitelesítés sikertelen",
"fix_flow": {
"step": {
"confirm": {
"title": "Levelezőszerver újrahitelesítése",
"description": "Nem sikerült a hitelesítés az IMAP levelezőszerveren. Kattintson a küldésre az újrahitelesítési folyamat elindításához."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Usare l'immagine personalizzata generica 'nessuna consegna'?",
"generate_grid": "Crea una griglia di immagini per i modelli di visione LLM",
"allow_forwarded_emails": "Consenti email inoltrate oltre al valore predefinito di un servizio (ad es. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Includere il segnaposto USPS senza immagine nella GIF?"
},
"description": "Termina la configurazione personalizzando quanto segue in base alla struttura della tua e-mail e all'installazione di Home Assistant. \n\n Per i dettagli sulle opzioni [Integrazione posta e pacchetti] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) rivedere le [configurazione, modelli e sezione automazioni] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) su GitHub.",
"title": "Posta e pacchi (passaggio 2 di 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Usare l'immagine personalizzata generica 'nessuna consegna'?",
"generate_grid": "Crea una griglia di immagini per i modelli di visione LLM",
"allow_forwarded_emails": "Consenti email inoltrate oltre al valore predefinito di un servizio (ad es. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Includere il segnaposto USPS senza immagine nella GIF?"
},
"description": "Termina la configurazione personalizzando quanto segue in base alla struttura della tua email e all'installazione di Home Assistant.\n\nPer i dettagli sulle opzioni di [integrazione Mail e Pacchetti](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) consulta la [sezione configurazione, modelli e automazioni](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) su GitHub.\n\nSe utilizzi email inoltrate da Amazon, separa ogni indirizzo con una virgola o inserisci (nessuno) per cancellare questa impostazione.",
"title": "Posta e pacchi (passaggio 2 di 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Autenticazione Mail and Packages fallita",
"fix_flow": {
"step": {
"confirm": {
"title": "Riautentica il server di posta",
"description": "L'autenticazione al server di posta IMAP è fallita. Clicca su invia per avviare la procedura di riautenticazione."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "사용자 정의 일반 '배송 없음' 이미지를 사용하시겠습니까?",
"generate_grid": "LLM 비전 모델을 위한 이미지 그리드 생성",
"allow_forwarded_emails": "서비스 기본값 외에 전달된 이메일 허용 (예: no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "GIF에 USPS 이미지 없음 자리 표시자를 포함하시겠습니까?"
},
"description": "이메일 구조 및 Home Assistant 설치에 따라 다음을 사용자 정의하여 구성을 완료하십시오. \n\n [메일 및 패키지 통합] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) 옵션에 대한 자세한 내용은 [구성, 템플릿 및 자동화 섹션] (https://github.com/moralmunky/Home-Assistant-Mail-and-Packages/wiki/Configuration-and-Email-Settings#configuration)",
"title": "메일 및 패키지 (2/2 단계)"
@@ -80,7 +81,8 @@
"generic_custom_img": "사용자 정의 일반 '배송 없음' 이미지를 사용하시겠습니까?",
"generate_grid": "LLM 비전 모델을 위한 이미지 그리드 생성",
"allow_forwarded_emails": "서비스 기본값 외에 전달된 이메일 허용 (예: no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "GIF에 USPS 이미지 없음 자리 표시자를 포함하시겠습니까?"
},
"description": "이메일 구조와 Home Assistant 설치에 따라 다음을 사용자 정의하여 구성을 완료하십시오.\n\n[Mail and Packages 통합](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) 옵션에 대한 자세한 내용은 GitHub의 [구성, 템플릿, 자동화 섹션](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)을 참조하십시오.\n\nAmazon에서 전달된 이메일을 사용하는 경우 각 주소를 쉼표로 구분하거나 이 설정을 지우려면 (none)을 입력하십시오.",
"title": "메일 및 패키지 (2/2 단계)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Mail and Packages 인증 실패",
"fix_flow": {
"step": {
"confirm": {
"title": "메일 서버 재인증",
"description": "IMAP 메일 서버 인증에 실패했습니다. 제출을 클릭하여 재인증 흐름을 시작하십시오."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Gebruik aangepaste generieke 'geen levering' afbeelding?",
"generate_grid": "Maak een afbeeldingsraster voor LLM-visiemodellen",
"allow_forwarded_emails": "Doorgestuurde e-mails toestaan naast de standaardwaarde van een service (bijv. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "USPS tijdelijke aanduiding zonder afbeelding opnemen in GIF?"
},
"description": "Voltooi de configuratie door het volgende aan te passen op basis van uw e-mailstructuur en Home Assistant-installatie. \n\n Voor meer informatie over de [E-mail en pakketten integratie] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) opties bekijk de [configuratie, sjablonen , en automatisering sectie] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) op GitHub.",
"title": "Mail en pakketten (stap 2 van 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Gebruik aangepaste generieke 'geen levering' afbeelding?",
"generate_grid": "Maak een afbeeldingsraster voor LLM-visiemodellen",
"allow_forwarded_emails": "Doorgestuurde e-mails toestaan naast de standaardwaarde van een service (bijv. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "USPS tijdelijke aanduiding zonder afbeelding opnemen in GIF?"
},
"description": "Rond de configuratie af door het volgende aan te passen op basis van uw e-mailstructuur en Home Assistant-installatie.\n\nVoor details over de [Mail en Packages integratie](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) opties, bekijk de [configuratie, sjablonen en automatiseringen sectie](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) op GitHub.\n\nAls u doorgestuurde e-mails van Amazon gebruikt, scheid dan elk adres met een komma of voer (geen) in om deze instelling te wissen.",
"title": "Mail en pakketten (stap 2 van 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Mail and Packages authenticatie mislukt",
"fix_flow": {
"step": {
"confirm": {
"title": "E-mailserver opnieuw verifiëren",
"description": "Authenticatie bij uw IMAP-mailserver is mislukt. Klik op verzenden om de herauthenticatiestroom te starten."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Bruk tilpasset generisk 'ingen levering' bilde?",
"generate_grid": "Opprett bildegitter for LLM-visjonsmodeller",
"allow_forwarded_emails": "Tillat videresendte e-poster i tillegg til en tjenestes standardverdi (f.eks. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Inkluder USPS plassholder uten bilde i GIF?"
},
"description": "Fullfør konfigurasjonen ved å tilpasse følgende basert på e-poststrukturen og Home Assistant-installasjonen. \n\n For detaljer om alternativene [Mail and Packages] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), les gjennom [konfigurasjon, maler , og automatiseringsdel] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) på GitHub.",
"title": "E-post og pakker (trinn 2 av 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Bruk tilpasset generisk 'ingen levering' bilde?",
"generate_grid": "Opprett bildegitter for LLM-visjonsmodeller",
"allow_forwarded_emails": "Tillat videresendte e-poster i tillegg til en tjenestes standardverdi (f.eks. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Inkluder USPS plassholder uten bilde i GIF?"
},
"description": "Fullfør konfigurasjonen ved å tilpasse følgende basert på din e-poststruktur og Home Assistant-installasjon.\n\nFor detaljer om [Mail and Packages-integrasjonen](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) alternativene, se gjennom [konfigurasjon, maler og automatiseringsseksjonen](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) på GitHub.\n\nHvis du bruker Amazon videresendte e-poster, vennligst skill hver adresse med et komma eller skriv inn (ingen) for å tømme denne innstillingen.",
"title": "E-post og pakker (trinn 2 av 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Autentisering for Mail and Packages mislyktes",
"fix_flow": {
"step": {
"confirm": {
"title": "Autentiser e-postserver på nytt",
"description": "Autentisering mot din IMAP-e-postserver mislyktes. Klikk på send for å starte reautentiseringsflyten."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Użyć niestandardowego obrazu ogólnego 'brak dostawy'?",
"generate_grid": "Utwórz siatkę obrazów dla modeli wizji LLM",
"allow_forwarded_emails": "Zezwalaj na przekierowane e-maile oprócz wartości domyślnej usługi (np. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Dołączyć zarezerwowane miejsce dla USPS bez obrazu do pliku GIF?"
},
"description": "Zakończ konfigurację, dostosowując następujące elementy w oparciu o strukturę poczty e-mail i instalację Home Assistant. \n\n Aby uzyskać szczegółowe informacje na temat opcji [Integracja poczty i pakietów] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) sprawdź opcje [konfiguracja, szablony i sekcja automatyzacji] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHub.",
"title": "Poczta i paczki (krok 2 z 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Użyć niestandardowego obrazu ogólnego 'brak dostawy'?",
"generate_grid": "Utwórz siatkę obrazów dla modeli wizji LLM",
"allow_forwarded_emails": "Zezwalaj na przekierowane e-maile oprócz wartości domyślnej usługi (np. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Dołączyć zarezerwowane miejsce dla USPS bez obrazu do pliku GIF?"
},
"description": "Zakończ konfigurację, dostosowując następujące elementy do struktury swojego e-maila i instalacji Home Assistant.\n\nAby uzyskać szczegółowe informacje na temat opcji [integracji Mail and Packages](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), zapoznaj się z [sekcją konfiguracji, szablonów i automatyzacji](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHubie.\n\nJeśli korzystasz z przekierowanych e-maili Amazon, oddziel każdy adres przecinkiem lub wprowadź (brak), aby wyczyścić to ustawienie.",
"title": "Poczta i paczki (krok 2 z 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Błąd uwierzytelniania Mail and Packages",
"fix_flow": {
"step": {
"confirm": {
"title": "Ponownie uwierzytelnij serwer pocztowy",
"description": "Uwierzytelnienie na serwerze pocztowym IMAP nie powiodło się. Kliknij prześlij, aby rozpocząć proces ponownego uwierzytelniania."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Usar imagem personalizada genérica 'sem entrega'?",
"generate_grid": "Criar grade de imagens para modelos de visão LLM",
"allow_forwarded_emails": "Permitir emails encaminhados além do padrão de um serviço (ex: no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Incluir marcador de posição sem imagem USPS no GIF?"
},
"description": "Conclua a configuração, personalizando o seguinte com base na sua estrutura de email e instalação do Home Assistant. \n\n Para obter detalhes sobre as opções [integração de Mail e Pacotes] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), revise as opções de [configuração, modelos e seção de automações] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) no GitHub.",
"title": "Correio e pacotes (Etapa 2 de 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Usar imagem personalizada genérica 'sem entrega'?",
"generate_grid": "Criar grade de imagens para modelos de visão LLM",
"allow_forwarded_emails": "Permitir emails encaminhados além do padrão de um serviço (ex: no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Incluir marcador de posição sem imagem USPS no GIF?"
},
"description": "Conclua a configuração personalizando o seguinte com base na estrutura do seu email e na instalação do Home Assistant.\n\nPara detalhes sobre as opções de [integração de Correio e Pacotes](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), consulte a [seção de configuração, modelos e automações](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) no GitHub.\n\nSe estiver usando emails encaminhados da Amazon, separe cada endereço com uma vírgula ou insira (nenhum) para limpar essa configuração.",
"title": "Correio e pacotes (Etapa 2 de 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Falha na autenticação de Mail and Packages",
"fix_flow": {
"step": {
"confirm": {
"title": "Reautenticar o Servidor de E-mail",
"description": "A autenticação no seu servidor de e-mail IMAP falhou. Clique em enviar para iniciar o fluxo de reautenticação."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Usar imagem personalizada genérica 'sem entrega'?",
"generate_grid": "Criar grade de imagens para modelos de visão LLM",
"allow_forwarded_emails": "Permitir e-mails encaminhados além do padrão de um serviço (ex: no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Incluir marcador de posição sem imagem USPS no GIF?"
},
"description": "Conclua a configuração, personalizando o seguinte com base na sua estrutura de email e instalação do Home Assistant. \n\n Para obter detalhes sobre as opções [integração de Mail e Pacotes] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), revise as opções de [configuração, modelos e seção de automações] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) no GitHub.",
"title": "Correio e pacotes (Etapa 2 de 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Usar imagem personalizada genérica 'sem entrega'?",
"generate_grid": "Criar grade de imagens para modelos de visão LLM",
"allow_forwarded_emails": "Permitir e-mails encaminhados além do padrão de um serviço (ex: no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Incluir marcador de posição sem imagem USPS no GIF?"
},
"description": "Conclua a configuração personalizando o seguinte com base na estrutura do seu email e na instalação do Home Assistant.\n\nPara detalhes sobre as opções de [integração de Mail e Pacotes](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration), consulte a [seção de configuração, modelos e automações](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) no GitHub.\n\nSe estiver usando emails encaminhados da Amazon, separe cada endereço com uma vírgula ou insira (nenhum) para limpar essa configuração.",
"title": "Correio e pacotes (Etapa 2 de 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Falha na autenticação de Mail and Packages",
"fix_flow": {
"step": {
"confirm": {
"title": "Reautenticar o Servidor de E-mail",
"description": "A autenticação no seu servidor de e-mail IMAP falhou. Clique em enviar para iniciar o fluxo de reautenticação."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Использовать пользовательское изображение общее 'нет доставки'?",
"generate_grid": "Создать сетку изображений для моделей зрения LLM",
"allow_forwarded_emails": "Разрешить переадресованные электронные письма в дополнение к значениям по умолчанию службы (например, no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Включить заполнитель без изображения USPS в GIF?"
},
"description": "Завершите настройку, настроив следующие параметры в зависимости от структуры электронной почты и установки Home Assistant. \n\n Подробнее о параметрах [Интеграция с почтой и пакетами] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) см. В разделе [конфигурация, шаблоны и раздел автоматизации] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) на GitHub.",
"title": "Почта и пакеты (шаг 2 из 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Использовать пользовательское изображение общее 'нет доставки'?",
"generate_grid": "Создать сетку изображений для моделей зрения LLM",
"allow_forwarded_emails": "Разрешить переадресованные электронные письма в дополнение к значениям по умолчанию службы (например, no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Включить заполнитель без изображения USPS в GIF?"
},
"description": "Завершите настройку, настроив следующее в соответствии со структурой вашей электронной почты и установкой Home Assistant.\n\nДля получения подробной информации о вариантах [интеграции Почта и Пакеты](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) ознакомьтесь с [разделом конфигурации, шаблонов и автоматизации](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) на GitHub.\n\nЕсли вы используете переадресованные электронные письма Amazon, разделите каждый адрес запятой или введите (none), чтобы очистить эту настройку.",
"title": "Почта и пакеты (шаг 2 из 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Ошибка авторизации Mail and Packages",
"fix_flow": {
"step": {
"confirm": {
"title": "Повторная авторизация почтового сервера",
"description": "Не удалось авторизоваться на вашем почтовом сервере IMAP. Нажмите «Отправить», чтобы начать процесс повторной авторизации."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Použiť vlastný obrázok všeobecný 'bez dodávky'?",
"generate_grid": "Vytvoriť mriežku obrázkov pre modely videnia LLM",
"allow_forwarded_emails": "Povoliť preposielané e-maily okrem predvolenej hodnoty služby (napr. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Zahrnúť zástupný symbol USPS bez obrázka do GIF?"
},
"description": "Dokončite konfiguráciu prispôsobením nasledujúcich položiek na základe štruktúry e-mailu a inštalácie Home Assistant.\n\nPodrobnosti nájdete na [Pošta a balíky integrácia](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) možnosti si pozrite v časti [konfigurácia, šablóny a automatizácie](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHube.",
"title": "Pošta a balíky (krok 2 z 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Použiť vlastný obrázok všeobecný 'bez dodávky'?",
"generate_grid": "Vytvoriť mriežku obrázkov pre modely videnia LLM",
"allow_forwarded_emails": "Povoliť preposielané e-maily okrem predvolenej hodnoty služby (napr. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Zahrnúť zástupný symbol USPS bez obrázka do GIF?"
},
"description": "Dokončite konfiguráciu prispôsobením nasledujúceho na základe štruktúry vášho e-mailu a inštalácie Home Assistant.\n\nPre podrobnosti o možnostiach [integrácie Mail a Packages](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) si prečítajte [sekciu o konfigurácii, šablónach a automatizáciách](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHub.\n\nAk používate preposlané e-maily od Amazonu, oddelte každú adresu čiarkou alebo zadajte (none) na vymazanie tohto nastavenia.",
"title": "Pošta a balíky (krok 2 z 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Overenie Mail and Packages zlyhalo",
"fix_flow": {
"step": {
"confirm": {
"title": "Znovu overiť poštový server",
"description": "Overenie k vášmu poštovému serveru IMAP zlyhalo. Kliknutím na odoslať spustíte proces opätovného overenia."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Uporabite prilagojeno splošno sliko 'brez dostave'?",
"generate_grid": "Ustvari mrežo slik za vizualne modele LLM",
"allow_forwarded_emails": "Dovoli posredovane e-poštne sporočila poleg privzete vrednosti storitve (npr. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Ali naj se v GIF vključi nadomestni znak USPS brez slike?"
},
"description": "Končajte konfiguracijo s prilagoditvijo naslednjih na podlagi strukture e-pošte in namestitve Home Assistant. \n\n Za podrobnosti o možnostih [Integracija pošte in paketov] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) preglejte [konfiguracijo, predloge in oddelku za avtomatizacije] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHubu.",
"title": "Pošta in paketi (2. korak od 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Uporabite prilagojeno splošno sliko 'brez dostave'?",
"generate_grid": "Ustvari mrežo slik za vizualne modele LLM",
"allow_forwarded_emails": "Dovoli posredovane e-poštne sporočila poleg privzete vrednosti storitve (npr. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Ali naj se v GIF vključi nadomestni znak USPS brez slike?"
},
"description": "Konfiguracijo dokončajte z prilagajanjem naslednjega glede na strukturo vašega e-poštnega sporočila in namestitev Home Assistant.\n\nZa podrobnosti o možnostih [integracije Mail and Packages](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) si oglejte [razdelek o konfiguraciji, predlogah in avtomatizacijah](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) na GitHubu.\n\nČe uporabljate preusmerjena e-poštna sporočila Amazon, ločite vsak naslov z vejico ali vnesite (noben) za izbris te nastavitve.",
"title": "Pošta in paketi (2. korak od 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Preverjanje pristnosti za Mail and Packages ni uspelo",
"fix_flow": {
"step": {
"confirm": {
"title": "Ponovno preveri poštni strežnik",
"description": "Preverjanje pristnosti z vašim poštnim strežnikom IMAP ni uspelo. Kliknite Pošlji, če želite začeti potek ponovnega preverjanja pristnosti."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "Använd anpassad generisk 'ingen leverans' bild?",
"generate_grid": "Skapa bildrutnät för LLM-visionsmodeller",
"allow_forwarded_emails": "Tillåt vidarebefordrade e-postmeddelanden utöver en tjänsts standardvärde (t.ex. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Inkludera USPS platshållare utan bild i GIF?"
},
"description": "Avsluta konfigurationen genom att anpassa följande baserat på din e-poststruktur och installation av hemassistent. \n\n Mer information om alternativen [Mail and Packages] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) läser [konfiguration, mallar , och automatiseringsavsnitt] (https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) på GitHub.",
"title": "Mail och paket (steg 2 av 2)"
@@ -80,7 +81,8 @@
"generic_custom_img": "Använd anpassad generisk 'ingen leverans' bild?",
"generate_grid": "Skapa bildrutnät för LLM-visionsmodeller",
"allow_forwarded_emails": "Tillåt vidarebefordrade e-postmeddelanden utöver en tjänsts standardvärde (t.ex. no-reply@usps.com)",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "Inkludera USPS platshållare utan bild i GIF?"
},
"description": "Slutför konfigurationen genom att anpassa följande baserat på din e-poststruktur och Home Assistant-installation.\n\nFör detaljer om [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) alternativen granska [konfiguration, mallar och automatiseringssektionen](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) på GitHub.\n\nOm du använder vidarebefordrade e-postmeddelanden från Amazon, separera varje adress med ett kommatecken eller ange (ingen) för att rensa denna inställning.",
"title": "Mail och paket (steg 2 av 2)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Mail and Packages-autentisering misslyckades",
"fix_flow": {
"step": {
"confirm": {
"title": "Återautentisera e-postserver",
"description": "Autentisering mot din IMAP-e-postserver misslyckades. Klicka på skicka för att starta återautentiseringsflödet."
}
}
}
}
}
}
@@ -36,7 +36,8 @@
"generic_custom_img": "使用自訂的通用「無送貨」圖像?",
"generate_grid": "為LLM視覺模型創建圖像網格",
"allow_forwarded_emails": "允許轉發的電郵,除了服務的預設值(例如 no-reply@usps.com",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "在 GIF 中包含 USPS 無圖像預留位置?"
},
"description": "通過根據您的電子郵件結構和Home Assistant安裝自定義以下內容來完成配置。 \n\n有關[郵件和軟件包集成]https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)選項的詳細信息,請查看[配置,模板和自動化部分](GitHub上的https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)。",
"title": "郵件和包裹(第2步,共2步)"
@@ -80,7 +81,8 @@
"generic_custom_img": "使用自訂的通用「無送貨」圖像?",
"generate_grid": "為LLM視覺模型創建圖像網格",
"allow_forwarded_emails": "允許轉發的電郵,除了服務的預設值(例如 no-reply@usps.com",
"custom_days": "Days back to check for package emails (minimum 1, default 3)"
"custom_days": "Days back to check for package emails (minimum 1, default 3)",
"usps_placeholder": "在 GIF 中包含 USPS 無圖像預留位置?"
},
"description": "根據您的電郵結構和Home Assistant安裝來完成配置。\n\n有關[郵件和包裹整合](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)選項的詳情,請查閱GitHub上的[配置、模板和自動化部分](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration)。\n\n如果使用Amazon轉發的電郵,請用逗號分隔每個地址,或輸入(none)以清除此設定。",
"title": "郵件和包裹(第2步,共2步)"
@@ -199,5 +201,18 @@
"oauth2_google": "OAuth2 - Google (Gmail)"
}
}
},
"issues": {
"auth_failed": {
"title": "Mail and Packages 認證失敗",
"fix_flow": {
"step": {
"confirm": {
"title": "重新認證郵件伺服器",
"description": "認證 IMAP 郵件伺服器失敗。請按提交以啟動重新認證流程。"
}
}
}
}
}
}
@@ -43,7 +43,12 @@ _MAX_IMAGE_SIZE = 10 * 1024 * 1024 # 10 MB
DOMAIN_LANG_MAP = {
"amazon.de": ["versandbestaetigung", "Geliefert:", "Zugestellt:"],
"amazon.it": ["conferma-spedizione", "Consegna effettuata:", "Arriverà"],
"amazon.it": [
"conferma-spedizione",
"Consegna effettuata:",
"Arriverà",
"Spedito:",
],
"amazon.nl": [
"update-bestelling",
"verzending-volgen",
@@ -374,7 +374,7 @@ def _get_courier_info(
),
]
base_path = f"{hass.config.path()}/{default_image_path(hass, config)}"
base_path = hass.config.path(default_image_path(hass, config))
for (
active,
@@ -5,6 +5,7 @@ import binascii
import logging
import re
import unicodedata
from urllib.parse import quote, unquote
import aioimaplib
from aioimaplib import (
@@ -115,6 +116,30 @@ def quote_folder(folder: str) -> str:
return folder if _is_imap_atom(folder) else f'"{folder}"'
def encode_folder_ref(folder: str) -> str:
"""Percent-encode a folder name for use in a composite ``folder/uid`` ID.
Multi-folder searches tag each UID with its source folder as
``folder/uid``. Those composite IDs are space-joined and re-split on
whitespace at several call sites, and split on ``/`` to recover the
folder — so the folder component must contain neither whitespace nor
``/``. A folder named ``# - Projects`` would otherwise shatter into
``#``, ``-``, ``Projects/55`` when the joined ID list is ``.split()``.
``quote(..., safe="")`` escapes both (and ``%`` itself, keeping the
round-trip lossless for any folder name).
"""
return quote(folder, safe="")
def decode_folder_ref(folder: str) -> str:
"""Decode the percent-encoded folder component of a composite ID.
Takes the already-split folder component (everything before the final
``/`` of a ``folder/uid`` ID), not the full composite ID.
"""
return unquote(folder)
class InvalidAuth(HomeAssistantError):
"""Raise exception for invalid credentials."""
@@ -382,7 +407,7 @@ def _parse_esearch_line(line_bytes: bytes) -> list[bytes]:
pass
else:
uids.append(part)
return [f"{mailbox}/{uid}".encode() for uid in uids]
return [f"{encode_folder_ref(mailbox)}/{uid}".encode() for uid in uids]
async def _execute_single_search(account: IMAP4_SSL, search_query: str) -> list[bytes]: # noqa: C901
@@ -446,7 +471,8 @@ async def _execute_single_search(account: IMAP4_SSL, search_query: str) -> list[
if res.result == "OK" and res.lines:
parsed = parse_search_response(res.lines)
all_uids.extend(
f"{folder}/{uid.decode()}".encode() for uid in parsed
f"{encode_folder_ref(folder)}/{uid.decode()}".encode()
for uid in parsed
)
except TimeoutError:
raise
@@ -570,7 +596,7 @@ async def email_fetch(account: IMAP4_SSL, num, parts: str = "(RFC822)") -> tuple
num_str = num.decode() if isinstance(num, bytes) else str(num)
if "/" in num_str:
folder, num_str = num_str.rsplit("/", 1)
await selectfolder(account, folder)
await selectfolder(account, decode_folder_ref(folder))
try:
res = await account.uid("FETCH", num_str, parts)
except TimeoutError:
@@ -597,7 +623,7 @@ async def email_fetch_headers(account: IMAP4_SSL, num) -> tuple:
num_str = num.decode() if isinstance(num, bytes) else str(num)
if "/" in num_str:
folder, num_str = num_str.rsplit("/", 1)
await selectfolder(account, folder)
await selectfolder(account, decode_folder_ref(folder))
try:
res = await account.uid("FETCH", num_str, "(BODY[HEADER.FIELDS (SUBJECT)])")
except TimeoutError:
@@ -627,7 +653,7 @@ async def email_fetch_text(account: IMAP4_SSL, num, parts: str = "(BODY[1])") ->
num_str = num.decode() if isinstance(num, bytes) else str(num)
if "/" in num_str:
folder, num_str = num_str.rsplit("/", 1)
await selectfolder(account, folder)
await selectfolder(account, decode_folder_ref(folder))
try:
res = await account.uid("FETCH", num_str, parts)
except TimeoutError:
@@ -688,6 +714,7 @@ async def email_fetch_batch( # noqa: C901
num_str = num.decode() if isinstance(num, bytes) else str(num)
if "/" in num_str:
folder, actual_num = num_str.rsplit("/", 1)
folder = decode_folder_ref(folder)
else:
folder, actual_num = None, num_str
folder_to_nums.setdefault(folder, []).append(actual_num)
@@ -114,8 +114,21 @@ def _find_tracking_in_body(
return None
def save_image_data_to_disk(shipper_name: str, path: str, image_data: bytes) -> bool:
def save_image_data_to_disk(
shipper_name: str, path: str, image_data: bytes | None
) -> bool:
"""Write image bytes to disk and verify."""
if not image_data:
# Extraction can hand us zero bytes (e.g. a bare/empty base64 data URI
# in the email HTML). Writing that produces a 0-byte "photo" the
# camera then serves as a broken image — report failure instead so
# the caller falls through to the next extraction pass.
_LOGGER.debug(
"%s - No image data extracted; not writing %s",
shipper_name,
path,
)
return False
try:
# Ensure directory exists
directory = Path(path).parent
@@ -240,8 +253,11 @@ def _extract_from_html(
else str(payload)
)
# Base64 check
if matches := re.findall(base64_pattern, content):
# Base64 check. Skip empty matches: a bare "data:image/...;base64,"
# URI (seen in real FedEx delivered emails) matches zero characters,
# and taking it would discard a real photo later in the same part.
matches = [m for m in re.findall(base64_pattern, content) if m]
if matches:
try:
base64_data = matches[0].replace(" ", "").replace("=3D", "=")
return save_image_data_to_disk(