# Yahoo Mail API

- Tool: FlutterFlow
- Difficulty: Advanced
- Time required: 45 minutes
- Last updated: July 2026

## TL;DR

Connect FlutterFlow to Yahoo Mail API using OAuth 2.0: FlutterFlow opens the Yahoo consent screen via a Custom Action, captures the authorization code, and calls a Firebase Cloud Function to exchange it for an access token — since the OAuth client secret cannot live in a compiled Flutter app. Use the resulting Bearer token to read the signed-in user's mailbox. For sending email, route through SMTP in the same Cloud Function.

## Read Your Users' Yahoo Mailboxes from a FlutterFlow App with OAuth

Yahoo Mail is one of the oldest and most widely used personal email services, with hundreds of millions of active accounts. Integrating it into a FlutterFlow app enables use cases like reading inbox messages, filtering emails by sender, and displaying email summaries inside your app — useful for CRM-style tools, inbox aggregators, or apps where users want to surface their email data alongside other information.

The FlutterFlow-specific challenge is the OAuth 2.0 token exchange. Yahoo's authorization-code flow requires your app's client secret when trading the authorization code for an access token — and that secret cannot live in the compiled Flutter app. A Firebase Cloud Function handles this securely. Yahoo's API surface is also thinner than Gmail's: there is no clean REST send endpoint, so sending email realistically means SMTP inside a server-side function. Some API details (exact scope strings, endpoint paths) are subject to change — always verify in the Yahoo Developer portal.

For pure email sending (welcome messages, receipts, password resets), use Mailgun or SendGrid — those are domain-level bulk senders with simple API keys. Yahoo Mail is specifically for reading and acting on the signed-in user's personal mailbox. The developer application is free to register at developer.yahoo.com; access to the mailbox is scoped by the OAuth consent the user grants your app.

## Before you start

- A Yahoo Developer account and a Yahoo app registered at developer.yahoo.com with the correct OAuth redirect URI configured
- The Yahoo app's Client ID and Client Secret copied from the Yahoo Developer portal
- A Firebase project with Cloud Functions enabled on the Blaze pay-as-you-go plan (required for external network calls)
- A FlutterFlow project with Firebase Auth or Supabase for user management and Firestore for token storage
- Familiarity with deep links or URL scheme configuration in FlutterFlow for capturing the OAuth callback

## Step-by-step guide

### 1. Register a Yahoo Developer App and Configure OAuth

Go to developer.yahoo.com and sign in with your Yahoo account. Click 'Create App' and fill in the application details: app name, description, and the application type (select 'Web Application' for a Cloud Function callback or 'Native Application' for a deep-link flow). Under API Permissions, check 'Mail' and select the appropriate permission level — 'Read' (`mail-r`) to read messages, or 'Read/Write' (`mail-w`) to manage them. Yahoo's exact scope strings (`mail-r`, `mail-w`) should be verified in the current Yahoo Developer documentation as they can change. Set the Callback Domain / Redirect URI to the URL your Cloud Function will listen at for the authorization code — for example `https://us-central1-your-project.cloudfunctions.net/yahooOAuthCallback`. You can also use a deep link (e.g., `yourapp://yahoo-callback`) if you handle the callback in FlutterFlow itself, but the Cloud Function approach is cleaner for token security. Copy the Application (Client) ID and Client Secret from the app settings page and save them securely — you will add them to your Firebase Functions config, never to FlutterFlow.

**Expected result:** A Yahoo Developer app is registered with mail scopes, redirect URI pointing at your Cloud Function, and Client ID + Secret copied.

### 2. Build a Cloud Function for OAuth Code Exchange and Token Refresh

