Skip to content

Commit

Permalink
fix: add support for SendGrid categories and streamline SendGrid dete…
Browse files Browse the repository at this point in the history
…ction (#2053) (#2249)

Co-authored-by: Gustolandia <[email protected]>
  • Loading branch information
cabljac and Gustolandia committed Feb 3, 2025
1 parent 94fcf11 commit 314efdf
Show file tree
Hide file tree
Showing 13 changed files with 3,047 additions and 3,874 deletions.
4,730 changes: 2,173 additions & 2,557 deletions firestore-bigquery-export/functions/package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions firestore-send-email/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Version 0.1.35

feat - add SendGrid category support

## Version 0.1.34

fixed - SendGrid v3 issues (#2020)
Expand Down
22 changes: 22 additions & 0 deletions firestore-send-email/POSTINSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,28 @@ admin
See the [official documentation](https://firebase.google.com/docs/extensions/official/firestore-send-email) for information on using this extension, including advanced use cases such as using Handlebars templates and managing email delivery status.
#### Firestore-Send-Email: SendGrid Categories
When using SendGrid (`SMTP_CONNECTION_URI` includes `sendgrid.net`), you can assign categories to your emails.
## Example JSON with Categories:
```json
{
"to": ["[email protected]"],
"categories": ["Example_Category"],
"message": {
"subject": "Test Email with Categories",
"text": "This is a test email to see if categories work.",
"html": "<strong>This is a test email to see if categories work.</strong>"
}
}
```
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).
### Monitoring
As a best practice, you can [monitor the activity](https://firebase.google.com/docs/extensions/manage-installed-extensions#monitor) of your installed extension, including checks on its health, usage, and logs.
Expand Down
21 changes: 21 additions & 0 deletions firestore-send-email/PREINSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,27 @@ You can also optionally configure this extension to render emails using [Handleb

When you configure this extension, you'll need to supply your **SMTP credentials for mail delivery**. Note that this extension is for use with bulk email service providers, like SendGrid, Mailgun, etc.

#### Firestore-Send-Email: SendGrid Categories

When using SendGrid (`SMTP_CONNECTION_URI` includes `sendgrid.net`), you can assign categories to your emails.

## Example JSON with Categories:
```json
{
"to": ["[email protected]"],
"categories": ["Example_Category"],
"message": {
"subject": "Test Email with Categories",
"text": "This is a test email to see if categories work.",
"html": "<strong>This is a test email to see if categories work.</strong>"
}
}
```

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

**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:
Expand Down
21 changes: 21 additions & 0 deletions firestore-send-email/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,27 @@ You can also optionally configure this extension to render emails using [Handleb

When you configure this extension, you'll need to supply your **SMTP credentials for mail delivery**. Note that this extension is for use with bulk email service providers, like SendGrid, Mailgun, etc.

#### Firestore-Send-Email: SendGrid Categories

When using SendGrid (`SMTP_CONNECTION_URI` includes `sendgrid.net`), you can assign categories to your emails.

## Example JSON with Categories:
```json
{
"to": ["[email protected]"],
"categories": ["Example_Category"],
"message": {
"subject": "Test Email with Categories",
"text": "This is a test email to see if categories work.",
"html": "<strong>This is a test email to see if categories work.</strong>"
}
}
```

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

**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:
Expand Down
2 changes: 1 addition & 1 deletion firestore-send-email/extension.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

name: firestore-send-email
version: 0.1.34
version: 0.1.35
specVersion: v1beta

displayName: Trigger Email from Firestore
Expand Down
87 changes: 42 additions & 45 deletions firestore-send-email/functions/__tests__/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Mail = require("nodemailer/lib/mailer");
const { logger } = require("firebase-functions");

import { setSmtpCredentials } from "../src/helpers";
import { setSmtpCredentials, isSendGrid } from "../src/helpers";
import { Config } from "../src/types";

const consoleLogSpy = jest.spyOn(logger, "warn").mockImplementation();
Expand All @@ -11,7 +11,7 @@ const regex = new RegExp(
"^(smtp[s]*://(.*?(:[^:@]*)?@)?[^:@]+:[0-9]+(\\?[^ ]*)?)$"
);

describe("set server credentials helper function", () => {
describe("setSmtpCredentials function", () => {
test("return smtpServerDomain credentials with new password", () => {
const config: Config = {
smtpConnectionUri:
Expand All @@ -32,26 +32,7 @@ describe("set server credentials helper function", () => {
expect(regex.test(config.smtpConnectionUri)).toBe(true);
});

test("return smtpServerDomain credentials with new password (old deleted)", () => {
const config: Config = {
smtpConnectionUri: "smtps://[email protected]@smtp.gmail.com:465",
smtpPassword: "sec#:@ret-password",
location: "",
mailCollection: "",
defaultFrom: "",
};
const credentials = setSmtpCredentials(config);
expect(credentials).toBeInstanceOf(Mail);
expect(credentials.options.port).toBe(465);
expect(credentials.options.host).toBe("smtp.gmail.com");
expect(credentials.options.auth.pass).toBe(config.smtpPassword);
expect(credentials.options.secure).toBe(true);

// The regex should match the smtpConnectionUri, it should be valid
expect(regex.test(config.smtpConnectionUri)).toBe(true);
});

test("return smtpConnectionUri credentials with old password", () => {
test("return smtpServerDomain credentials with old password", () => {
const config: Config = {
smtpConnectionUri:
"smtps://[email protected]:[email protected]:465",
Expand Down Expand Up @@ -130,7 +111,7 @@ describe("set server credentials helper function", () => {
expect(regex.test(config.smtpConnectionUri)).toBe(true);
});

test("return valid smtpConnectionUri credentials with special chars in password config", () => {
test("return valid smtpConnectionUri credentials with valid special chars in password", () => {
const config: Config = {
smtpConnectionUri:
"smtp://[email protected]@smtp.gmail.com:465?pool=true&service=gmail",
Expand Down Expand Up @@ -176,7 +157,7 @@ describe("set server credentials helper function", () => {
expect(regex.test(config.smtpConnectionUri)).toBe(true);
});

test("return invalid smtpConnectionUri credentials with invalid special chars in connectionUri password", () => {
test("throw error for invalid smtpConnectionUri", () => {
const config: Config = {
smtpConnectionUri:
"smtp://[email protected]:4,h?dhuNTbv9zMrP4&7&7%*[email protected]:465?pool=true&service=gmail",
Expand All @@ -185,48 +166,64 @@ describe("set server credentials helper function", () => {
defaultFrom: "",
};

// Expect an error to be thrown
expect(() => setSmtpCredentials(config)).toThrow(Error);

expect(consoleLogSpy).toBeCalledWith(
"Invalid URI: please reconfigure with a valid SMTP connection URI"
);
});
test("return valid smtpConnectionUri credentials with correct seprator", () => {
});

describe("isSendGrid function", () => {
test("return true for SendGrid SMTP URI", () => {
const config: Config = {
smtpConnectionUri:
"smtp://[email protected]:4,h?dhuNTbv9zMrP4&7&7%*[email protected]:465?pool=true&service=gmail",
smtpConnectionUri: "smtps://[email protected]:465",
location: "",
mailCollection: "",
defaultFrom: "",
};

expect(regex.test(config.smtpConnectionUri)).toBe(true);
expect(isSendGrid(config)).toBe(true);
});

test("return invalid smtpConnectionUri credentials with invalid seprator", () => {
test("return false for non-SendGrid SMTP URI", () => {
const config: Config = {
smtpConnectionUri:
"smtp://[email protected]:4,h?dhuNTbv9zMrP4&7&7%*3:smtp.gmail.com:465?pool=true&service=gmail",
"smtps://[email protected]:secret-password@smtp.gmail.com:465",
location: "",
mailCollection: "",
defaultFrom: "",
};

expect(regex.test(config.smtpConnectionUri)).toBe(false);
expect(isSendGrid(config)).toBe(false);
});
});

/* Test removed due to the new SendGrid transporter logic - see setSendGridTransport()
test("return a SendGrid transporter if the host is smtp.sendgrid.net", () => {
const config: Config = {
smtpConnectionUri: "smtps://apikey@smtp.sendgrid.net:465",
location: "",
mailCollection: "",
defaultFrom: "",
};
test("return invalid smtpConnectionUri credentials with invalid separator", () => {
const config: Config = {
smtpConnectionUri:
"smtp://[email protected]:4,h?dhuNTbv9zMrP4&7&7%*3:smtp.gmail.com:465?pool=true&service=gmail",
location: "",
mailCollection: "",
defaultFrom: "",
};

const credentials = setSmtpCredentials(config);
expect(credentials.transporter.name === "nodemailer-sendgrid").toBe(true);
});
*/
expect(regex.test(config.smtpConnectionUri)).toBe(false);
});

test("correctly detects SendGrid SMTP URI", () => {
const config: Config = {
smtpConnectionUri: "smtps://[email protected]:465",
location: "",
mailCollection: "",
defaultFrom: "",
};
expect(isSendGrid(config)).toBe(true);

const invalidConfig: Config = {
smtpConnectionUri: "smtps://[email protected]:465",
location: "",
mailCollection: "",
defaultFrom: "",
};
expect(isSendGrid(invalidConfig)).toBe(false);
});
Loading

0 comments on commit 314efdf

Please sign in to comment.