diff --git a/packages/backend/package.json b/packages/backend/package.json index e4bc0c0c..be09a6e1 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -27,6 +27,7 @@ "http-errors": "~1.6.3", "knex": "^0.95.11", "morgan": "^1.10.0", + "nodemailer": "6.7.0", "objection": "^2.2.17", "pg": "^8.7.1", "twitch-js": "2.0.0-beta.42", @@ -62,6 +63,7 @@ "@types/http-errors": "^1.8.1", "@types/morgan": "^1.9.3", "@types/node": "^16.10.2", + "@types/nodemailer": "^6.4.4", "@types/pg": "^8.6.1", "ava": "^3.15.0", "nodemon": "^2.0.13", diff --git a/packages/backend/src/apps/smtp/assets/favicon.svg b/packages/backend/src/apps/smtp/assets/favicon.svg new file mode 100644 index 00000000..44b0edb4 --- /dev/null +++ b/packages/backend/src/apps/smtp/assets/favicon.svg @@ -0,0 +1,6 @@ + diff --git a/packages/backend/src/apps/smtp/index.ts b/packages/backend/src/apps/smtp/index.ts new file mode 100644 index 00000000..5e65587b --- /dev/null +++ b/packages/backend/src/apps/smtp/index.ts @@ -0,0 +1,40 @@ +import nodemailer from 'nodemailer'; +import App from '../../models/app'; + +export default class SMTP { + client: any + connectionData: any + appData: any + + constructor(connectionData: any) { + this.client = nodemailer.createTransport({ + host: connectionData.host, + port: connectionData.port, + secure: connectionData.useTls, + auth: { + user: connectionData.username, + pass: connectionData.password, + }, + }); + + this.connectionData = connectionData; + this.appData = App.findOneByKey('smtp'); + } + + async verifyCredentials() { + await this.client.verify() + + return { + screenName: this.connectionData.username + } + } + + async isStillVerified() { + try { + await this.client.verify() + return true; + } catch(error) { + return false + } + } +} diff --git a/packages/backend/src/apps/smtp/info.json b/packages/backend/src/apps/smtp/info.json new file mode 100644 index 00000000..aac1358f --- /dev/null +++ b/packages/backend/src/apps/smtp/info.json @@ -0,0 +1,200 @@ +{ + "name": "SMTP", + "key": "smtp", + "iconUrl": "{BASE_URL}/apps/smtp/assets/favicon.svg", + "docUrl": "https://automatisch.io/docs/smtp", + "primaryColor": "2DAAE1", + "fields": [ + { + "key": "host", + "label": "Host", + "type": "string", + "required": true, + "readOnly": false, + "value": null, + "placeholder": null, + "description": "The host information Automatisch will connect to.", + "docUrl": "https://automatisch.io/docs/smtp#host", + "clickToCopy": false + }, + { + "key": "username", + "label": "Email/Username", + "type": "string", + "required": true, + "readOnly": false, + "value": null, + "placeholder": null, + "description": "Your SMTP login credentials.", + "docUrl": "https://automatisch.io/docs/smtp#username", + "clickToCopy": false + }, + { + "key": "password", + "label": "Password", + "type": "string", + "required": true, + "readOnly": false, + "value": null, + "placeholder": null, + "description": null, + "docUrl": "https://automatisch.io/docs/smtp#password", + "clickToCopy": false + }, + { + "key": "useTls", + "label": "Use TLS?", + "type": "boolean", + "required": false, + "readOnly": false, + "value": false, + "placeholder": null, + "description": null, + "docUrl": "https://automatisch.io/docs/smtp#use-tls", + "clickToCopy": false + }, + { + "key": "port", + "label": "Port", + "type": "integer", + "required": false, + "readOnly": false, + "value": 25, + "placeholder": null, + "description": null, + "docUrl": "https://automatisch.io/docs/smtp#port", + "clickToCopy": false + }, + { + "key": "fromEmail", + "label": "From Email", + "type": "string", + "required": false, + "readOnly": false, + "value": null, + "placeholder": null, + "description": null, + "docUrl": "https://automatisch.io/docs/smtp#from-email", + "clickToCopy": false + } + ], + "authenticationSteps": [ + { + "step": 1, + "type": "mutation", + "name": "createConnection", + "fields": [ + { + "name": "key", + "value": "{key}" + }, + { + "name": "data", + "value": null, + "fields": [ + { + "name": "host", + "value": "{fields.host}" + }, + { + "name": "username", + "value": "{fields.username}" + }, + { + "name": "password", + "value": "{fields.password}" + }, + { + "name": "useTLS", + "value": "{fields.useTls}" + }, + { + "name": "port", + "value": "{fields.port}" + }, + { + "name": "fromEmail", + "value": "{fields.fromEmail}" + } + ] + } + ] + }, + { + "step": 2, + "type": "mutation", + "name": "verifyConnection", + "fields": [ + { + "name": "id", + "value": "{createConnection.id}" + } + ] + } + ], + "reconnectionSteps": [ + { + "step": 1, + "type": "mutation", + "name": "resetConnection", + "fields": [ + { + "name": "id", + "value": "{connection.id}" + } + ] + }, + { + "step": 2, + "type": "mutation", + "name": "updateConnection", + "fields": [ + { + "name": "id", + "value": "{connection.id}" + }, + { + "name": "data", + "value": null, + "fields": [ + { + "name": "host", + "value": "{fields.host}" + }, + { + "name": "username", + "value": "{fields.username}" + }, + { + "name": "password", + "value": "{fields.password}" + }, + { + "name": "useTLS", + "value": "{fields.useTls}" + }, + { + "name": "port", + "value": "{fields.port}" + }, + { + "name": "fromEmail", + "value": "{fields.fromEmail}" + } + ] + } + ] + }, + { + "step": 3, + "type": "mutation", + "name": "verifyConnection", + "fields": [ + { + "name": "id", + "value": "{connection.id}" + } + ] + } + ] +} diff --git a/packages/backend/src/graphql/mutations/verify-connection.ts b/packages/backend/src/graphql/mutations/verify-connection.ts index 09e5e9df..ef2dae01 100644 --- a/packages/backend/src/graphql/mutations/verify-connection.ts +++ b/packages/backend/src/graphql/mutations/verify-connection.ts @@ -18,7 +18,10 @@ const verifyConnectionResolver = async (params: Params, req: RequestWithCurrentU const verifiedCredentials = await appInstance.verifyCredentials(); connection = await connection.$query().patchAndFetch({ - data: verifiedCredentials, + data: { + ...connection.data, + ...verifiedCredentials + }, verified: true }) diff --git a/yarn.lock b/yarn.lock index afc3d8de..bb3997e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3180,6 +3180,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.33.tgz#24927446e8b7669d10abacedd16077359678f436" integrity sha512-5XmYX2GECSa+CxMYaFsr2mrql71Q4EvHjKS+ox/SiwSdaASMoBIWE6UmZqFO+VX1jIcsYLStI4FFoB6V7FeIYw== +"@types/nodemailer@^6.4.4": + version "6.4.4" + resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.4.tgz#c265f7e7a51df587597b3a49a023acaf0c741f4b" + integrity sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw== + dependencies: + "@types/node" "*" + "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" @@ -11099,6 +11106,11 @@ node-releases@^2.0.0: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.0.tgz#67dc74903100a7deb044037b8a2e5f453bb05400" integrity sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA== +nodemailer@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.0.tgz#86614722c4e0c33d1b5b02aecb90d6d629932b0d" + integrity sha512-AtiTVUFHLiiDnMQ43zi0YgkzHOEWUkhDgPlBXrsDzJiJvB29Alo4OKxHQ0ugF3gRqRQIneCLtZU3yiUo7pItZw== + nodemon@^2.0.13: version "2.0.13" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.13.tgz#67d40d3a4d5bd840aa785c56587269cfcf5d24aa"