How to Fix Entra API 403 Error exchangelib

If your Python app suddenly throws this error: exchangelib.errors.MalformedResponseError: Unknown failure in response. Code: 403 the issue is usually not Entra itself. In most cases, Exchange Web Services rejects the request because the OAuth setup is wrong, the app lacks the correct Exchange permission, mailbox access is blocked, or EWS is disabled.

How to Fix Entra API 403 Error exchangelib
How to Fix Entra API 403 Error exchangelib

This guide explains what causes the error, how to check your Entra and Exchange setup, and how to fix it step by step.

What Causes Entra API 403 Error in exchangelib

A 403 error means Exchange Online received your request but refused access. That usually happens for one of these reasons:

  • Your app uses the wrong permission type
  • Your token matches the wrong auth flow
  • The mailbox is outside the app’s allowed Exchange scope
  • EWS is disabled for the tenant, mailbox, or app
  • Your code uses app-only access, but the app only has delegated permission

In exchangelib, Exchange sometimes returns a blank or incomplete error response. When that happens, the library shows:

MalformedResponseError: Unknown failure in response. Code: 403

instead of a more direct authorization message.

First Identify the Access Model

Before changing anything, confirm which auth model your app uses.

You are using delegated access if:

  • A real user signs in
  • The app works on behalf of that signed-in user
  • You use an interactive login flow

This model needs:

  • EWS.AccessAsUser.All

You are using app-only access if:

  • Your script runs in the background
  • You use client_id and client_secret
  • No user signs in during runtime
  • The service connects directly to mailboxes

This model needs:

  • full_access_as_app

Common Cause in exchangelib

This pattern usually means app-only access:

credentials = OAuth2Credentials(
    client_id=client_id,
    client_secret=client_secret,
    tenant_id=tenant_id
)

If you use only client_id, client_secret, and tenant_id, but the app registration only has delegated EWS permission, Exchange will usually return 403.

That mismatch is one of the most common reasons this error appears.

Fix 1: Add the Correct EWS Permission in Entra

Open your app registration in the Entra admin center and check API permissions.

If your app uses delegated access

Add:

  • Office 365 Exchange Online
  • Delegated permission
  • EWS.AccessAsUser.All

Then grant consent if your tenant requires it.

If your app uses app-only access

Add:

  • Office 365 Exchange Online
  • Application permission
  • full_access_as_app

Then grant admin consent.

Fix 2: Match the Token to the Access Type

Do not mix delegated permissions with app-only code.

If your code runs as a daemon or backend service, your token must come from an application flow and your app must have full_access_as_app. If your code runs with a signed-in user, use delegated login and EWS.AccessAsUser.All. Microsoft clearly separates these two EWS OAuth models.

A lot of 403 errors happen because developers register one model but code the other.other.

Fix 3: Check Exchange Mailbox Access Scope

Even if the Entra permission looks correct, Exchange Online can still block mailbox access.

In many tenants, Exchange limits which mailboxes an app can open. So the app may be valid, consent may be granted, and the token may still fail because the mailbox is outside the allowed scope.

Check that:

  • the service principal exists correctly in Exchange Online
  • the app has the required Exchange application role
  • the target mailbox is inside the allowed scope

If this part is missing, Exchange can return 403 even when everything in Entra looks fine.

Fix 4: Check Whether EWS Is Disabled

EWS access can be disabled at multiple levels:

  • organization level
  • mailbox level
  • application level

So if the app registration looks correct but the request still fails, verify that EWS is actually enabled where your app needs it.

Typical checks include Exchange settings like:

Set-OrganizationConfig -EwsEnabled:$false
Set-CASMailbox -Identity [email protected] -EwsEnabled:$false

If one of these restrictions is active, the request will fail no matter how clean the token is.

Fix 5: Verify the EWS Endpoint

For Exchange Online, the usual EWS endpoint is:

https://outlook.office365.com/EWS/Exchange.asmx

If your app points to the wrong endpoint, or if you combine an EWS request with the wrong token/resource flow, authentication can fail.

Fix 6: Stop Using Basic Auth

If your older script still uses username and password directly, update it now.

Basic authentication no longer works for EWS in Exchange Online. The working setup is:

  • register the app in Entra
  • use OAuth
  • assign the correct EWS permission
  • confirm Exchange-side mailbox access

Anything built on old basic auth logic will keep breaking.

Fix 7: Review Your exchangelib Access Type

If your code looks like this:

account = Account(
    primary_smtp_address=username,
    credentials=credentials,
    config=config,
    autodiscover=False,
    access_type=IMPERSONATION
)

make sure your Exchange configuration actually supports that access pattern.

A lot of older EWS examples rely on impersonation logic, but current Exchange Online setups often fail unless the app permission, mailbox scope, and Exchange-side access rules all line up correctly.

So if the code looks right but still throws 403, check the Exchange authorization side more carefully.

Quick Checklist to Fix Entra API 403 Issue

StepWhat to DoKey Details
1Identify the auth modelCheck if a user signs in or if it runs as a background service using client_secret. If no user signs in, treat it as app-only access.
2Check Entra API permissionsUse EWS.AccessAsUser.All for delegated access and full_access_as_app for app-only access.
3Grant consentEnsure user consent or admin consent is fully completed.
4Check Exchange mailbox accessConfirm the app is allowed to access the target mailbox.
5Verify EWS is enabledCheck organization-level, mailbox-level, and application-level EWS settings.
6Inspect 403 response headersLook for WWW-Authenticate, x-ms-diagnostics, and X-BackEndHttpStatus to identify the root cause.

Example Scenario

Let’s say your code looks like this:

credentials = OAuth2Credentials(
    client_id=client_id,
    client_secret=client_secret,
    tenant_id=tenant_id
)

config = Configuration(
    credentials=credentials,
    auth_type=OAUTH2,
    service_endpoint="https://outlook.office365.com/EWS/Exchange.asmx",
)

account = Account(
    primary_smtp_address=username,
    credentials=credentials,
    config=config,
    autodiscover=False,
    access_type=IMPERSONATION
)

If this app registration only has delegated permission, the setup is wrong.

This code behaves like a background service, so it usually needs:

  • Exchange Online application permission full_access_as_app
  • admin consent
  • valid mailbox scope in Exchange Online
  • EWS enabled for that mailbox and tenant

That is the first place to check before changing anything else.

EWS Deprecation 2026: What You Need to Know

EWS in Exchange Online is on a countdown. It is scheduled for deprecation and full disablement in October 2026.

So if you are fixing this in a production environment, treat it as both a repair and a warning sign. You can still fix the 403 now, but long-term planning should move toward Microsoft Graph wherever possible.

That does not change the immediate fix, but it does affect how much effort you should invest in older EWS-based workflows.

FAQs

Is this an Entra API problem?

Usually no. The 403 normally comes from Exchange Online EWS authorization, not from Entra being down.

Why does exchangelib show MalformedResponseError instead of a clean auth error?

Because Exchange can return a 403 with an empty or incomplete response body, and exchangelib turns that into an unknown failure.

Which permission do I need for a background script?

For background or daemon-style EWS access, use full_access_as_app.

Can EWS still be disabled even if the app is correct?

Yes. Exchange can block EWS at the organization, mailbox, or application level.

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

    Leave a Reply