Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/readmes-updated.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
echo "::set-output name=dir::$(npm config get prefix)"

- name: Cache global dependencies
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ${{ steps.global-deps-setup.outputs.dir }}
key:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ You can also browse official Firebase extensions on the [Extensions Marketplace]

Documentation for the [Extensions by Firebase](https://firebase.google.com/docs/extensions) section are now stored in this repository.

They can be found under [Docs](https://github.com/firebase/extensions/docs)
They can be found under [Docs](https://github.com/firebase/extensions/tree/master/docs)
8 changes: 8 additions & 0 deletions firestore-send-email/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## Version 0.1.37

feat: add support for OAuth2 authentication

fix: default replyTo issue introduced in 0.1.35

fix: sendgrid attachment bug introduced in 0.1.35

## Version 0.1.36

feat - move to Node.js 20 runtimes
Expand Down
154 changes: 137 additions & 17 deletions firestore-send-email/PREINSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,150 @@ Add this document to the Firestore mail collection to send categorized emails.

For more details, see the [SendGrid Categories documentation](https://docs.sendgrid.com/ui/sending-email/categories).

#### Setup Google App Passwords
#### Setting Up OAuth2 Authentication

This section will help you set up OAuth2 authentication for the extension, using GCP (Gmail) as an example.

The extension is agnostic with respect to OAuth2 provider. You just need to provide it with valid Client ID, Client Secret, and Refresh Token parameters.

##### Step 1: Create OAuth Credentials in Google Cloud Platform

1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Select your project
3. In the left sidebar, navigate to **APIs & Services > Credentials**
4. Click Create Credentials and select **OAuth client ID**
5. Set the application type to **Web application**
6. Give your OAuth client a name (e.g., "Firestore Send Email Extension")
7. Under **Authorized redirect URIs**, add the URI where you'll receive the OAuth callback, for example, `http://localhost:8080/oauth/callback`.

**Note**: The redirect URI in your OAuth client settings MUST match exactly the callback URL in your code.

8. Click **Create**.

##### Step 2: Configure OAuth Consent Screen

1. In Google Cloud Console, go to **APIs & Services > OAuth consent screen**
2. Choose the appropriate user type:
- **External**: For applications used by any Google user
- **Internal**: For applications used only by users in your organization

> **Important Note**: If your OAuth consent screen is in "Testing" status, refresh tokens will expire after 7 days unless the User Type is set to "Internal."

##### Step 3: Generate a Refresh Token

**Google** no longer allows **Gmail** users to use their own passwords to authorize third-party apps and services. Instead, you have to use the [Sign in with App Passwords](https://support.google.com/accounts/answer/185833) service to generate a special password for each app you want to authorize. To do so:
You can use a standalone helper script (`oauth2-refresh-token-helper.js`) that generates a refresh token without requiring any npm installations.

**Prerequisites:**
- You must have Node.js installed on your machine

1. Go to your [Google Account](https://myaccount.google.com/).
2. Select **Security**.
3. Under "Signing in to Google," select **App Passwords**. You may need to sign in. If you don’t have this option, it might be because:
1. 2-Step Verification is not set up for your account.
2. 2-Step Verification is only set up for security keys.
3. Your account is through work, school, or other organization.
4. You turned on Advanced Protection.
4. At the bottom, choose **Select app** and choose **Other** option and then write the name of the app password (e.g. `Firebase Trigger Email from Firestore Extension`) and click **Generate**.
5. Follow the instructions to enter the App Password. The App Password is the 16-character code in the yellow bar on your device.
6. Tap **Done**.
**Download the script:**
1. Download the script using curl, wget, or directly from your browser:
```bash
# Using curl
curl -o oauth2-refresh-token-helper.js https://raw.githubusercontent.com/firebase/extensions/refs/heads/master/firestore-send-email/scripts/oauth2-refresh-token-helper.js

# Using wget
wget https://raw.githubusercontent.com/firebase/extensions/refs/heads/master/firestore-send-email/scripts/oauth2-refresh-token-helper.js
```

Now you can use your Google username with the generated password to authorize the extension.
You can also [view the script on GitHub](https://github.com/firebase/extensions/blob/master/firestore-send-email/scripts/oauth2-refresh-token-helper.js) and download it manually.

#### Setup Hotmail Passwords
> **Note**: If you are creating your own application to obtain a refresh token, in a Node.js environment where you can use npm packages, consider using the official google-auth-library instead:
>
> 1. Install the library: `npm install google-auth-library`
> 2. Then use it like this:
> ```javascript
> import { OAuth2Client } from "google-auth-library";
>
> // Initialize OAuth client
> const oAuth2Client = new OAuth2Client(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);
>
> // Generate authorization URL
> const authorizeUrl = oAuth2Client.generateAuthUrl({
> access_type: "offline",
> prompt: "consent",
> scope: ["https://mail.google.com/"], // Full Gmail access
> });
>
> // After receiving the code from the callback:
> const { tokens } = await oAuth2Client.getToken(code);
> const refreshToken = tokens.refresh_token;
> ```

To use your Outlook/Hotmail email account with this extension, you'll need to have 2FA enabled on your account, and [Create an App Password](https://support.microsoft.com/en-us/help/12409/microsoft-account-app-passwords-and-two-step-verification).
2. Run the script with Node.js:

#### Additional setup
```bash
node oauth2-refresh-token-helper.js
```

Before installing this extension, make sure that you've [set up a Cloud Firestore database](https://firebase.google.com/docs/firestore/quickstart) in your Firebase project.
3. The script supports the following command-line options:
```
--port, -p Port to run the server on (default: 8080 or PORT env var)
--id, -i Google OAuth Client ID
--secret, -s Google OAuth Client Secret
--output, -o Output file to save the refresh token (default: refresh_token.txt)
--help, -h Show help information
```

4. You can either provide your credentials as command-line arguments or set them as environment variables:
```bash
# Using environment variables
export CLIENT_ID=your_client_id
export CLIENT_SECRET=your_client_secret
node oauth2-refresh-token-helper.js

# Using command-line arguments
node oauth2-refresh-token-helper.js --id=your_client_id --secret=your_client_secret
```

5. The script will:
- Start a local web server
- Open your browser to the OAuth consent page
- Receive the authorization code
- Exchange the code for tokens
- Save the refresh token to a file (default: `refresh_token.txt`)
- Display the refresh token in your browser

6. **Important**: The redirect URI in the script (`http://localhost:8080/oauth/callback` by default) **MUST** match exactly what you configured in the Google Cloud Console OAuth client settings.

7. The script automatically requests the appropriate scope for Gmail access (`https://mail.google.com/`) and sets the authorization parameters to always receive a refresh token (`access_type: "offline"` and `prompt: "consent"`).

##### Step 4: Configure the Firestore Send Email Extension

When installing the extension, select "OAuth2" as the **Authentication Type** and provide the following parameters:

- **OAuth2 SMTP Host**: `smtp.gmail.com` (for Gmail)
- **OAuth2 SMTP Port**: `465` (for SMTPS) or `587` (for STARTTLS)
- **Use Secure OAuth2 Connection**: `true` (for port 465) or `false` (for port 587)
- **OAuth2 Client ID**: Your Client ID from GCP
- **OAuth2 Client Secret**: Your Client Secret from GCP
- **OAuth2 Refresh Token**: The refresh token generated in Step 3
- **SMTP User**: Your full Gmail email address

Leave `Use secure OAuth2 connection?` as the default value `true`.

##### Troubleshooting

###### Refresh Token Expiration

- **Testing Status**: If your OAuth consent screen is in "Testing" status, refresh tokens expire after 7 days unless User Type is set to "Internal"
- **Solution**: Either publish your app or ensure User Type is set to "Internal" in the OAuth consent screen settings

###### No Refresh Token Received

- **Problem**: If you don't receive a refresh token during the OAuth flow
- **Solution**: Make sure you've revoked previous access or forced consent by going to [Google Account Security](https://myaccount.google.com/security) > Third-party apps with account access

###### Scope Issues

- **Problem**: If you see authentication errors, you might not have the correct scopes
- **Solution**: Ensure you've added `https://mail.google.com/` as a scope in the OAuth consent screen

###### Additional Resources

- [Google OAuth2 Documentation](https://developers.google.com/identity/protocols/oauth2)
- [Nodemailer OAuth2 Guide](https://nodemailer.com/smtp/oauth2/)
- [Firebase Extensions Documentation](https://firebase.google.com/docs/extensions)

#### Automatic Deletion of Email Documents

Expand Down
170 changes: 153 additions & 17 deletions firestore-send-email/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,150 @@ Add this document to the Firestore mail collection to send categorized emails.

For more details, see the [SendGrid Categories documentation](https://docs.sendgrid.com/ui/sending-email/categories).

#### Setup Google App Passwords
#### Setting Up OAuth2 Authentication

This section will help you set up OAuth2 authentication for the extension, using GCP (Gmail) as an example.

The extension is agnostic with respect to OAuth2 provider. You just need to provide it with valid Client ID, Client Secret, and Refresh Token parameters.

##### Step 1: Create OAuth Credentials in Google Cloud Platform

1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Select your project
3. In the left sidebar, navigate to **APIs & Services > Credentials**
4. Click Create Credentials and select **OAuth client ID**
5. Set the application type to **Web application**
6. Give your OAuth client a name (e.g., "Firestore Send Email Extension")
7. Under **Authorized redirect URIs**, add the URI where you'll receive the OAuth callback, for example, `http://localhost:8080/oauth/callback`.

**Note**: The redirect URI in your OAuth client settings MUST match exactly the callback URL in your code.

8. Click **Create**.

##### Step 2: Configure OAuth Consent Screen

1. In Google Cloud Console, go to **APIs & Services > OAuth consent screen**
2. Choose the appropriate user type:
- **External**: For applications used by any Google user
- **Internal**: For applications used only by users in your organization

> **Important Note**: If your OAuth consent screen is in "Testing" status, refresh tokens will expire after 7 days unless the User Type is set to "Internal."

##### Step 3: Generate a Refresh Token

**Google** no longer allows **Gmail** users to use their own passwords to authorize third-party apps and services. Instead, you have to use the [Sign in with App Passwords](https://support.google.com/accounts/answer/185833) service to generate a special password for each app you want to authorize. To do so:
You can use a standalone helper script (`oauth2-refresh-token-helper.js`) that generates a refresh token without requiring any npm installations.

**Prerequisites:**
- You must have Node.js installed on your machine

1. Go to your [Google Account](https://myaccount.google.com/).
2. Select **Security**.
3. Under "Signing in to Google," select **App Passwords**. You may need to sign in. If you don’t have this option, it might be because:
1. 2-Step Verification is not set up for your account.
2. 2-Step Verification is only set up for security keys.
3. Your account is through work, school, or other organization.
4. You turned on Advanced Protection.
4. At the bottom, choose **Select app** and choose **Other** option and then write the name of the app password (e.g. `Firebase Trigger Email from Firestore Extension`) and click **Generate**.
5. Follow the instructions to enter the App Password. The App Password is the 16-character code in the yellow bar on your device.
6. Tap **Done**.
**Download the script:**
1. Download the script using curl, wget, or directly from your browser:
```bash
# Using curl
curl -o oauth2-refresh-token-helper.js https://raw.githubusercontent.com/firebase/extensions/refs/heads/master/firestore-send-email/scripts/oauth2-refresh-token-helper.js

# Using wget
wget https://raw.githubusercontent.com/firebase/extensions/refs/heads/master/firestore-send-email/scripts/oauth2-refresh-token-helper.js
```

Now you can use your Google username with the generated password to authorize the extension.
You can also [view the script on GitHub](https://github.com/firebase/extensions/blob/master/firestore-send-email/scripts/oauth2-refresh-token-helper.js) and download it manually.

#### Setup Hotmail Passwords
> **Note**: If you are creating your own application to obtain a refresh token, in a Node.js environment where you can use npm packages, consider using the official google-auth-library instead:
>
> 1. Install the library: `npm install google-auth-library`
> 2. Then use it like this:
> ```javascript
> import { OAuth2Client } from "google-auth-library";
>
> // Initialize OAuth client
> const oAuth2Client = new OAuth2Client(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);
>
> // Generate authorization URL
> const authorizeUrl = oAuth2Client.generateAuthUrl({
> access_type: "offline",
> prompt: "consent",
> scope: ["https://mail.google.com/"], // Full Gmail access
> });
>
> // After receiving the code from the callback:
> const { tokens } = await oAuth2Client.getToken(code);
> const refreshToken = tokens.refresh_token;
> ```

To use your Outlook/Hotmail email account with this extension, you'll need to have 2FA enabled on your account, and [Create an App Password](https://support.microsoft.com/en-us/help/12409/microsoft-account-app-passwords-and-two-step-verification).
2. Run the script with Node.js:

#### Additional setup
```bash
node oauth2-refresh-token-helper.js
```

Before installing this extension, make sure that you've [set up a Cloud Firestore database](https://firebase.google.com/docs/firestore/quickstart) in your Firebase project.
3. The script supports the following command-line options:
```
--port, -p Port to run the server on (default: 8080 or PORT env var)
--id, -i Google OAuth Client ID
--secret, -s Google OAuth Client Secret
--output, -o Output file to save the refresh token (default: refresh_token.txt)
--help, -h Show help information
```

4. You can either provide your credentials as command-line arguments or set them as environment variables:
```bash
# Using environment variables
export CLIENT_ID=your_client_id
export CLIENT_SECRET=your_client_secret
node oauth2-refresh-token-helper.js

# Using command-line arguments
node oauth2-refresh-token-helper.js --id=your_client_id --secret=your_client_secret
```

5. The script will:
- Start a local web server
- Open your browser to the OAuth consent page
- Receive the authorization code
- Exchange the code for tokens
- Save the refresh token to a file (default: `refresh_token.txt`)
- Display the refresh token in your browser

6. **Important**: The redirect URI in the script (`http://localhost:8080/oauth/callback` by default) **MUST** match exactly what you configured in the Google Cloud Console OAuth client settings.

7. The script automatically requests the appropriate scope for Gmail access (`https://mail.google.com/`) and sets the authorization parameters to always receive a refresh token (`access_type: "offline"` and `prompt: "consent"`).

##### Step 4: Configure the Firestore Send Email Extension

When installing the extension, select "OAuth2" as the **Authentication Type** and provide the following parameters:

- **OAuth2 SMTP Host**: `smtp.gmail.com` (for Gmail)
- **OAuth2 SMTP Port**: `465` (for SMTPS) or `587` (for STARTTLS)
- **Use Secure OAuth2 Connection**: `true` (for port 465) or `false` (for port 587)
- **OAuth2 Client ID**: Your Client ID from GCP
- **OAuth2 Client Secret**: Your Client Secret from GCP
- **OAuth2 Refresh Token**: The refresh token generated in Step 3
- **SMTP User**: Your full Gmail email address

Leave `Use secure OAuth2 connection?` as the default value `true`.

##### Troubleshooting

###### Refresh Token Expiration

- **Testing Status**: If your OAuth consent screen is in "Testing" status, refresh tokens expire after 7 days unless User Type is set to "Internal"
- **Solution**: Either publish your app or ensure User Type is set to "Internal" in the OAuth consent screen settings

###### No Refresh Token Received

- **Problem**: If you don't receive a refresh token during the OAuth flow
- **Solution**: Make sure you've revoked previous access or forced consent by going to [Google Account Security](https://myaccount.google.com/security) > Third-party apps with account access

###### Scope Issues

- **Problem**: If you see authentication errors, you might not have the correct scopes
- **Solution**: Ensure you've added `https://mail.google.com/` as a scope in the OAuth consent screen

###### Additional Resources

- [Google OAuth2 Documentation](https://developers.google.com/identity/protocols/oauth2)
- [Nodemailer OAuth2 Guide](https://nodemailer.com/smtp/oauth2/)
- [Firebase Extensions Documentation](https://firebase.google.com/docs/extensions)

#### Automatic Deletion of Email Documents

Expand Down Expand Up @@ -99,6 +219,8 @@ You can find more information about this extension in the following articles:

**Configuration Parameters:**

* Authentication Type: The authentication type to be used for the SMTP server (e.g., OAuth2, Username & Password.

* SMTP connection URI: A URI representing an SMTP server this extension can use to deliver email. Note that port 25 is blocked by Google Cloud Platform, so we recommend using port 587 for SMTP connections. If you're using the SMTPS protocol, we recommend using port 465. In order to keep passwords secure, it is recommended to omit the password from the connection string while using the `SMTP Password` field for entering secrets and passwords. Passwords and secrets should now be included in `SMTP password` field.
Secure format:
`smtps://username@gmail.com@smtp.gmail.com:465` (username only)
Expand All @@ -109,6 +231,20 @@ password)

* SMTP password: User password for the SMTP server

* OAuth2 SMTP Host: The OAuth2 hostname of the SMTP server (e.g., smtp.gmail.com).

* OAuth2 SMTP Port: The OAuth2 port number for the SMTP server (e.g., 465 for SMTPS, 587 for STARTTLS).

* Use secure OAuth2 connection?: Set to true to enable a secure connection (TLS/SSL) when using OAuth2 authentication for the SMTP server.

* OAuth2 Client ID: The OAuth2 Client ID for authentication with the SMTP server.

* OAuth2 Client Secret: The OAuth2 Client Secret for authentication with the SMTP server.

* OAuth2 Refresh Token: The OAuth2 Refresh Token for authentication with the SMTP server.

* OAuth2 SMTP User: The OAuth2 user email or username for SMTP authentication.

* Email documents collection: What is the path to the collection that contains the documents used to build and send the emails?

* Default FROM address: The email address to use as the sender's address (if it's not specified in the added email document). You can optionally include a name with the email address (`Friendly Firebaser <foobar@example.com>`). This parameter does not work with [Gmail SMTP](https://nodemailer.com/usage/using-gmail/).
Expand Down
Loading
Loading