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

某些用戶管理操作(例如更新用戶的電子郵件地址和重置用戶密碼)會導致向用戶發送電子郵件。這些電子郵件包含收件人可以打開以完成或取消用戶管理操作的鏈接。默認情況下,用戶管理電子郵件鏈接到默認操作處理程序,該處理程序是託管在您項目的 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
    oob代碼一次性代碼,用於識別和驗證請求
    密鑰您的 Firebase 項目的 API 密鑰,為方便起見而提供
    繼續網址這是一個可選的 URL,它提供了一種通過 URL 將狀態傳回應用程序的方法。這與密碼重置和電子郵件驗證模式有關。發送密碼重置電子郵件或驗證電子郵件時,需要使用繼續 URL 指定ActionCodeSettings對象才能使其可用。這使得用戶可以在電子郵件操作後從他們離開的地方繼續。

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

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

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

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

    Web modular API

    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);

    Web namespaced API

    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 。例如:

    Web modular API

    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.
      });
    }

    Web namespaced API

    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恢復用戶的電子郵件地址。例如:

    Web modular API

    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.
      });
    }

    Web namespaced API

    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處理電子郵件地址驗證。例如:

    Web modular API

    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.
      });
    }

    Web namespaced API

    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 Hosting

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

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

  1. Firebase 控制台中打開您的項目。
  2. 轉到Auth部分中的Email Templates頁面。
  3. 在任何電子郵件類型條目中,單擊鉛筆圖標以編輯電子郵件模板。
  4. 單擊customize action URL ,並指定您的自定義電子郵件操作處理程序的 URL。

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