Your Firebase Cloud Function is the cornerstone of this integration — it handles the Yahoo authorization-code exchange, stores the resulting access and refresh tokens in Firestore per user, and refreshes the access token when it expires. Deploy this function and store your Yahoo Client ID and Client Secret in Firebase config: run `firebase functions:config:set yahoo.client_id="your-client-id" yahoo.client_secret="your-client-secret"` in your terminal. The function exposes two HTTP endpoints: one for the OAuth callback (code → tokens) and one for token refresh. Access tokens from Yahoo expire; verify the current TTL in Yahoo's documentation and implement refresh proactively. All tokens are stored in Firestore under a per-user document so FlutterFlow can read the current access token when it needs to make API calls. Note: because Yahoo's IMAP endpoints are more established than its REST API for some operations, sending email from this same Cloud Function via SMTP (using the `nodemailer` package with `imap.mail.yahoo.com` or your verified SMTP host) is the recommended path for email sending.

```
// functions/index.js — Yahoo OAuth handler
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const fetch = require('node-fetch');

admin.initializeApp();
const db = admin.firestore();

const YAHOO_CLIENT_ID = functions.config().yahoo.client_id;
const YAHOO_CLIENT_SECRET = functions.config().yahoo.client_secret;
const REDIRECT_URI = functions.config().yahoo.redirect_uri; // set this too

// Step 1: Callback — exchange code for tokens
exports.yahooOAuthCallback = functions.https.onRequest(async (req, res) => {
  const { code, state } = req.query; // state = Firebase UID
  if (!code) return res.status(400).send('Missing code');

  const params = new URLSearchParams({
    grant_type: 'authorization_code',
    code,
    redirect_uri: REDIRECT_URI,
    client_id: YAHOO_CLIENT_ID,
    client_secret: YAHOO_CLIENT_SECRET,
  });

  try {
    const tokenRes = await fetch('https://api.login.yahoo.com/oauth2/get_token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: params,
    });
    const tokens = await tokenRes.json();
    if (!tokens.access_token) {
      return res.status(400).json({ error: 'Token exchange failed', details: tokens });
    }

    // Store tokens in Firestore per user
    await db.collection('yahoo_tokens').doc(state).set({
      accessToken: tokens.access_token,
      refreshToken: tokens.refresh_token,
      expiresAt: Date.now() + (tokens.expires_in * 1000),
      updatedAt: admin.firestore.FieldValue.serverTimestamp(),
    });

    res.status(200).send('<html><body>Connected! You may close this window.</body></html>');
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Step 2: Get a valid access token (refresh if needed)
exports.getYahooToken = functions.https.onRequest(async (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
  if (req.method === 'OPTIONS') { res.status(204).send(''); return; }
  const { uid } = req.body;
  if (!uid) return res.status(400).json({ error: 'Missing uid' });

  const doc = await db.collection('yahoo_tokens').doc(uid).get();
  if (!doc.exists) return res.status(404).json({ error: 'No Yahoo token for user' });

  let { accessToken, refreshToken, expiresAt } = doc.data();

  // Refresh if within 5 minutes of expiry
  if (Date.now() > expiresAt - 300000) {
    const params = new URLSearchParams({
      grant_type: 'refresh_token',
      refresh_token: refreshToken,
      client_id: YAHOO_CLIENT_ID,
      client_secret: YAHOO_CLIENT_SECRET,
    });
    const refreshRes = await fetch('https://api.login.yahoo.com/oauth2/get_token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: params,
    });
    const newTokens = await refreshRes.json();
    accessToken = newTokens.access_token;
    await db.collection('yahoo_tokens').doc(uid).update({
      accessToken,
      expiresAt: Date.now() + (newTokens.expires_in * 1000),
    });
  }

  res.status(200).json({ accessToken });
});
```

**Expected result:** The Cloud Function is deployed. The `yahooOAuthCallback` endpoint handles the code exchange and writes tokens to Firestore. The `getYahooToken` endpoint returns a fresh access token to FlutterFlow API Calls.

### 3. Launch the Yahoo OAuth Consent Flow from FlutterFlow

