diff --git a/package-lock.json b/package-lock.json index a4578bb..0c49c2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2153,6 +2153,16 @@ "which": "^1.3.1" } }, + "@pushrocks/smartsmtp": { + "version": "1.0.6", + "resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartsmtp/-/smartsmtp-1.0.6.tgz", + "integrity": "sha512-W+XyCflolJdzFokSFpFX653+5tYd5vig3K0uFKVNH5wJYSrRr9E/+o2HsjA3L0xXQSnSRCUBtR7gE7C3l6QLhA==", + "requires": { + "@pushrocks/smartmail": "^1.0.18", + "@types/nodemailer": "^6.4.0", + "nodemailer": "^6.4.11" + } + }, "@pushrocks/smartstring": { "version": "3.0.18", "resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartstring/-/smartstring-3.0.18.tgz", @@ -2563,6 +2573,14 @@ "resolved": "https://verdaccio.lossless.one/@types%2fnode/-/node-14.0.27.tgz", "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==" }, + "@types/nodemailer": { + "version": "6.4.0", + "resolved": "https://verdaccio.lossless.one/@types%2fnodemailer/-/nodemailer-6.4.0.tgz", + "integrity": "sha512-KY7bFWB0MahRZvVW4CuW83qcCDny59pJJ0MQ5ifvfcjNwPlIT0vW4uARO4u1gtkYnWdhSvURegecY/tzcukJcA==", + "requires": { + "@types/node": "*" + } + }, "@types/parcel-bundler": { "version": "1.12.1", "resolved": "https://verdaccio.lossless.one/@types%2fparcel-bundler/-/parcel-bundler-1.12.1.tgz", @@ -7909,6 +7927,11 @@ "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", "dev": true }, + "nodemailer": { + "version": "6.4.11", + "resolved": "https://verdaccio.lossless.one/nodemailer/-/nodemailer-6.4.11.tgz", + "integrity": "sha512-BVZBDi+aJV4O38rxsUh164Dk1NCqgh6Cm0rQSb9SK/DHGll/DrCMnycVDD7msJgZCnmVa8ASo8EZzR7jsgTukQ==" + }, "normalize-html-whitespace": { "version": "1.0.0", "resolved": "https://verdaccio.lossless.one/normalize-html-whitespace/-/normalize-html-whitespace-1.0.0.tgz", diff --git a/package.json b/package.json index 784d185..0f7b80b 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@pushrocks/smartfile": "^8.0.0", "@pushrocks/smartmail": "^1.0.18", "@pushrocks/smartrequest": "^1.1.47", + "@pushrocks/smartsmtp": "^1.0.6", "@pushrocks/smartstring": "^3.0.18" }, "files": [ diff --git a/qenv.yml b/qenv.yml index 2ee9002..ec13b75 100644 --- a/qenv.yml +++ b/qenv.yml @@ -1,2 +1,3 @@ required: - - MAILGUN_API_TOKEN \ No newline at end of file + - MAILGUN_API_TOKEN + - MAILGUN_SMTP_CREDENTIALS \ No newline at end of file diff --git a/test/test.ts b/test/test.ts index d51db1d..b7d7d3c 100644 --- a/test/test.ts +++ b/test/test.ts @@ -12,6 +12,7 @@ let testSmartmail: smartmail.Smartmail; tap.test('should create a mailgun account', async () => { testMailgunAccount = new mailgun.MailgunAccount(testQenv.getEnvVarOnDemand('MAILGUN_API_TOKEN')); + testMailgunAccount.addSmtpCredentials(testQenv.getEnvVarOnDemand('MAILGUN_SMTP_CREDENTIALS')); expect(testMailgunAccount).to.be.instanceOf(mailgun.MailgunAccount); }); @@ -21,7 +22,7 @@ tap.test('should create a smartmail', async () => { from: 'Lossless GmbH ', subject: 'TestMessage from @mojoio/mailgun test' }); - return testSmartmail; + expect(testSmartmail).to.be.instanceOf(smartmail.Smartmail); }); tap.test('should send a smartmail', async () => { @@ -31,12 +32,10 @@ tap.test('should send a smartmail', async () => { tap.test('should send a smartmail with empty body', async () => { const emptyBodySmartmail = new smartmail.Smartmail({ body: '', - from: 'Lossless GmbH ', + from: 'Lossless GmbH ', subject: 'A message with no body from @mojoio/mailgun test' }); - console.log('ok'); await testMailgunAccount.sendSmartMail(emptyBodySmartmail, 'Sandbox Team '); - console.log('hey'); }); tap.test('should retrieve a mail using a retrieval url', async () => { diff --git a/ts/mailgun.classes.account.ts b/ts/mailgun.classes.account.ts index 631a27b..bc2593f 100644 --- a/ts/mailgun.classes.account.ts +++ b/ts/mailgun.classes.account.ts @@ -5,10 +5,28 @@ export class MailgunAccount { public baseUrl = 'https://api.mailgun.net/v3'; public apiToken: string; + public smartSmtps: {[domain: string]: plugins.smartsmtp.Smartsmtp} = {}; + constructor(apiTokenArg: string) { this.apiToken = apiTokenArg; } + /** + * allows adding smtp credentials + * Format: [domain]|[username]|[password] + */ + public addSmtpCredentials (credentials: string) { + const credentialArray = credentials.split('|'); + if (credentialArray.length !== 3) { + throw new Error('credentials are in the wrong format'); + } + this.smartSmtps[credentialArray[0]] = new plugins.smartsmtp.Smartsmtp({ + smtpServer: 'smtp.mailgun.org', + smtpUser: credentialArray[1], + smtpPassword: credentialArray[2] + }); + } + public async getRequest(routeArg: string, binaryArg: boolean = false) { let requestUrl = routeArg; const needsBaseUrlPrefix = !routeArg.startsWith('https://'); @@ -18,9 +36,9 @@ export class MailgunAccount { method: 'GET', headers: { Authorization: `Basic ${plugins.smartstring.base64.encode(`api:${this.apiToken}`)}`, - 'Content-Type': 'application/json' + 'Content-Type': 'application/json', }, - keepAlive: false + keepAlive: false, }; let response: plugins.smartrequest.IExtendedIncomingMessage; if (!binaryArg) { @@ -37,9 +55,9 @@ export class MailgunAccount { requestUrl, { headers: { - Authorization: `Basic ${plugins.smartstring.base64.encode(`api:${this.apiToken}`)}` + Authorization: `Basic ${plugins.smartstring.base64.encode(`api:${this.apiToken}`)}`, }, - keepAlive: false + keepAlive: false, }, formFields ); @@ -59,35 +77,25 @@ export class MailgunAccount { { name: 'from', type: 'string', - payload: smartmailArg.options.from + payload: smartmailArg.options.from, }, { name: 'to', type: 'string', - payload: toArg + payload: toArg, }, { name: 'subject', type: 'string', - payload: smartmailArg.getSubject(dataArg) - } + payload: smartmailArg.getSubject(dataArg), + }, + { + name: 'html', + type: 'string', + payload: smartmailArg.getBody(dataArg), + }, ]; - if (smartmailArg.getBody(dataArg)) { - formFields.push({ - name: 'html', - type: 'string', - payload: smartmailArg.getBody(dataArg) - }); - } else { - console.log('message has no body'); - formFields.push({ - name: 'html', - type: 'string', - payload: 'The sender did not provide a bodytext.' - }); - } - console.log(smartmailArg.attachments); for (const attachment of smartmailArg.attachments) { @@ -95,16 +103,29 @@ export class MailgunAccount { name: 'attachment', type: 'Buffer', payload: attachment.contentBuffer, - fileName: attachment.parsedPath.base + fileName: attachment.parsedPath.base, }); } - const response = await this.postFormData(`/${domain}/messages`, formFields); - if (response.statusCode === 200) { - return response.body; + if (smartmailArg.getBody(dataArg)) { + console.log('All requirements for API met'); + const response = await this.postFormData(`/${domain}/messages`, formFields); + if (response.statusCode === 200) { + console.log(`Sent mail with subject ${smartmailArg.getSubject(dataArg)} to ${toArg} using the mailgun API`); + return response.body; + } else { + console.log(response.body); + throw new Error('could not send email'); + } } else { - console.log(response.body); - throw new Error('could not send email'); + console.log('An empty body was provided. This does not work via the API, but using SMTP instead.'); + const wantedSmartsmtp = this.smartSmtps[domain]; + if (!wantedSmartsmtp) { + console.log('did not find appropriate smtp credentials'); + return; + } + wantedSmartsmtp.sendSmartMail(smartmailArg, toArg); + console.log(`Sent mail with subject ${smartmailArg.getSubject(dataArg)} to ${toArg} using an smtp transport over Mailgun`); } } @@ -119,7 +140,7 @@ export class MailgunAccount { from: responseBody.From, body: responseBody['body-html'], subject: responseBody.Subject, - creationObjectRef: responseBody + creationObjectRef: responseBody, }); // lets care about attachments @@ -131,7 +152,7 @@ export class MailgunAccount { new plugins.smartfile.Smartfile({ path: `./${attachmentName}`, base: `./${attachmentName}`, - contentBuffer: attachmentContents.body + contentBuffer: attachmentContents.body, }) ); } diff --git a/ts/mailgun.plugins.ts b/ts/mailgun.plugins.ts index bf2b6c2..ec707e8 100644 --- a/ts/mailgun.plugins.ts +++ b/ts/mailgun.plugins.ts @@ -2,6 +2,7 @@ import * as smartfile from '@pushrocks/smartfile'; import * as smartmail from '@pushrocks/smartmail'; import * as smartrequest from '@pushrocks/smartrequest'; +import * as smartsmtp from '@pushrocks/smartsmtp'; import * as smartstring from '@pushrocks/smartstring'; -export { smartfile, smartmail, smartrequest, smartstring }; +export { smartfile, smartmail, smartrequest, smartsmtp, smartstring };