Skip to content

@invertase/firestore send email v2 rebased #2388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
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
6 changes: 4 additions & 2 deletions firestore-send-email/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## Version 0.1.38
## Version 0.2.0

fix: empty message property causing error when using SendGrid
feat: use v2 firestore trigger

feat: allow non-(default) firestore instances

## Version 0.1.37

Expand Down
2 changes: 1 addition & 1 deletion firestore-send-email/POSTINSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

You can test out this extension right away!

1. Go to your [Cloud Firestore dashboard](https://console.firebase.google.com/project/${param:PROJECT_ID}/firestore/data) in the Firebase console.
1. Go to your [Cloud Firestore dashboard](https://console.firebase.google.com/project/${param:PROJECT_ID}/firestore/data) in the Firebase console. Note that, if you have configured a non-default firestore database, you may have to view it via the [Google Cloud Console](https://console.cloud.google.com/firestore/databases/${param:DATABASE}).

1. If it doesn't already exist, create the collection you specified during installation: `${param:MAIL_COLLECTION}`.

Expand Down
10 changes: 8 additions & 2 deletions firestore-send-email/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ You can find more information about this extension in the following articles:

**Configuration Parameters:**

* Firestore Instance ID: The Firestore database to use. Use "(default)" for the default database. You can view your available Firestore databases at [https://console.cloud.google.com/firestore/databases](https://console.cloud.google.com/firestore/databases).


* Firestore Instance Location: Where is the Firestore database located? You can check your current database location at [https://console.cloud.google.com/firestore/databases](https://console.cloud.google.com/firestore/databases).


* 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.
Expand Down Expand Up @@ -263,9 +269,9 @@ password)



**Cloud Functions:**
**Other Resources**:

* **processQueue:** Processes document changes in the specified Cloud Firestore collection, delivers emails, and updates the document with delivery status information.
* processQueue (firebaseextensions.v1beta.v2function)



Expand Down
146 changes: 141 additions & 5 deletions 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.38
version: 0.2.0
specVersion: v1beta

displayName: Trigger Email from Firestore
Expand Down Expand Up @@ -47,18 +47,154 @@ roles:

resources:
- name: processQueue
type: firebaseextensions.v1beta.function
type: firebaseextensions.v1beta.v2function
description:
Processes document changes in the specified Cloud Firestore collection,
delivers emails, and updates the document with delivery status
information.
properties:
runtime: nodejs20
sourceDirectory: functions
buildConfig:
runtime: nodejs22
serviceConfig:
timeoutSeconds: 120
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${param:PROJECT_ID}/databases/(default)/documents/${param:MAIL_COLLECTION}/{id}
eventType: google.cloud.firestore.document.v1.written
triggerRegion: ${DATABASE_REGION}
eventFilters:
- attribute: database
value: ${DATABASE}
- attribute: document
value: ${MAIL_COLLECTION}/{documentId}
operator: match-path-pattern

params:
- param: DATABASE
label: Firestore Instance ID
description: >
The Firestore database to use. Use "(default)" for the default database.
You can view your available Firestore databases at
[https://console.cloud.google.com/firestore/databases](https://console.cloud.google.com/firestore/databases).
example: (default)
default: (default)
required: true

- param: DATABASE_REGION
label: Firestore Instance Location
description: >
Where is the Firestore database located? You can check your current
database location at
[https://console.cloud.google.com/firestore/databases](https://console.cloud.google.com/firestore/databases).
type: select
options:
# Multi-region locations
- label: Multi-region (Europe - Belgium and Netherlands)
value: eur3
- label: Multi-region (United States)
value: nam5
- label: Multi-region (Iowa, North Virginia, and Oklahoma)
value: nam7

# North America
- label: Iowa (us-central1)
value: us-central1
- label: Oregon (us-west1)
value: us-west1
- label: Los Angeles (us-west2)
value: us-west2
- label: Salt Lake City (us-west3)
value: us-west3
- label: Las Vegas (us-west4)
value: us-west4
- label: South Carolina (us-east1)
value: us-east1
- label: Northern Virginia (us-east4)
value: us-east4
- label: Columbus (us-east5)
value: us-east5
- label: Dallas (us-south1)
value: us-south1
- label: Montreal (northamerica-northeast1)
value: northamerica-northeast1
- label: Toronto (northamerica-northeast2)
value: northamerica-northeast2
- label: Queretaro (northamerica-south1)
value: northamerica-south1

# South America
- label: Sao Paulo (southamerica-east1)
value: southamerica-east1
- label: Santiago (southamerica-west1)
value: southamerica-west1

# Europe
- label: Belgium (europe-west1)
value: europe-west1
- label: London (europe-west2)
value: europe-west2
- label: Frankfurt (europe-west3)
value: europe-west3
- label: Netherlands (europe-west4)
value: europe-west4
- label: Zurich (europe-west6)
value: europe-west6
- label: Milan (europe-west8)
value: europe-west8
- label: Paris (europe-west9)
value: europe-west9
- label: Berlin (europe-west10)
value: europe-west10
- label: Turin (europe-west12)
value: europe-west12
- label: Madrid (europe-southwest1)
value: europe-southwest1
- label: Finland (europe-north1)
value: europe-north1
- label: Stockholm (europe-north2)
value: europe-north2
- label: Warsaw (europe-central2)
value: europe-central2

# Middle East
- label: Doha (me-central1)
value: me-central1
- label: Dammam (me-central2)
value: me-central2
- label: Tel Aviv (me-west1)
value: me-west1

# Asia
- label: Mumbai (asia-south1)
value: asia-south1
- label: Delhi (asia-south2)
value: asia-south2
- label: Singapore (asia-southeast1)
value: asia-southeast1
- label: Jakarta (asia-southeast2)
value: asia-southeast2
- label: Taiwan (asia-east1)
value: asia-east1
- label: Hong Kong (asia-east2)
value: asia-east2
- label: Tokyo (asia-northeast1)
value: asia-northeast1
- label: Osaka (asia-northeast2)
value: asia-northeast2
- label: Seoul (asia-northeast3)
value: asia-northeast3

# Australia
- label: Sydney (australia-southeast1)
value: australia-southeast1
- label: Melbourne (australia-southeast2)
value: australia-southeast2

# Africa
- label: Johannesburg (africa-south1)
value: africa-south1
required: true
immutable: false

- param: AUTH_TYPE
label: Authentication Type
description: >-
Expand Down
4 changes: 4 additions & 0 deletions firestore-send-email/functions/__tests__/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ functionsTestInit();

const environment = {
LOCATION: "us-central1",
DATABASE: "fake-database",
DATABASE_REGION: "us-central1",
TEMPLATES_COLLECTION: "templates",
MAIL_COLLECTION: "mail",
SMTP_CONNECTION_URI:
Expand Down Expand Up @@ -41,6 +43,8 @@ describe("extensions config", () => {
test("config loaded from environment variables", () => {
const testConfig: Config = {
location: process.env.LOCATION,
database: process.env.DATABASE,
databaseRegion: process.env.DATABASE_REGION,
mailCollection: process.env.MAIL_COLLECTION,
smtpConnectionUri: process.env.SMTP_CONNECTION_URI,
smtpPassword: process.env.SMTP_PASSWORD,
Expand Down
28 changes: 28 additions & 0 deletions firestore-send-email/functions/__tests__/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const regex = new RegExp(
describe("setSmtpCredentials function", () => {
test("return smtpServerDomain credentials with new password", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri:
"smtps://[email protected]:[email protected]:465",
smtpPassword: "fakepassword",
Expand All @@ -35,6 +37,8 @@ describe("setSmtpCredentials function", () => {

test("return smtpServerDomain credentials with old password", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri:
"smtps://[email protected]:[email protected]:465",
location: "",
Expand All @@ -56,6 +60,8 @@ describe("setSmtpCredentials function", () => {

test("return smtpConnectionUri credentials without any password", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri: "smtps://[email protected]@smtp.gmail.com:465",
location: "",
mailCollection: "",
Expand All @@ -76,6 +82,8 @@ describe("setSmtpCredentials function", () => {

test("return smtpConnectionUri credentials without any password and username", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri: "smtp://smtp.gmail.com:465",
location: "",
mailCollection: "",
Expand All @@ -95,6 +103,8 @@ describe("setSmtpCredentials function", () => {

test("return smtpConnectionUri credentials with query params", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri:
"smtp://[email protected]:[email protected]:465?pool=true&service=gmail",
location: "",
Expand All @@ -118,6 +128,8 @@ describe("setSmtpCredentials function", () => {

test("return valid smtpConnectionUri credentials with valid special chars in password", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri:
"smtp://[email protected]@smtp.gmail.com:465?pool=true&service=gmail",
smtpPassword: "4,h?dhuNTbv9zMrP4&7&7%*3",
Expand All @@ -142,6 +154,8 @@ describe("setSmtpCredentials function", () => {

test("return valid smtpConnectionUri credentials with valid special chars in connectionUri password", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri:
"smtp://[email protected]:4,hdhuNTbv9zMrP4&7&7%*[email protected]:465?pool=true&service=gmail",
location: "",
Expand All @@ -166,6 +180,8 @@ describe("setSmtpCredentials function", () => {

test("throw error for invalid smtpConnectionUri", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri:
"smtp://[email protected]:4,h?dhuNTbv9zMrP4&7&7%*[email protected]:465?pool=true&service=gmail",
location: "",
Expand All @@ -184,6 +200,8 @@ describe("setSmtpCredentials function", () => {
describe("isSendGrid function", () => {
test("return true for SendGrid SMTP URI", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri: "smtps://[email protected]:465",
location: "",
mailCollection: "",
Expand All @@ -196,6 +214,8 @@ describe("isSendGrid function", () => {

test("return false for non-SendGrid SMTP URI", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri:
"smtps://[email protected]:[email protected]:465",
location: "",
Expand All @@ -210,6 +230,8 @@ describe("isSendGrid function", () => {

test("return invalid smtpConnectionUri credentials with invalid separator", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri:
"smtp://[email protected]:4,h?dhuNTbv9zMrP4&7&7%*3:smtp.gmail.com:465?pool=true&service=gmail",
location: "",
Expand All @@ -224,6 +246,8 @@ test("return invalid smtpConnectionUri credentials with invalid separator", () =

test("correctly detects SendGrid SMTP URI", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri: "smtps://[email protected]:465",
location: "",
mailCollection: "",
Expand All @@ -234,6 +258,8 @@ test("correctly detects SendGrid SMTP URI", () => {
expect(isSendGrid(config)).toBe(true);

const invalidConfig: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri: "smtps://[email protected]:465",
location: "",
mailCollection: "",
Expand All @@ -246,6 +272,8 @@ test("correctly detects SendGrid SMTP URI", () => {

test("correctly uses oAuth credentials when provided", () => {
const config: Config = {
database: "fake-database",
databaseRegion: "us-central1",
smtpConnectionUri:
"smtps://[email protected]:[email protected]:465",
location: "",
Expand Down
Loading
Loading