-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from pdroll/switch-to-mailgun-dot-js
Move to mailgun.js, complete test suite, modernize code base
- Loading branch information
Showing
17 changed files
with
1,754 additions
and
840 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
let data = {}; | ||
|
||
const getPassword = jest.fn(async (name, key) => ( | ||
(data[name] && data[name][key]) ? data[name][key] : null)); | ||
|
||
const setPassword = jest.fn(async (name, key, value) => { | ||
data[name] = data[name] || {}; | ||
data[name][key] = value; | ||
}); | ||
|
||
const deletePassword = jest.fn(async (name, key) => { | ||
if (!getPassword(name, key)) { | ||
return false; | ||
} | ||
|
||
delete data[name][key]; | ||
|
||
return true; | ||
}); | ||
|
||
const clearMockData = () => { | ||
data = {}; | ||
}; | ||
|
||
module.exports = { | ||
getPassword, setPassword, deletePassword, clearMockData, | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
const faker = require('faker'); | ||
|
||
function mailgunClientMock({ key, username }) { | ||
this.apiKey = key; | ||
this.username = username; | ||
|
||
this.messages = { | ||
create: jest.fn(async () => { | ||
if (this.apiKey === 'FAIL_UNAUTHORIZED') { | ||
const e = new Error(); | ||
e.status = 401; | ||
throw e; | ||
} | ||
|
||
if (this.apiKey === 'FAIL_NETWORK') { | ||
const e = new Error(); | ||
e.type = 'EUNAVAILABLE'; | ||
throw e; | ||
} | ||
|
||
if (this.apiKey === 'FAIL_OTHER') { | ||
throw new Error('Failed'); | ||
} | ||
|
||
return { | ||
id: faker.random.uuid(), | ||
message: 'Queued. Thank you.', | ||
}; | ||
}), | ||
}; | ||
|
||
return this; | ||
} | ||
|
||
module.exports = { client: mailgunClientMock }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`help option prints help text 1`] = ` | ||
"Usage: mailgun-send [options] | ||
You will be prompted to enter your Mailgun API Key [https://app.mailgun.com/app/account/security/api_keys] and Domain [https://app.mailgun.com/app/sending/domains/] on your first use. | ||
Options: | ||
-V, --version output the version number | ||
-s, --subject <value> Subject of Email | ||
-t, --to <value> Email address of recipient of email | ||
-f, --from <value> Email address of email sender | ||
-r, --reply <value> ReplyTo email address. Optional | ||
-c, --cc <value> Email address to CC. Optional | ||
-b, --bcc <value> Email address to BCC. Optional | ||
-T, --text <value> Text to send as body of email. Must specify this or | ||
--htmlpath. | ||
-H, --htmlpath <value> Path to HTML file to send as email. Must specify this | ||
or --text. | ||
-R, --reset Reset Mailgun API key and Domain. You will be | ||
prompted to enter these again. | ||
-v, --verbose Output more detailed information, such as message id | ||
-h, --help display help for command | ||
" | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,29 @@ | ||
#!/usr/bin/env node | ||
const runCli = require('../lib/runCli.js'); | ||
|
||
const { Command } = require('commander'); | ||
const keytar = require('keytar'); | ||
const readlineSync = require('readline-sync'); | ||
const MailgunSend = require('../lib/MailgunSend'); | ||
const packageJson = require('../package.json'); | ||
const { argv } = process; | ||
|
||
const program = new Command(); | ||
// Suppress commander error logging, | ||
// since we're handling them ourselves | ||
global.console.error = () => {}; | ||
|
||
/** | ||
* Configure Program options and parse arguments | ||
*/ | ||
program | ||
.version(packageJson.version) | ||
.usage('[options]') | ||
.description('You will be prompted to enter your Mailgun API Key [https://mailgun.com/app/account/security] and Domain [https://mailgun.com/app/domains] on your first use.') | ||
.option('-s, --subject <value>', 'Subject of Email') | ||
.option('-t, --to <value>', 'Email address of recipient of email') | ||
.option('-f, --from <value>', 'Email address of email sender') | ||
.option('-r, --reply <value>', 'ReplyTo email address. Optional') | ||
.option('-c, --cc <value>', 'Email address to CC. Optional') | ||
.option('-b, --bcc <value>', 'Email address to BCC. Optional') | ||
.option('-T, --text <value>', 'Text to send as body of email. Must specify this or --htmlpath.') | ||
.option('-H, --htmlpath <value>', 'Path to HTML file to send as email. Must specify this or --text.') | ||
.option('-R, --reset', 'Reset Mailgun API key and Domain. You will be prompted to enter these again.') | ||
.parse(process.argv); | ||
|
||
(async () => { | ||
/** | ||
* Get/Set Mailgun creds from keychain. | ||
* Prompt user for them if they are not found. | ||
*/ | ||
if (program.reset) { | ||
await keytar.deletePassword(packageJson.name, 'apiKey'); | ||
await keytar.deletePassword(packageJson.name, 'domain'); | ||
const exitOverride = (e) => { | ||
// Don't treat help or version commands as errors | ||
if (['commander.helpDisplayed', 'commander.version'].includes(e.code)) { | ||
process.exit(0); | ||
} | ||
|
||
let apiKey = await keytar.getPassword(packageJson.name, 'apiKey'); | ||
let domain = await keytar.getPassword(packageJson.name, 'domain'); | ||
throw new Error(e.message); | ||
}; | ||
|
||
if (!domain) { | ||
domain = readlineSync.question('Mailgun Domain (e.g. mg.example.com): '); | ||
await keytar.setPassword(packageJson.name, 'domain', domain); | ||
} | ||
|
||
if (!apiKey) { | ||
apiKey = readlineSync.question('Mailgun API (e.g. key-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX): ', { | ||
hideEchoBack: true, | ||
}); | ||
await keytar.setPassword(packageJson.name, 'apiKey', apiKey); | ||
} | ||
|
||
/** | ||
* Attempt to send email | ||
*/ | ||
const mg = new MailgunSend({ apiKey, domain }); | ||
|
||
mg.send({ | ||
subject: program.subject, | ||
to: program.to, | ||
from: program.from, | ||
reply: program.reply, | ||
cc: program.cc, | ||
bcc: program.bcc, | ||
text: program.text, | ||
htmlpath: program.htmlpath, | ||
}).then((msg) => { | ||
(async () => { | ||
try { | ||
const msg = await runCli({ argv, exitOverride }); | ||
console.log(`\n✅ Success!\n\t${msg}`); | ||
}).catch((e) => { | ||
} catch (e) { | ||
// Remove extraneous 'Error:' if present | ||
const errMsg = `${e}`.replace('Error:', ''); | ||
const errMsg = `${e.message || e}`.replace(/error:/i, ''); | ||
console.log(`\n🚨 Error:${errMsg}\n`); | ||
}); | ||
process.exit(1); | ||
} | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
const path = require('path'); | ||
const { exec } = require('child_process'); | ||
const { version } = require('../package.json'); | ||
|
||
const cli = (args) => new Promise((resolve) => { | ||
exec(`node ${path.resolve('bin/mailgun-send.js')} ${args.join(' ')}`, | ||
{ cwd: '.' }, | ||
(error, stdout, stderr) => { | ||
resolve({ | ||
code: error && error.code ? error.code : 0, | ||
error, | ||
stdout, | ||
stderr, | ||
}); | ||
}); | ||
}); | ||
|
||
describe('help option', () => { | ||
it('returns a zero code', async () => { | ||
const result = await cli(['-h']); | ||
|
||
expect(result.code).toBe(0); | ||
}); | ||
|
||
it('prints help text', async () => { | ||
const result = await cli(['-h']); | ||
|
||
expect(result.stdout).toMatchSnapshot(); | ||
}); | ||
}); | ||
|
||
describe('version option', () => { | ||
it('returns a zero code', async () => { | ||
const result = await cli(['-V']); | ||
|
||
expect(result.code).toBe(0); | ||
}); | ||
|
||
it('prints the version from the package.json file', async () => { | ||
const result = await cli(['-V']); | ||
|
||
expect(result.stdout).toMatch(version); | ||
}); | ||
}); | ||
|
||
describe('error handling', () => { | ||
it('returns error code of 1', async () => { | ||
const result = await cli(['-t']); | ||
expect(result.code).toBe(1); | ||
}); | ||
|
||
it('prints a friendly error message for commander errors', async () => { | ||
const result = await cli(['-W']); | ||
expect(result.stdout).toMatch(/🚨 {2}Error:/); | ||
expect(result.stdout).toMatch(/unknown option/i); | ||
}); | ||
}); |
Oops, something went wrong.