Outlook / Gmail OAuth sending
For Outlook (Microsoft 365) and Gmail mailboxes, MailPort can send via OAuth2 — no app passwords or IMAP tokens needed in the mailbox itself. After authorization, mail is delivered over SMTP XOAUTH2.
Flow
The callback URL is a fixed value
https://<your-domain>/api/oauth/callbackwith no sender information in it. So you can fill it into Azure/Google before creating any sender — no circular dependency between "you need the callback URL to create the app" and "you need the sender to see the callback URL". Which sender is being authorized is determined at callback time by the signedstate.
When sending, MailPort exchanges the refresh token for an access token and logs in via SMTP XOAUTH2:
Outlook uses smtp.office365.com:587, Gmail uses smtp.gmail.com.
1. Register an OAuth application
Outlook (Microsoft Entra ID / Azure)
- Open Azure portal → App registrations and click "New registration".
- Pick any name; for "Supported account types" choose "Accounts in any organizational directory and personal Microsoft accounts".
- Under "Redirect URI" select Web and enter the fixed callback URL
https://xxx.vercel.app/api/oauth/callback(replace the domain with where you deployed MailPort). - After registering, the Application (client) ID on the Overview page is your Client ID.
- Under "Certificates & secrets → New client secret", create a secret and copy its Value — it is only shown once.
Gmail (Google Cloud)
- Open the Google Cloud Console and create a project.
- Go to "APIs & Services → Credentials → Create credentials → OAuth client ID", application type Web application.
- Fill in the two addresses below, then click "Create".
- Note the Client ID and Client secret.
- If prompted to configure the "OAuth consent screen" first, fill in the basic details (in test mode, add your own email as a test user).
Gmail: the two addresses to fill in Google Cloud
In the Google Cloud "OAuth client ID (Web application)" form you fill in two addresses, both based on MailPort's own domain:
- The site address is your MailPort deployment domain, with no path and no trailing
/. - The callback address is fixed: site address +
/api/oauth/callback. It is the same for every sender, so you can enter it before creating any sender. - The callback address must match Google exactly, or Google rejects the authorization with
redirect_uri_mismatch.
The callback address must be reachable from the public internet, so
localhostonly works for debugging the flow — deploy to Vercel or similar for real use.
2. Configure in MailPort
- Create a sender and choose Outlook OAuth or Gmail OAuth as the delivery method.
- Fill in:
- Account email: the mailbox to authorize (e.g.
you@outlook.com), used for the OAuth login. - Client ID: from the previous step.
- Client Secret: from the previous step (cannot be viewed again after saving; leave blank to keep unchanged).
- Account email: the mailbox to authorize (e.g.
- Click Authorize — the configuration is saved first, then you are redirected to the provider's consent page.
- Sign in with the mailbox and consent.
- On success you are redirected back to the sender page with a success message.
The authorization status (authorized + date) is shown under the "Settings" tab. From then on, call the endpoint like any other sender:
Re-authorizing
Re-authorize (the "Re-authorize" button — no need to re-enter the configuration) when:
- the refresh token expired or was revoked
- you switched to a different OAuth application (different Client ID/Secret)
- you want to authorize a different mailbox
Outlook refresh tokens are typically long-lived; Gmail tokens lapse after about 7 days of inactivity — just re-authorize when that happens.
Requested scopes
MailPort requests only the minimum needed to send:
offline_access(Outlook) /access_type=offline(Gmail) is what yields a refresh token, required for persistent sending.- Gmail always sends
prompt=consentso a fresh refresh token is issued each time.
Security notes
- Client secrets and refresh tokens are encrypted at rest with AES-256-GCM and never echoed back to the frontend.
- The
stateparameter in the callback is signed withMAILPORT_SECRET(valid for 10 minutes): it prevents CSRF and identifies which sender the fixed callback belongs to. - The callback endpoint is public, but its only capability is writing the authorization token — it never exposes existing credentials.