Skip to content

imap

imap

Generic IMAP email connector for any provider.

Classes

IMAPConnector

IMAPConnector(email_address: str = '', app_password: str = '', credentials_path: str = '', *, imap_host: str = '', imap_port: int | None = None, imap_security: str = '', max_messages: Optional[int] = None)

Bases: GmailIMAPConnector

Generic IMAP connector for any email provider.

Source code in src/openjarvis/connectors/imap.py
def __init__(
    self,
    email_address: str = "",
    app_password: str = "",
    credentials_path: str = "",
    *,
    imap_host: str = "",
    imap_port: int | None = None,
    imap_security: str = "",
    max_messages: Optional[int] = None,
) -> None:
    super().__init__(
        email_address,
        app_password,
        credentials_path or _DEFAULT_CREDENTIALS_PATH,
        imap_host=imap_host,
        imap_port=imap_port,
        imap_security=imap_security,
        max_messages=max_messages,
    )
Functions
mcp_tools
mcp_tools() -> list

Do not expose Gmail-branded live tools for non-Gmail mailboxes.

Source code in src/openjarvis/connectors/imap.py
def mcp_tools(self) -> list:
    """Do not expose Gmail-branded live tools for non-Gmail mailboxes."""
    return []

Functions

validate_imap_endpoint

validate_imap_endpoint(host: str, port: int) -> tuple[str, tuple[str, ...]]

Resolve a public IMAP endpoint and return addresses safe to pin.

All resolved addresses must be globally routable. Returning the resolved addresses lets the socket layer pin one of the checked IPs, closing the DNS-rebinding gap between policy validation and connection establishment.

Source code in src/openjarvis/connectors/imap.py
def validate_imap_endpoint(host: str, port: int) -> tuple[str, tuple[str, ...]]:
    """Resolve a public IMAP endpoint and return addresses safe to pin.

    All resolved addresses must be globally routable. Returning the resolved
    addresses lets the socket layer pin one of the checked IPs, closing the
    DNS-rebinding gap between policy validation and connection establishment.
    """
    normalized = _normalize_hostname(host)
    lowered = normalized.lower()
    if (
        lowered in _BLOCKED_HOSTNAMES
        or lowered.endswith(".localhost")
        or lowered.endswith(".local")
        or lowered.endswith(".internal")
    ):
        raise ValueError("Private or local IMAP hosts are not allowed")

    try:
        resolved = socket.getaddrinfo(
            normalized,
            port,
            socket.AF_UNSPEC,
            socket.SOCK_STREAM,
        )
    except socket.gaierror as exc:
        raise ValueError(f"Unable to resolve IMAP host '{normalized}'") from exc

    addresses: list[str] = []
    for _, _, _, _, sockaddr in resolved:
        address = sockaddr[0]
        if not _is_public_address(address):
            raise ValueError("Private or non-public IMAP addresses are not allowed")
        if address not in addresses:
            addresses.append(address)
    if not addresses:
        raise ValueError(f"Unable to resolve IMAP host '{normalized}'")
    return normalized, tuple(addresses)

resolve_imap_host

resolve_imap_host(email_address: str) -> str

Resolve the IMAP host for an email address from its domain.

Source code in src/openjarvis/connectors/imap.py
def resolve_imap_host(email_address: str) -> str:
    """Resolve the IMAP host for an email address from its domain."""
    domain = email_address.rsplit("@", 1)[-1].lower() if "@" in email_address else ""
    if not domain:
        return ""
    return _PROVIDER_HOSTS.get(domain, f"imap.{domain}")