In FlutterFlow, you need a Custom Action to launch the Yahoo authorization URL in the device browser and handle the redirect back to your app. Click 'Custom Code' in the left navigation, then '+ Add' → 'Action'. Name it 'launchYahooOAuth'. In the Dependencies field, add `url_launcher: ^6.0.0` to launch the Yahoo consent URL in the device browser. The action builds the authorization URL with your Yahoo Client ID, the `mail-r` scope (verify current scope string in Yahoo docs), your redirect URI (the Cloud Function callback URL), and the current user's Firebase UID as the `state` parameter. Passing the state lets the Cloud Function know which Firestore document to write tokens to. After the user completes the Yahoo consent screen in the browser, the browser is redirected to your Cloud Function callback URL, which exchanges the code and stores the tokens. If you want an in-app browser experience instead, add the `flutter_web_auth` or `in_app_web_view` pub.dev package and capture the callback redirect directly — but this adds complexity. Test with a tap action on a 'Connect Yahoo Mail' button that calls this Custom Action.

```
// custom_action.dart — Launch Yahoo OAuth (url_launcher)
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

Future<void> launchYahooOAuth(
  String clientId,
  String redirectUri,
  String userUid,
) async {
  const String scope = 'mail-r'; // Verify current scope string with Yahoo docs
  final String state = Uri.encodeComponent(userUid);

  final Uri authUri = Uri.parse(
    'https://api.login.yahoo.com/oauth2/request_auth'
    '?client_id=$clientId'
    '&redirect_uri=${Uri.encodeComponent(redirectUri)}'
    '&response_type=code'
    '&scope=$scope'
    '&state=$state',
  );

  if (await canLaunchUrl(authUri)) {
    await launchUrl(authUri, mode: LaunchMode.externalApplication);
  } else {
    debugPrint('Could not launch Yahoo OAuth URL');
  }
}
```

**Expected result:** Tapping the 'Connect Yahoo Mail' button opens the Yahoo consent page in the device browser. After authorizing, the browser redirects to the Cloud Function, and tokens appear in Firestore under the user's UID document.

### 4. Add FlutterFlow API Calls to Read Yahoo Mailbox Data

Once the OAuth flow completes and tokens are stored in Firestore, your FlutterFlow app can read Yahoo mailbox data. The workflow is: (1) call the `getYahooToken` Cloud Function to get a fresh access token, (2) use that token in a Bearer-authenticated API Call to the Yahoo Mail endpoint to fetch message data. In FlutterFlow, click 'API Calls' in the left nav → '+ Add' → 'Create API Group'. Name it 'YahooMail'. Set the base URL to `https://mail.yahooapis.com/ws/mail/v1.1/jsonrpc` (verify this endpoint in current Yahoo docs — the Yahoo Mail REST API surface has changed over time). Add a header variable `accessToken` (String) to be used as `Authorization: Bearer {{ accessToken }}`. Add an API Call named 'listMessages' with the appropriate method and parameters. Before this call, chain a 'Backend/API Call' action to the `getYahooToken` function to fetch a fresh token, store the result in a page state variable, then use that variable in the YahooMail API Call's `accessToken` header. Because Yahoo's mail API may route certain operations through IMAP rather than REST, complex inbox operations (search, read full message body) may work more reliably through a Cloud Function that handles the IMAP connection and returns simplified JSON to FlutterFlow.

```
// API Group config reference
// Group: YahooMail
// Base URL: https://mail.yahooapis.com/ws/mail/v1.1/jsonrpc
//   (verify current endpoint in Yahoo Developer docs)
// Headers:
//   Authorization: Bearer {{ accessToken }}
//   Content-Type: application/json
//
// Before each YahooMail API Call, chain:
// 1. Call getYahooToken Cloud Function → store token in page state
// 2. Pass stored token as {{ accessToken }} variable
```

**Expected result:** The FlutterFlow API Call successfully retrieves mailbox data using the Bearer token. A ListView bound to the parsed JSON Path shows inbox messages with sender, subject, and date.

### 5. Handle Token Refresh and Revocation in the App

Yahoo access tokens expire — verify the exact TTL in Yahoo's documentation (it has been 3600 seconds historically but can change). Your Cloud Function's `getYahooToken` endpoint already handles refresh, but your FlutterFlow app needs to handle the case where the user's tokens are expired or revoked (e.g., they changed their Yahoo password or revoked your app's access in Yahoo's connected apps settings). In your FlutterFlow app, read the token expiry from the Firestore `yahoo_tokens` document and show a 'Reconnect Yahoo Mail' prompt if the token is missing or older than the TTL. When the user taps reconnect, re-run the `launchYahooOAuth` Custom Action. For the disconnect flow, add a 'Disconnect Yahoo Mail' button that calls a Cloud Function to delete the Firestore token document and optionally revokes the Yahoo token via Yahoo's revocation endpoint. Test this by manually deleting the Firestore document and confirming the app prompts reconnection. If you'd rather skip building and maintaining the full token lifecycle yourself, RapidDev's team builds FlutterFlow integrations like this every week — free scoping call at rapidevelopers.com/contact.

**Expected result:** The app detects expired or missing tokens and prompts the user to reconnect. The reconnect flow completes the OAuth process and updates the Firestore token document.

## Best practices

- Never store the Yahoo OAuth client secret in FlutterFlow — the token exchange must happen in a Firebase Cloud Function where the secret stays server-side.
- Always verify current Yahoo OAuth scope strings and API endpoint paths in the Yahoo Developer documentation before coding — Yahoo's API surface changes more frequently than Google or Microsoft.
- Store access and refresh tokens in Firestore per user, not in FlutterFlow page state — page state is lost on navigation and tokens need to persist across sessions.
- Implement proactive token refresh (check expiry before making API calls) rather than reactive refresh (catch 401 and retry) — it gives users a smoother experience.
- For sending email, use a server-side SMTP connection (via Cloud Function + nodemailer) rather than looking for a Yahoo REST send endpoint — the REST path for sending is unreliable.
- Scope requests to the minimum required: request `mail-r` only unless write operations are needed — Yahoo's OAuth consent screen shows the scopes to the user and narrower permissions build trust.
- Add a 'Disconnect Yahoo Mail' flow in the app that deletes the Firestore token document — this respects user privacy and is required by most app store data deletion policies.
- Set realistic user expectations: Yahoo Mail integration is for personal mailbox access, not for bulk sending — if your use case is transactional email, direct users to use Mailgun or SendGrid instead.

## Use cases

### Inbox aggregator app that shows Yahoo Mail alongside other inboxes

A FlutterFlow productivity app connects to multiple email providers including Yahoo Mail. After the user completes the OAuth consent flow, the app displays their most recent Yahoo inbox messages in a unified feed alongside Gmail and Outlook messages fetched via their respective APIs. All email data is read from the user's own mailboxes with explicit consent.

Prompt example:

```
After the user signs into Yahoo Mail with OAuth, show their 10 most recent inbox messages with sender, subject, and date in a scrollable list.
```

### CRM app that surfaces incoming emails from leads

A FlutterFlow CRM app lets sales reps authorize Yahoo Mail access so the app can surface emails from tracked contacts. When a lead sends an email, it appears in the CRM timeline alongside call logs and deal notes — giving reps a full picture without switching between apps.

Prompt example:

```
Read the user's Yahoo inbox, filter emails from a specific sender address, and display them in a CRM timeline card inside the FlutterFlow app.
```

### Notification app that watches for important email patterns

A FlutterFlow app periodically reads the user's Yahoo inbox via the Cloud Function, checks for emails matching certain subject patterns (e.g., bank alerts, shipping notifications), and pushes a local notification when matches are found. All email data stays within the app's Firestore per-user collection.

Prompt example:

```
Check the user's Yahoo inbox every hour for emails from specific senders, and push an in-app notification when new ones arrive.
```

## Troubleshooting

### redirect_uri_mismatch error during Yahoo OAuth consent

Cause: The redirect URI passed in the authorization URL does not exactly match the URI registered in the Yahoo Developer app — even a trailing slash difference or HTTP vs HTTPS causes this error.

Solution: In the Yahoo Developer portal, go to your app's settings and copy the exact Callback Domain / Redirect URI value. Ensure the URI in your Cloud Function and in the consent URL built by the Custom Action matches character-for-character, including protocol (https://), domain, path, and no trailing slash unless registered with one.

### Token exchange fails with 'invalid_client' or 400 error at the Cloud Function callback

Cause: The client ID or client secret stored in Firebase Functions config does not match the Yahoo Developer app credentials, or the `Content-Type` on the token exchange request is missing.

Solution: Verify your Firebase Functions config values: `firebase functions:config:get yahoo`. Compare them against the Client ID and Secret shown in the Yahoo Developer portal. Confirm the token exchange POST request uses `Content-Type: application/x-www-form-urlencoded` — not JSON. Redeploy the function after updating config.

### 401 Unauthorized when calling Yahoo Mail API endpoints with the access token

Cause: The access token has expired and the refresh flow has not run, or the token was issued with insufficient scopes for the endpoint being called.

Solution: Call the `getYahooToken` Cloud Function before every Yahoo Mail API Call — it handles refresh automatically. If the error persists after refresh, verify the authorized scopes in your Yahoo Developer app include `mail-r` (or `mail-w` for write operations) and that the user re-authorized after any scope changes.

### Yahoo Mail API returns an endpoint not found or 'not implemented' error

Cause: Yahoo's REST API surface for Mail has changed and some previously documented endpoints have been deprecated or moved.

Solution: Check the Yahoo Mail API section of the Yahoo Developer portal for current endpoint paths and scope strings — this is one of the most frequently shifted APIs in this category. For operations that lack a REST endpoint, implement them in your Cloud Function using the `imapflow` Node.js package to access Yahoo Mail over IMAP, returning simplified JSON to FlutterFlow.

### Custom Action with url_launcher does not work in FlutterFlow Run Mode (web preview)

Cause: Custom Actions with pub.dev dependencies cannot run in FlutterFlow's web-based Run Mode — they require a real device or a compiled build.

Solution: Use FlutterFlow's 'Test Mode on Device' to test the Custom Action, or download and run the Flutter project locally. The url_launcher package works correctly on both iOS and Android devices.

## Frequently asked questions

### Can FlutterFlow send email through Yahoo Mail without OAuth?

No. Yahoo Mail does not offer an API key-based send endpoint — all access goes through OAuth 2.0. If you need to send emails from your app without a per-user login flow, use a transactional email service like Mailgun or SendGrid that authenticates with an API key at the service level rather than on behalf of individual users.

### Is Yahoo Mail API suitable for sending marketing or bulk emails?

No — Yahoo Mail API is a personal mailbox integration that acts on behalf of a single signed-in user. Sending bulk email through a personal Yahoo account is against Yahoo's Terms of Service and will result in account suspension. Use a purpose-built transactional or marketing email service (Mailgun, SendGrid, Mailchimp) for bulk sending.

### Why is the Yahoo Mail API harder to integrate than Gmail API?

Gmail has a comprehensive, well-documented REST API with stable endpoint paths and a clean `messages.send` endpoint (with the base64url encoding quirk). Yahoo Mail's REST API surface is thinner and less consistently documented — several operations that Gmail handles via REST require IMAP on Yahoo. Both use OAuth 2.0, but the Yahoo integration requires more server-side work because of the limited REST coverage.

### What happens if a user changes their Yahoo password after connecting?

Changing a Yahoo password invalidates existing OAuth tokens — the refresh token will fail and the user will need to re-authorize your app. Your FlutterFlow app should detect a failed refresh (the Cloud Function returns an error from Yahoo's token endpoint) and prompt the user to reconnect by running the OAuth consent flow again. Storing the last-successful token timestamp in Firestore helps surface this gracefully.

### Does this integration work for Yahoo accounts with two-factor authentication enabled?

Yes — the OAuth 2.0 consent flow handles MFA transparently. When the user authorizes on the Yahoo consent page in the browser, Yahoo handles any MFA challenge as part of its own login flow. Your Cloud Function and FlutterFlow app only interact with the resulting authorization code and tokens, never with the login step itself.

---

Source: https://www.rapidevelopers.com/flutterflow-integrations/yahoo-mail-api
© RapidDev — https://www.rapidevelopers.com/flutterflow-integrations/yahoo-mail-api
