提交 fa02b35acb8d752a8278c6e66c9d7367cb575f06

作者 Nick Baugh
1 个父辈 66451189

added email component

... ... @@ -165,6 +165,7 @@ app.listen(settings.port, function() {
165 165
166 166 ## Components
167 167
  168 +* [email](#email)
168 169 * [error-handler](#error-handler)
169 170 * [knex](#knex)
170 171 * [logger](#logger)
... ... @@ -175,6 +176,31 @@ app.listen(settings.port, function() {
175 176 * [settings](#settings)
176 177 * [update-notifier](#update-notifier)
177 178
  179 +### email
  180 +
  181 +> Returns a function which accepts templateName, locals, headers, transport, and callback arguments. This component uses
  182 +
  183 +[View source](lib/boot/email)
  184 +
  185 +```js
  186 +// example - email
  187 +
  188 +// TODO: finish this!
  189 +
  190 +// mention that transport defaults to settings.email.transport
  191 +
  192 +// mention that headers inherits settings.email.headers
  193 +
  194 +// but only if you don't set `headers.useDefaults: false`
  195 +
  196 +// note that is also uses `settings.email.templates` object
  197 +// which can have `dir` string and `options` object for node email-templates pkg
  198 +
  199 +// also document about having `transport` of `settings.email.transport` be an
  200 +// actual transporter already pre-created (possibly with plugins like html-to-text)
  201 +
  202 +```
  203 +
178 204 ### error-handler
179 205
180 206 > Returns [Express][express] route middleware for error handling.
... ...
  1 +
  2 +// # boot - email
  3 +
  4 +var nodemailer = require('nodemailer')
  5 +var emailTemplates = require('email-templates')
  6 +var _ = require('underscore')
  7 +
  8 +exports = module.exports = function(settings) {
  9 +
  10 + // check to make sure we defined a default email object
  11 + if (!_.isObject(settings.email))
  12 + throw new Error('Settings did not have an `email` object')
  13 +
  14 + // check to make sure settings.email.templates is defined
  15 + if (!_.isObject(settings.email.templates))
  16 + throw new Error('Settings did not have a `settings.email.templates` object')
  17 +
  18 + // check to make sure settings.email.templates.dir is defined
  19 + if (!_.isString(settings.email.templates.dir))
  20 + throw new Error('Settings did not have a `settings.email.templates.dir` string')
  21 +
  22 + var templateName, locals, headers, callback, transporter
  23 +
  24 + function renderTemplate(_templateName, _locals, _headers, transport, _callback) {
  25 +
  26 + templateName = _templateName
  27 + locals = _locals
  28 + headers = _headers
  29 + callback = _callback
  30 +
  31 + // add ability to override default transport defined in settings
  32 + if (_.isFunction(transport)) {
  33 +
  34 + // check to make sure we defined a default transport object
  35 + if (!_.isObject(settings.email.transport))
  36 + throw new Error('Settings did not have an `email.transport` object')
  37 +
  38 + callback = transport
  39 +
  40 + //
  41 + // if the transport defined in settings is an actual transport
  42 + // (as opposed to just a config object) then we need to use that
  43 + // instead of creating a transport - to do so we'll look for the
  44 + // `.transporter` property that gets added to all transport objects
  45 + // <https://github.com/andris9/Nodemailer/blob/master/src/nodemailer.js#L39>
  46 + //
  47 + // the reason we have this support added is in case users add plugins to
  48 + // their transporter, for example the `nodemailer-html-to-text` plugin
  49 + // <https://github.com/andris9/nodemailer-html-to-text>
  50 + //
  51 + if (_.has(settings.email.transport, 'transporter'))
  52 + transporter = settings.email.transport
  53 + else
  54 + transporter = nodemailer.createTransport(settings.email.transport)
  55 +
  56 + } else {
  57 + transporter = nodemailer.createTransport(transport)
  58 + }
  59 +
  60 + if (_.isObject(settings.email.templates.options))
  61 + return emailTemplates(settings.email.templates.dir, settings.email.templates.options, createTemplate)
  62 +
  63 + emailTemplates(settings.email.templates.dir, createTemplate)
  64 +
  65 + }
  66 +
  67 + function createTemplate(err, template) {
  68 + if (err) throw err
  69 + template(templateName, locals, createEmail(headers))
  70 + }
  71 +
  72 + function createEmail(headers) {
  73 + return function(err, html, text) {
  74 + if (err) return callback(err)
  75 + // if we defined a default headers object, then inherit it here
  76 + // but only if we didn't set `useDefaults` to false in the headers
  77 + if (_.isObject(settings.email.headers) && !headers.useDefaults)
  78 + headers = _.defaults(headers, settings.email.headers)
  79 + if (_.isString(html))
  80 + headers.html = html
  81 + if (_.isString(text))
  82 + headers.text = text
  83 + transporter.sendMail(headers, callback)
  84 + }
  85 + }
  86 +
  87 + return renderTemplate
  88 +
  89 +}
  90 +
  91 +exports['@singleton'] = true
  92 +exports['@require'] = [ 'igloo/settings' ]
... ...
... ... @@ -53,9 +53,28 @@ exports = module.exports = function(settings) {
53 53 transports: transports
54 54 })
55 55
  56 + if (settings.server.env === 'development')
  57 + logger = expandErrors(logger)
56 58
57 59 return logger
58 60
  61 + // Extend a winston by making it expand errors when passed in as the
  62 + // second argument (the first argument is the log level).
  63 + // <https://gist.github.com/johndgiese/59bd96360ce411042294>
  64 + // <https://gist.github.com/getvega/6211610>
  65 + function expandErrors(logger) {
  66 + var oldLogFunc = logger.log
  67 + logger.log = function() {
  68 + var args = Array.prototype.slice.call(arguments, 0)
  69 + if (args.length >= 2 && args[1] instanceof Error) {
  70 + args[1] = args[1].stack
  71 + }
  72 + return oldLogFunc.apply(this, args)
  73 + };
  74 + return logger
  75 + }
  76 +
  77 +
59 78 }
60 79
61 80 exports['@singleton'] = true
... ...
... ... @@ -5,20 +5,24 @@ var _ = require('underscore')
5 5 var util = require('util')
6 6 var mergeDefaults = require('merge-defaults')
7 7
8   -exports = module.exports = function(config, local) {
  8 +exports = module.exports = function(IoC, config) {
9 9
10 10 var settings = {}
11 11
12 12 var env = process.env.NODE_ENV || 'development'
13 13
14   - if (!_.isObject(local))
15   - local = {}
16   -
17   - mergeDefaults(config, local)
18   -
19 14 if (!_.isObject(config[env]))
20 15 throw new Error(util.format('Unknown environment %s', env))
21 16
  17 + if (env === 'development') {
  18 + try {
  19 + var local = IoC.create('local')
  20 + if (_.isObject(local))
  21 + mergeDefaults(settings, local)
  22 + } catch(e) {
  23 + }
  24 + }
  25 +
22 26 mergeDefaults(settings, config[env], config.defaults)
23 27
24 28 return settings
... ... @@ -26,13 +30,4 @@ exports = module.exports = function(config, local) {
26 30 }
27 31
28 32 exports['@singleton'] = true
29   -exports['@require'] = ['config']
30   -
31   -var fs = require('fs')
32   -var path = require('path')
33   -var localPath = path.join(__dirname, '..', '..', '..', '..' ,'boot', 'local.js')
34   -
35   -// Include local.js if it exists at boot/local.js
36   -if (fs.existsSync(localPath)) {
37   - exports['@require'].push('local')
38   -}
  33 +exports['@require'] = [ '$container', 'config' ]
... ...
... ... @@ -32,8 +32,10 @@
32 32 "chalk": "^0.4.0",
33 33 "commander": "^2.2.0",
34 34 "connect-redis": "~2.0.0",
  35 + "email-templates": "^1.1.2",
35 36 "express-session": "^1.2.1",
36 37 "merge-defaults": "^0.1.0",
  38 + "nodemailer": "^1.3.0",
37 39 "to-camel-case": "^0.2.1",
38 40 "underscore": "^1.6.0",
39 41 "update-notifier": "^0.2.0",
... ...
注册登录 后发表评论