Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Unreleased
----------
* UAS multi-credential update
* Added `specific_time_availability` field to `AvailabilityParticipant` for overriding open hours on specific dates
* Added `smtp_required` option to hosted authentication config to require users to enter SMTP settings during IMAP authentication

v6.14.2
----------
Expand Down
3 changes: 3 additions & 0 deletions nylas/models/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class URLForAuthenticationConfig(TypedDict):
state: Optional state to be returned after authentication
login_hint: Prefill the login name (usually email) during authorization flow.
If a Grant for the provided email already exists, a Grant's re-auth will automatically be initiated.
smtp_required: If True, adds options=smtp_required so users must enter SMTP settings during
authentication. Relevant for IMAP; avoids grant errors when sending email later.
"""

client_id: str
Expand All @@ -48,6 +50,7 @@ class URLForAuthenticationConfig(TypedDict):
state: NotRequired[str]
login_hint: NotRequired[str]
credential_id: NotRequired[str]
smtp_required: NotRequired[bool]


class URLForAdminConsentConfig(URLForAuthenticationConfig):
Expand Down
3 changes: 3 additions & 0 deletions nylas/resources/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def _build_query(config: dict) -> dict:
if "scope" in config:
config["scope"] = " ".join(config["scope"])

if config.pop("smtp_required", None):
config["options"] = "smtp_required"

return config


Expand Down
36 changes: 36 additions & 0 deletions tests/resources/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,30 @@ def test_build_query(self):
"scope": "email calendar",
}

def test_build_query_with_smtp_required_true(self):
config = {
"foo": "bar",
"scope": ["email"],
"smtp_required": True,
}
result = _build_query(config)
assert result["options"] == "smtp_required"
assert "smtp_required" not in result # must not leak into URL params

def test_build_query_smtp_required_false_omits_options(self):
config = {
"foo": "bar",
"scope": ["email"],
"smtp_required": False,
}
result = _build_query(config)
assert "options" not in result

def test_build_query_smtp_required_omitted_omits_options(self):
config = {"foo": "bar", "scope": ["email"]}
result = _build_query(config)
assert "options" not in result

def test_build_query_with_pkce(self):
config = {
"foo": "bar",
Expand All @@ -52,6 +76,18 @@ def test_build_query_with_pkce(self):
"code_challenge_method": "s256",
}

def test_build_query_with_pkce_and_smtp_required(self):
config = {
"foo": "bar",
"scope": ["email"],
"smtp_required": True,
}
result = _build_query_with_pkce(config, "secret-hash-123")
assert result["options"] == "smtp_required"
assert "smtp_required" not in result # must not leak into URL params
assert result["code_challenge"] == "secret-hash-123"
assert result["code_challenge_method"] == "s256"

def test_build_query_with_admin_consent(self):
config = {
"foo": "bar",
Expand Down