"""Hide my email service.""" from typing import Any, Generator, Optional from requests import Response from pyicloud.services.base import BaseService from pyicloud.session import PyiCloudSession class HideMyEmailService(BaseService): """ The 'Hide My Email' iCloud service connects to iCloud and manages email aliases. This service allows users to: - Generate new email aliases - Reserve specific aliases - List all existing aliases - Get alias details by ID - Update alias metadata (label, note) - Delete aliases - Deactivate aliases - Reactivate aliases """ def __init__( self, service_root: str, session: PyiCloudSession, params: dict[str, Any] ) -> None: super().__init__(service_root, session, params) # Define v1 endpoints self._v1_endpoint: str = f"{service_root}/v1/hme" self._generate_endpoint: str = f"{self._v1_endpoint}/generate" self._reserve_endpoint: str = f"{self._v1_endpoint}/reserve" self._update_metadata_endpoint: str = f"{self._v1_endpoint}/updateMetaData" self._delete_endpoint: str = f"{self._v1_endpoint}/delete" self._deactivate_endpoint: str = f"{self._v1_endpoint}/deactivate" self._reactivate_endpoint: str = f"{self._v1_endpoint}/reactivate" # Define v2 endpoints self._v2_endpoint: str = f"{service_root}/v2/hme" self._list_endpoint: str = f"{self._v2_endpoint}/list" self._get_endpoint: str = f"{self._v2_endpoint}/get" def generate(self) -> Optional[str]: """ Generate a new email alias. Returns: The generated email address string or None if generation failed. """ req: Response = self.session.post(self._generate_endpoint, params=self.params) response: dict[str, dict[str, str]] = req.json() result: Optional[dict[str, str]] = response.get("result") if result: return result.get("hme") return None def reserve(self, email: str, label: str, note="Generated") -> dict[str, Any]: """ Reserve an alias for emails. Args: email: The email alias to reserve. label: A label for the email alias. note: An optional note for the email alias. Returns: The API's result containing details about the reserved alias. """ req: Response = self.session.post( self._reserve_endpoint, params=self.params, json={ "hme": email, "label": label, "note": note, }, ) response = req.json() return response.get("result", {}) def __len__(self) -> int: """ Get the number of emails """ req: Response = self.session.get(self._list_endpoint, params=self.params) response: dict[str, dict[str, str]] = req.json() result: Optional[dict[str, str]] = response.get("result") if result: return len(result.get("hmeEmails", [])) return 0 def __iter__(self) -> Generator[Any, Any, None]: """ Iterate over the list of emails """ req: Response = self.session.get(self._list_endpoint, params=self.params) response: dict[str, dict[str, str]] = req.json() result: Optional[dict[str, str]] = response.get("result") if result: yield from result.get("hmeEmails", []) def __getitem__(self, anonymous_id: str) -> dict[str, Any]: """ Get alias email details by anonymous_id. Args: anonymous_id: The unique identifier for the alias. Returns: A dictionary containing details about the alias. """ req: Response = self.session.post( self._get_endpoint, params=self.params, json={"anonymousId": anonymous_id}, ) response = req.json() return response.get("result", {}) def update_metadata( self, anonymous_id: str, label: str, note: Optional[str] = None ) -> dict[str, Any]: """ Update metadata for an alias email. Args: anonymous_id: The unique identifier for the alias. label: The new label for the alias. note: The new note for the alias (optional). Returns: A dictionary containing the API response. """ payload: dict[str, str] = { "anonymousId": anonymous_id, "label": label, } if note is not None: payload["note"] = note req: Response = self.session.post( self._update_metadata_endpoint, params=self.params, json=payload, ) response = req.json() return response.get("result", {}) def delete(self, anonymous_id: str) -> dict[str, Any]: """ Delete an alias email. Args: anonymous_id: The unique identifier for the alias to delete. Returns: A dictionary containing the API response. """ req: Response = self.session.post( self._delete_endpoint, params=self.params, json={"anonymousId": anonymous_id}, ) response = req.json() return response.get("result", {}) def deactivate(self, anonymous_id: str) -> dict[str, Any]: """ Deactivate an alias email. Deactivating an alias means emails sent to it will no longer be forwarded, but the alias remains in your list and can be reactivated later. Args: anonymous_id: The unique identifier for the alias to deactivate. Returns: A dictionary containing the API response. """ req: Response = self.session.post( self._deactivate_endpoint, params=self.params, json={"anonymousId": anonymous_id}, ) response = req.json() return response.get("result", {}) def reactivate(self, anonymous_id: str) -> dict[str, Any]: """ Reactivate a previously deactivated alias email. Reactivating an alias means emails sent to it will be forwarded again to your primary inbox. Args: anonymous_id: The unique identifier for the alias to reactivate. Returns: A dictionary containing the API response. """ req: Response = self.session.post( self._reactivate_endpoint, params=self.params, json={"anonymousId": anonymous_id}, ) response = req.json() return response.get("result", {})