Gmail IMAP connector — reads email via IMAP with app password.
Simpler alternative to the OAuth-based Gmail connector.
Uses Python's built-in imaplib + email modules (no dependencies).
Setup: generate an app password at https://myaccount.google.com/apppasswords
Classes
GmailIMAPConnector
GmailIMAPConnector(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: BaseConnector
Gmail connector using IMAP + app password.
No OAuth needed — just an email address and app password.
Source code in src/openjarvis/connectors/gmail_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:
self._email = email_address
self._password = app_password
self._credentials_path = credentials_path or _DEFAULT_CREDENTIALS_PATH
self._imap_host = imap_host or self._default_imap_host
self._imap_port = imap_port
self._imap_security = imap_security
# None means "use the persisted validation marker". Direct credentials
# are not considered connected until a real LOGIN + SELECT succeeds.
self._credentials_validated: bool | None = None
# ``None`` means "no cap" — the full inbox is indexed. A positive
# value is still honored for tests that want a bounded scan.
self._max_messages = max_messages
self._items_synced = 0
self._items_total = 0
|
Functions
connect_with_credentials
connect_with_credentials(email_address: str, app_password: str, *, imap_host: str = '', imap_port: int | None = None, imap_security: str = '') -> None
Validate LOGIN + INBOX access, then persist the connection.
Source code in src/openjarvis/connectors/gmail_imap.py
| def connect_with_credentials(
self,
email_address: str,
app_password: str,
*,
imap_host: str = "",
imap_port: int | None = None,
imap_security: str = "",
) -> None:
"""Validate LOGIN + INBOX access, then persist the connection."""
email_address = email_address.strip()
app_password = app_password.strip()
if not email_address or not app_password:
raise ValueError("Email address and app password are required")
host = (imap_host or self._host_for_email(email_address)).strip()
if not host:
raise ValueError("An IMAP host is required")
security = _normalize_imap_security(imap_security)
port = _normalize_imap_port(imap_port, security)
imap = self._open_authenticated_imap(
email_address,
app_password,
host,
port,
security,
)
self._close_imap(imap)
save_tokens(
self._credentials_path,
{
"email": email_address,
"password": app_password,
"imap_host": host,
"imap_port": port,
"imap_security": security,
"validated": True,
},
)
self._email = email_address
self._password = app_password
self._imap_host = host
self._imap_port = port
self._imap_security = security
self._credentials_validated = True
|
Functions