Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

創建自定義電子郵件操作處理程序

某些用戶管理操作(例如更新用戶的電子郵件地址和重置用戶的密碼)會導致向用戶發送電子郵件。這些電子郵件包含收件人可以打開以完成或取消用戶管理操作的鏈接。默認情況下,用戶管理電子郵件鏈接到默認操作處理程序,這是一個網頁,託管在您項目的 Firebase 託管域中的 URL 中。

您可以改為創建和託管自定義電子郵件操作處理程序來進行自定義處理並將電子郵件操作處理程序與您的網站集成。

以下用戶管理操作要求用戶使用電子郵件操作處理程序完成操作:

  • 重置密碼
  • 撤消電子郵件地址更改 - 當用戶更改其帳戶的主要電子郵件地址時,Firebase 會向其舊地址發送一封電子郵件,允許他們撤消更改
  • 驗證電子郵件地址

要自定義 Firebase 項目的電子郵件操作處理程序,您必須創建並託管一個網頁,該網頁使用 Firebase JavaScript SDK 來驗證請求的有效性並完成請求。然後,您必須自定義 Firebase 項目的電子郵件模板以鏈接到您的自定義操作處理程序。

創建電子郵件操作處理程序頁面

  1. Firebase 在生成用戶管理電子郵件時會向您的操作處理程序 URL 添加多個查詢參數。例如:

    https://example.com/usermgmt?mode=resetPassword&oobCode=ABC123&apiKey=AIzaSy...&lang=fr

    這些參數指定用戶正在完成的用戶管理任務。您的電子郵件操作處理程序頁面必須處理以下查詢參數:

    參數
    模式

    要完成的用戶管理操作。可以是以下值之一:

    • resetPassword
    • recoverEmail
    • verifyEmail
    代碼一次性代碼,用於識別和驗證請求
    密鑰您的 Firebase 項目的 API 密鑰,為方便起見而提供
    繼續網址這是一個可選的 URL,它提供了一種通過 URL 將狀態傳遞回應用程序的方法。這與密碼重置和電子郵件驗證模式有關。當發送密碼重置電子郵件或驗證電子郵件, ActionCodeSettings對象需要與被指定的URL繼續這一可用。這使用戶可以在電子郵件操作後從上次中斷的地方繼續。

    這是可選的BCP47代表用戶的區域語言標記(例如, fr )。您可以使用此值向您的用戶提供本地化的電子郵件操作處理程序頁面。

    本地化可以通過 Firebase 控制台設置,也可以通過在觸發電子郵件操作之前調用相應的客戶端 API 來動態設置。例如,使用JavaScript: firebase.auth().languageCode = 'fr'; .

    為獲得一致的用戶體驗,請確保電子郵件操作處理程序本地化與電子郵件模板相匹配。

    以下示例顯示瞭如何在基於瀏覽器的處理程序中處理查詢參數。 (您也可以使用類似的邏輯將處理程序實現為 Node.js 應用程序。)

    網頁版 9

    import { initializeApp } from "firebase/app";
    import { getAuth } from "firebase/auth";
    
    document.addEventListener('DOMContentLoaded', () => {
      // TODO: Implement getParameterByName()
    
      // Get the action to complete.
      const mode = getParameterByName('mode');
      // Get the one-time code from the query parameter.
      const actionCode = getParameterByName('oobCode');
      // (Optional) Get the continue URL from the query parameter if available.
      const continueUrl = getParameterByName('continueUrl');
      // (Optional) Get the language code if available.
      const lang = getParameterByName('lang') || 'en';
    
      // Configure the Firebase SDK.
      // This is the minimum configuration required for the API to be used.
      const config = {
        'apiKey': "YOU_API_KEY" // Copy this key from the web initialization
                                // snippet found in the Firebase console.
      };
      const app = initializeApp(config);
      const auth = getAuth(app);
    
      // Handle the user management action.
      switch (mode) {
        case 'resetPassword':
          // Display reset password handler and UI.
          handleResetPassword(auth, actionCode, continueUrl, lang);
          break;
        case 'recoverEmail':
          // Display email recovery handler and UI.
          handleRecoverEmail(auth, actionCode, lang);
          break;
        case 'verifyEmail':
          // Display email verification handler and UI.
          handleVerifyEmail(auth, actionCode, continueUrl, lang);
          break;
        default:
          // Error: invalid mode.
      }
    }, false);

    網頁版 8

    document.addEventListener('DOMContentLoaded', () => {
      // TODO: Implement getParameterByName()
    
      // Get the action to complete.
      var mode = getParameterByName('mode');
      // Get the one-time code from the query parameter.
      var actionCode = getParameterByName('oobCode');
      // (Optional) Get the continue URL from the query parameter if available.
      var continueUrl = getParameterByName('continueUrl');
      // (Optional) Get the language code if available.
      var lang = getParameterByName('lang') || 'en';
    
      // Configure the Firebase SDK.
      // This is the minimum configuration required for the API to be used.
      var config = {
        'apiKey': "YOU_API_KEY" // Copy this key from the web initialization
                                // snippet found in the Firebase console.
      };
      var app = firebase.initializeApp(config);
      var auth = app.auth();
    
      // Handle the user management action.
      switch (mode) {
        case 'resetPassword':
          // Display reset password handler and UI.
          handleResetPassword(auth, actionCode, continueUrl, lang);
          break;
        case 'recoverEmail':
          // Display email recovery handler and UI.
          handleRecoverEmail(auth, actionCode, lang);
          break;
        case 'verifyEmail':
          // Display email verification handler and UI.
          handleVerifyEmail(auth, actionCode, continueUrl, lang);
          break;
        default:
          // Error: invalid mode.
      }
    }, false);
  2. 手柄密碼重置請求先驗證與操作代碼verifyPasswordResetCode ;然後從用戶那裡得到一個新的密碼,並把它傳遞給confirmPasswordReset 。例如:

    網頁版 9

    import { verifyPasswordResetCode, confirmPasswordReset } from "firebase/auth";
    
    function handleResetPassword(auth, actionCode, continueUrl, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
    
      // Verify the password reset code is valid.
      verifyPasswordResetCode(auth, actionCode).then((email) => {
        const accountEmail = email;
    
        // TODO: Show the reset screen with the user's email and ask the user for
        // the new password.
        const newPassword = "...";
    
        // Save the new password.
        confirmPasswordReset(auth, actionCode, newPassword).then((resp) => {
          // Password reset has been confirmed and new password updated.
    
          // TODO: Display a link back to the app, or sign-in the user directly
          // if the page belongs to the same domain as the app:
          // auth.signInWithEmailAndPassword(accountEmail, newPassword);
    
          // TODO: If a continue URL is available, display a button which on
          // click redirects the user back to the app via continueUrl with
          // additional state determined from that URL's parameters.
        }).catch((error) => {
          // Error occurred during confirmation. The code might have expired or the
          // password is too weak.
        });
      }).catch((error) => {
        // Invalid or expired action code. Ask user to try to reset the password
        // again.
      });
    }

    網頁版 8

    function handleResetPassword(auth, actionCode, continueUrl, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
    
      // Verify the password reset code is valid.
      auth.verifyPasswordResetCode(actionCode).then((email) => {
        var accountEmail = email;
    
        // TODO: Show the reset screen with the user's email and ask the user for
        // the new password.
        var newPassword = "...";
    
        // Save the new password.
        auth.confirmPasswordReset(actionCode, newPassword).then((resp) => {
          // Password reset has been confirmed and new password updated.
    
          // TODO: Display a link back to the app, or sign-in the user directly
          // if the page belongs to the same domain as the app:
          // auth.signInWithEmailAndPassword(accountEmail, newPassword);
    
          // TODO: If a continue URL is available, display a button which on
          // click redirects the user back to the app via continueUrl with
          // additional state determined from that URL's parameters.
        }).catch((error) => {
          // Error occurred during confirmation. The code might have expired or the
          // password is too weak.
        });
      }).catch((error) => {
        // Invalid or expired action code. Ask user to try to reset the password
        // again.
      });
    }
  3. 處理電子郵件地址變更撤銷先驗證與操作代碼checkActionCode ;然後恢復用戶的電子郵件地址applyActionCode 。例如:

    網頁版 9

    import { checkActionCode, applyActionCode, sendPasswordResetEmail } from "firebase/auth";
    
    function handleRecoverEmail(auth, actionCode, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
      let restoredEmail = null;
      // Confirm the action code is valid.
      checkActionCode(auth, actionCode).then((info) => {
        // Get the restored email address.
        restoredEmail = info['data']['email'];
    
        // Revert to the old email.
        return applyActionCode(auth, actionCode);
      }).then(() => {
        // Account email reverted to restoredEmail
    
        // TODO: Display a confirmation message to the user.
    
        // You might also want to give the user the option to reset their password
        // in case the account was compromised:
        sendPasswordResetEmail(auth, restoredEmail).then(() => {
          // Password reset confirmation sent. Ask user to check their email.
        }).catch((error) => {
          // Error encountered while sending password reset code.
        });
      }).catch((error) => {
        // Invalid code.
      });
    }

    網頁版 8

    function handleRecoverEmail(auth, actionCode, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
      var restoredEmail = null;
      // Confirm the action code is valid.
      auth.checkActionCode(actionCode).then((info) => {
        // Get the restored email address.
        restoredEmail = info['data']['email'];
    
        // Revert to the old email.
        return auth.applyActionCode(actionCode);
      }).then(() => {
        // Account email reverted to restoredEmail
    
        // TODO: Display a confirmation message to the user.
    
        // You might also want to give the user the option to reset their password
        // in case the account was compromised:
        auth.sendPasswordResetEmail(restoredEmail).then(() => {
          // Password reset confirmation sent. Ask user to check their email.
        }).catch((error) => {
          // Error encountered while sending password reset code.
        });
      }).catch((error) => {
        // Invalid code.
      });
    }
  4. 通過調用處理電子郵件地址驗證applyActionCode 。例如:

    網頁版 9

    function handleVerifyEmail(auth, actionCode, continueUrl, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
      // Try to apply the email verification code.
      applyActionCode(auth, actionCode).then((resp) => {
        // Email address has been verified.
    
        // TODO: Display a confirmation message to the user.
        // You could also provide the user with a link back to the app.
    
        // TODO: If a continue URL is available, display a button which on
        // click redirects the user back to the app via continueUrl with
        // additional state determined from that URL's parameters.
      }).catch((error) => {
        // Code is invalid or expired. Ask the user to verify their email address
        // again.
      });
    }

    網頁版 8

    function handleVerifyEmail(auth, actionCode, continueUrl, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
      // Try to apply the email verification code.
      auth.applyActionCode(actionCode).then((resp) => {
        // Email address has been verified.
    
        // TODO: Display a confirmation message to the user.
        // You could also provide the user with a link back to the app.
    
        // TODO: If a continue URL is available, display a button which on
        // click redirects the user back to the app via continueUrl with
        // additional state determined from that URL's parameters.
      }).catch((error) => {
        // Code is invalid or expired. Ask the user to verify their email address
        // again.
      });
    }
  5. 主機頁面的某個地方,例如使用火力地堡託管

接下來,您必須將 Firebase 項目配置為鏈接到其用戶管理電子郵件中的自定義電子郵件操作處理程序。

要配置您的 Firebase 項目以使用您的自定義電子郵件操作處理程序:

  1. 打開在項目火力地堡控制台
  2. 轉至電子郵件模板頁面的驗證部分。
  3. 在任何電子郵件類型的條目,點擊鉛筆圖標編輯的電子郵件模板。
  4. 單擊自定義動作URL,並指定URL到您的自定義電子郵件操作處理程序。

保存 URL 後,您的所有 Firebase 項目的電子郵件模板都會使用它。