Skip to content

Email() port/ssl kwargs silently ignored when auto-discovery is used #69

Closed

Description

@FernandoCelmer

Description

Email.__init__ accepts port and ssl keyword arguments, but the auto-discovery branches in _resolve (EmailFactories.from_env / EmailFactories.from_address) build a fresh Credentials instance using values returned by resolve_imap_host, never consulting the caller-supplied port/ssl. The kwargs become no-ops without any warning.

Location

  • email_profile/email.py lines ~40-101 (__init__, _resolve)
  • email_profile/core/credentials.py line ~32 (EmailFactories.from_address)

Current Behavior

def __init__(self, server=None, user=None, password=None, port=993, ssl=True, storage=None):
    connection = self._resolve(server, user, password, port, ssl)
    ...

@staticmethod
def _resolve(server, user, password, port, ssl) -> Credentials:
    if server is None and user is not None and "@" in user and password:
        return EmailFactories.from_address(user, password)   # port/ssl dropped
    ...
Email("u@gmail.com", "pw", port=2143, ssl=False)
# resolves to Credentials(server="imap.gmail.com", port=993, ssl=True)

The caller's port=2143, ssl=False are discarded.

Expected Behavior

Caller-supplied port and ssl should override the values returned by auto-discovery. Or, if the design is intentional, raise a clear TypeError when both are provided.

Suggested Fix

Forward overrides through the factory:

@classmethod
def from_address(cls, address, password, *, port=None, ssl=None) -> Credentials:
    host = resolve_imap_host(address)
    return Credentials(
        server=host.host,
        user=address,
        password=password,
        port=port if port is not None else host.port,
        ssl=ssl if ssl is not None else host.ssl,
    )
# email.py
def _resolve(server, user, password, port, ssl):
    port_override = port if port != 993 else None
    ssl_override  = ssl if ssl is not True else None
    ...
    return EmailFactories.from_address(
        user, password, port=port_override, ssl=ssl_override,
    )

(Use sentinel objects rather than default-value comparison if you want to distinguish "user passed the default" from "user did not pass anything"; port / ssl should default to None in __init__.)

Impact

Users connecting to providers with non-standard ports (Proton Bridge, corporate IMAP gateways, dev sandboxes) cannot override the discovered values via the documented kwargs. They must drop down to constructing Credentials manually, defeating the high-level API.

Priority

High

Activity

  1. added
    bugSomething isn't working
    highHigh priority — incorrect behavior, performance, API breakage
    on May 17, 2026
  2. added a commit that references this issue on May 17, 2026
  3. FernandoCelmer commented on May 17, 2026

    @FernandoCelmer
    MemberAuthor

    Fixed in #79 (merged to develop).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghighHigh priority — incorrect behavior, performance, API breakage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions