Added function to send email for invoice #3
							
								
								
									
										10
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| { | ||||
|     "configurations": [ | ||||
|         { | ||||
|             "type": "node", | ||||
|             "request": "attach", | ||||
|             "name": "Debug", | ||||
|             "port": 9229 | ||||
|         } | ||||
|     ] | ||||
| } | ||||
							
								
								
									
										237
									
								
								functions/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										237
									
								
								functions/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -8,15 +8,21 @@ | ||||
|       "name": "functions", | ||||
|       "version": "0.0.0", | ||||
|       "dependencies": { | ||||
|         "@types/node-fetch": "^2.6.12", | ||||
|         "axios": "^1.8.4", | ||||
|         "firebase-admin": "^12.6.0", | ||||
|         "firebase-functions": "^6.0.1", | ||||
|         "form-data": "^4.0.1", | ||||
|         "html-to-text": "^9.0.5", | ||||
|         "long": "4.0.0", | ||||
|         "long": "^4.0.0", | ||||
|         "mailgun.js": "^10.4.0", | ||||
|         "node-fetch": "^2.7.0", | ||||
|         "pdfjs-dist": "^5.0.375", | ||||
|         "twilio": "^5.4.0" | ||||
|       }, | ||||
|       "devDependencies": { | ||||
|         "@types/long": "^5.0.0", | ||||
|         "@types/node": "^22.13.14", | ||||
|         "firebase-functions-test": "^3.1.0", | ||||
|         "typescript": "^5.8.2" | ||||
|       }, | ||||
| @ -1156,6 +1162,177 @@ | ||||
|         "url": "https://opencollective.com/js-sdsl" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.68.tgz", | ||||
|       "integrity": "sha512-LQESrePLEBLvhuFkXx9jjBXRC2ClYsO5mqQ1m/puth5z9SOuM3N/B3vDuqnC3RJFktDktyK9khGvo7dTkqO9uQ==", | ||||
|       "optional": true, | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       }, | ||||
|       "optionalDependencies": { | ||||
|         "@napi-rs/canvas-android-arm64": "0.1.68", | ||||
|         "@napi-rs/canvas-darwin-arm64": "0.1.68", | ||||
|         "@napi-rs/canvas-darwin-x64": "0.1.68", | ||||
|         "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.68", | ||||
|         "@napi-rs/canvas-linux-arm64-gnu": "0.1.68", | ||||
|         "@napi-rs/canvas-linux-arm64-musl": "0.1.68", | ||||
|         "@napi-rs/canvas-linux-riscv64-gnu": "0.1.68", | ||||
|         "@napi-rs/canvas-linux-x64-gnu": "0.1.68", | ||||
|         "@napi-rs/canvas-linux-x64-musl": "0.1.68", | ||||
|         "@napi-rs/canvas-win32-x64-msvc": "0.1.68" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-android-arm64": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.68.tgz", | ||||
|       "integrity": "sha512-h1KcSR4LKLfRfzeBH65xMxbWOGa1OtMFQbCMVlxPCkN1Zr+2gK+70pXO5ktojIYcUrP6KDcOwoc8clho5ccM/w==", | ||||
|       "cpu": [ | ||||
|         "arm64" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "android" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-darwin-arm64": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.68.tgz", | ||||
|       "integrity": "sha512-/VURlrAD4gDoxW1GT/b0nP3fRz/fhxmHI/xznTq2FTwkQLPOlLkDLCvTmQ7v6LtGKdc2Ed6rvYpRan+JXThInQ==", | ||||
|       "cpu": [ | ||||
|         "arm64" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "darwin" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-darwin-x64": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.68.tgz", | ||||
|       "integrity": "sha512-tEpvGR6vCLTo1Tx9wmDnoOKROpw57wiCWwCpDOuVlj/7rqEJOUYr9ixW4aRJgmeGBrZHgevI0EURys2ER6whmg==", | ||||
|       "cpu": [ | ||||
|         "x64" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "darwin" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.68.tgz", | ||||
|       "integrity": "sha512-U9xbJsumPOiAYeAFZMlHf62b9dGs2HJ6Q5xt7xTB0uEyPeurwhgYBWGgabdsEidyj38YuzI/c3LGBbSQB3vagw==", | ||||
|       "cpu": [ | ||||
|         "arm" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "linux" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-linux-arm64-gnu": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.68.tgz", | ||||
|       "integrity": "sha512-KFkn8wEm3mPnWD4l8+OUUkxylSJuN5q9PnJRZJgv15RtCA1bgxIwTkBhI/+xuyVMcHqON9sXq7cDkEJtHm35dg==", | ||||
|       "cpu": [ | ||||
|         "arm64" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "linux" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-linux-arm64-musl": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.68.tgz", | ||||
|       "integrity": "sha512-IQzts91rCdOALXBWQxLZRCEDrfFTGDtNRJMNu+2SKZ1uT8cmPQkPwVk5rycvFpvgAcmiFiOSCp1aRrlfU8KPpQ==", | ||||
|       "cpu": [ | ||||
|         "arm64" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "linux" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.68.tgz", | ||||
|       "integrity": "sha512-e9AS5UttoIKqXSmBzKZdd3NErSVyOEYzJfNOCGtafGk1//gibTwQXGlSXmAKuErqMp09pyk9aqQRSYzm1AQfBw==", | ||||
|       "cpu": [ | ||||
|         "riscv64" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "linux" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-linux-x64-gnu": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.68.tgz", | ||||
|       "integrity": "sha512-Pa/I36VE3j57I3Obhrr+J48KGFfkZk2cJN/2NmW/vCgmoF7kCP6aTVq5n+cGdGWLd/cN9CJ9JvNwEoMRDghu0g==", | ||||
|       "cpu": [ | ||||
|         "x64" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "linux" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-linux-x64-musl": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.68.tgz", | ||||
|       "integrity": "sha512-9c6rkc5195wNxuUHJdf4/mmnq433OQey9TNvQ9LspJazvHbfSkTij8wtKjASVQsJyPDva4fkWOeV/OQ7cLw0GQ==", | ||||
|       "cpu": [ | ||||
|         "x64" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "linux" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@napi-rs/canvas-win32-x64-msvc": { | ||||
|       "version": "0.1.68", | ||||
|       "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.68.tgz", | ||||
|       "integrity": "sha512-Fc5Dez23u0FoSATurT6/w1oMytiRnKWEinHivdMvXpge6nG4YvhrASrtqMk8dGJMVQpHr8QJYF45rOrx2YU2Aw==", | ||||
|       "cpu": [ | ||||
|         "x64" | ||||
|       ], | ||||
|       "optional": true, | ||||
|       "os": [ | ||||
|         "win32" | ||||
|       ], | ||||
|       "engines": { | ||||
|         "node": ">= 10" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@opentelemetry/api": { | ||||
|       "version": "1.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", | ||||
| @ -1423,10 +1600,14 @@ | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/@types/long": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", | ||||
|       "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", | ||||
|       "optional": true | ||||
|       "version": "5.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@types/long/-/long-5.0.0.tgz", | ||||
|       "integrity": "sha512-eQs9RsucA/LNjnMoJvWG/nXa7Pot/RbBzilF/QRIU/xRl+0ApxrSUFsV5lmf01SvSlqMzJ7Zwxe440wmz2SJGA==", | ||||
|       "deprecated": "This is a stub types definition. long provides its own type definitions, so you do not need this installed.", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "long": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/mime": { | ||||
|       "version": "1.3.5", | ||||
| @ -1439,13 +1620,22 @@ | ||||
|       "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" | ||||
|     }, | ||||
|     "node_modules/@types/node": { | ||||
|       "version": "22.13.10", | ||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", | ||||
|       "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", | ||||
|       "version": "22.13.14", | ||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", | ||||
|       "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", | ||||
|       "dependencies": { | ||||
|         "undici-types": "~6.20.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/node-fetch": { | ||||
|       "version": "2.6.12", | ||||
|       "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", | ||||
|       "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", | ||||
|       "dependencies": { | ||||
|         "@types/node": "*", | ||||
|         "form-data": "^4.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/qs": { | ||||
|       "version": "6.9.18", | ||||
|       "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", | ||||
| @ -1659,9 +1849,9 @@ | ||||
|       "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" | ||||
|     }, | ||||
|     "node_modules/axios": { | ||||
|       "version": "1.8.3", | ||||
|       "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", | ||||
|       "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", | ||||
|       "version": "1.8.4", | ||||
|       "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", | ||||
|       "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", | ||||
|       "dependencies": { | ||||
|         "follow-redirects": "^1.15.6", | ||||
|         "form-data": "^4.0.0", | ||||
| @ -3085,6 +3275,12 @@ | ||||
|         "node": ">=14" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/google-gax/node_modules/@types/long": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", | ||||
|       "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "node_modules/google-gax/node_modules/uuid": { | ||||
|       "version": "9.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", | ||||
| @ -4710,7 +4906,6 @@ | ||||
|       "version": "2.7.0", | ||||
|       "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", | ||||
|       "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", | ||||
|       "optional": true, | ||||
|       "dependencies": { | ||||
|         "whatwg-url": "^5.0.0" | ||||
|       }, | ||||
| @ -4970,6 +5165,17 @@ | ||||
|       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", | ||||
|       "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" | ||||
|     }, | ||||
|     "node_modules/pdfjs-dist": { | ||||
|       "version": "5.0.375", | ||||
|       "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.0.375.tgz", | ||||
|       "integrity": "sha512-QDRlEVldf/cX88CElGAyRhjqNOO69kmB3HZlalDAfqJ/IvmqJNkipomhBZy4cWATfLVlkQTXE3H4yFvMF2uPsg==", | ||||
|       "engines": { | ||||
|         "node": ">=20" | ||||
|       }, | ||||
|       "optionalDependencies": { | ||||
|         "@napi-rs/canvas": "^0.1.67" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/peberminta": { | ||||
|       "version": "0.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", | ||||
| @ -5824,8 +6030,7 @@ | ||||
|     "node_modules/tr46": { | ||||
|       "version": "0.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", | ||||
|       "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", | ||||
|       "optional": true | ||||
|       "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" | ||||
|     }, | ||||
|     "node_modules/ts-deepmerge": { | ||||
|       "version": "2.0.7", | ||||
| @ -6058,8 +6263,7 @@ | ||||
|     "node_modules/webidl-conversions": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", | ||||
|       "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", | ||||
|       "optional": true | ||||
|       "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" | ||||
|     }, | ||||
|     "node_modules/websocket-driver": { | ||||
|       "version": "0.7.4", | ||||
| @ -6086,7 +6290,6 @@ | ||||
|       "version": "5.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", | ||||
|       "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", | ||||
|       "optional": true, | ||||
|       "dependencies": { | ||||
|         "tr46": "~0.0.3", | ||||
|         "webidl-conversions": "^3.0.0" | ||||
|  | ||||
| @ -15,15 +15,21 @@ | ||||
|   }, | ||||
|   "main": "lib/index.js", | ||||
|   "dependencies": { | ||||
|     "@types/node-fetch": "^2.6.12", | ||||
|     "axios": "^1.8.4", | ||||
|     "firebase-admin": "^12.6.0", | ||||
|     "firebase-functions": "^6.0.1", | ||||
|     "form-data": "^4.0.1", | ||||
|     "html-to-text": "^9.0.5", | ||||
|     "long": "4.0.0", | ||||
|     "long": "^4.0.0", | ||||
|     "mailgun.js": "^10.4.0", | ||||
|     "node-fetch": "^2.7.0", | ||||
|     "pdfjs-dist": "^5.0.375", | ||||
|     "twilio": "^5.4.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@types/long": "^5.0.0", | ||||
|     "@types/node": "^22.13.14", | ||||
|     "firebase-functions-test": "^3.1.0", | ||||
|     "typescript": "^5.8.2" | ||||
|   }, | ||||
|  | ||||
| @ -4,12 +4,79 @@ import * as admin from 'firebase-admin'; | ||||
| import * as express from "express"; | ||||
| import * as logger from "firebase-functions/logger"; | ||||
| import { onDocumentCreated } from "firebase-functions/firestore"; | ||||
| 
 | ||||
| import * as os from 'os'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import * as https from 'https'; | ||||
| const formData = require('form-data'); | ||||
| const Mailgun = require('mailgun.js'); | ||||
| const { convert } = require('html-to-text'); | ||||
| const twilio = require('twilio') | ||||
| const twilio = require('twilio'); | ||||
| 
 | ||||
| 
 | ||||
| if (!admin.apps.length) { | ||||
|   admin.initializeApp(); | ||||
| } | ||||
| export const sendEmailWithAttachment = onRequest({ | ||||
|   region: '#{SERVICES_RGN}#' | ||||
| }, async (request: Request, response: express.Response) => { | ||||
|   try { | ||||
|     const { toAddress, subject, message, fileUrl, fileName } = request.body; | ||||
| 
 | ||||
|     if (!toAddress || !subject || !message || !fileUrl) { | ||||
|       response.status(400).json({ | ||||
|         error: 'Missing required fields (toAddress, subject, message, fileUrl)' | ||||
|       }); | ||||
|       return; | ||||
|     } | ||||
|     const tempFilePath = path.join(os.tmpdir(), fileName || 'attachment.pdf'); | ||||
|     await new Promise<void>((resolve, reject) => { | ||||
|       const file = fs.createWriteStream(tempFilePath); | ||||
|       https.get(fileUrl, (res) => { | ||||
|         res.pipe(file); | ||||
|         file.on('finish', () => { | ||||
|           file.close(); | ||||
|           resolve(); | ||||
|         }); | ||||
|       }).on('error', (err) => { | ||||
|         fs.unlink(tempFilePath, () => { }); | ||||
|         reject(err); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     const mailgun = new Mailgun(formData); | ||||
|     const client = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY }); | ||||
| 
 | ||||
|     const options = { | ||||
|       wordwrap: 130, | ||||
|     }; | ||||
|     const textMessage = convert(message, options); | ||||
|     const fileBuffer = fs.readFileSync(tempFilePath); | ||||
|     const attachmentFilename = fileName || path.basename(fileUrl.split('?')[0]); | ||||
| 
 | ||||
|     const data = { | ||||
|       from: process.env.MAILGUN_FROM_ADDRESS, | ||||
|       to: toAddress, | ||||
|       subject: subject, | ||||
|       text: textMessage, | ||||
|       html: message, | ||||
|       attachment: { | ||||
|         data: fileBuffer, | ||||
|         filename: attachmentFilename, | ||||
|         contentType: 'application/pdf', | ||||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     const result = await client.messages.create(process.env.MAILGUN_SERVER, data); | ||||
|     fs.unlinkSync(tempFilePath); | ||||
| 
 | ||||
|     logger.info('Email with attachment from URL sent successfully'); | ||||
|     response.json({ success: true, result }); | ||||
|   } catch (error) { | ||||
|     logger.error('Error sending email with attachment from URL:', error); | ||||
|     response.status(500).json({ success: false, error: error instanceof Error ? error.message : String(error) }); | ||||
|   } | ||||
| }); | ||||
| export const sendEmailMessage = onRequest({ | ||||
|   region: '#{SERVICES_RGN}#' | ||||
| }, (request: Request, response: express.Response) => { | ||||
| @ -136,3 +203,6 @@ export const notifyInvitation = onDocumentCreated({ | ||||
|     return null; | ||||
|   } | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										72
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | ||||
| { | ||||
|   "name": "fitlien-services", | ||||
|   "lockfileVersion": 3, | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "dependencies": { | ||||
|         "@types/busboy": "^1.5.4", | ||||
|         "busboy": "^1.6.0" | ||||
|       }, | ||||
|       "devDependencies": { | ||||
|         "@types/long": "^5.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/busboy": { | ||||
|       "version": "1.5.4", | ||||
|       "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.4.tgz", | ||||
|       "integrity": "sha512-kG7WrUuAKK0NoyxfQHsVE6j1m01s6kMma64E+OZenQABMQyTJop1DumUWcLwAQ2JzpefU7PDYoRDKl8uZosFjw==", | ||||
|       "dependencies": { | ||||
|         "@types/node": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/long": { | ||||
|       "version": "5.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@types/long/-/long-5.0.0.tgz", | ||||
|       "integrity": "sha512-eQs9RsucA/LNjnMoJvWG/nXa7Pot/RbBzilF/QRIU/xRl+0ApxrSUFsV5lmf01SvSlqMzJ7Zwxe440wmz2SJGA==", | ||||
|       "deprecated": "This is a stub types definition. long provides its own type definitions, so you do not need this installed.", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "long": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/node": { | ||||
|       "version": "22.10.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", | ||||
|       "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", | ||||
|       "dependencies": { | ||||
|         "undici-types": "~6.20.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/busboy": { | ||||
|       "version": "1.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", | ||||
|       "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", | ||||
|       "dependencies": { | ||||
|         "streamsearch": "^1.1.0" | ||||
|       }, | ||||
|       "engines": { | ||||
|         "node": ">=10.16.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/long": { | ||||
|       "version": "5.3.1", | ||||
|       "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", | ||||
|       "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/streamsearch": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", | ||||
|       "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", | ||||
|       "engines": { | ||||
|         "node": ">=10.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/undici-types": { | ||||
|       "version": "6.20.0", | ||||
|       "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", | ||||
|       "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										9
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| { | ||||
|   "dependencies": { | ||||
|     "@types/busboy": "^1.5.4", | ||||
|     "busboy": "^1.6.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@types/long": "^5.0.0" | ||||
|   } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user