Skip to content
This repository was archived by the owner on Jan 22, 2021. It is now read-only.

Removed Iron Router dependency #47

Merged
merged 3 commits into from
Dec 24, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -136,7 +136,7 @@ In `Mailer.init`, you're able to provide a key-value object with *template objec
teamMembers: ->
@team.users.map (user) -> Meteor.users.findOne(user)

# For previewing the email in your browser. Behaves like an ordinary Iron Router route.
# For previewing the email in your browser.
route:
path: '/activity/:user'
data: ->
@@ -234,16 +234,22 @@ The built in helpers are:
baseUrl: (path) ->
Utils.joinUrl(Mailer.settings.baseUrl, path)

# `emailUrlFor` takes an Iron Router route (with optional params) and
# `emailUrlFor` takes an Iron Router or Flow Router route (with optional params) and
# creates an absolute URL.
#
# {{ emailUrlFor 'myRoute' param='foo' }} => http://root-domain.com/my-route/foo
emailUrlFor: (route, params) ->
if Router
Utils.joinUrl Mailer.settings.baseUrl, Router.path.call(Router, route, params.hash)

emailUrlFor: (routeName, params) ->
# if Iron Router
if Router?
Utils.joinUrl Mailer.settings.baseUrl, Router.path.call(Router, routeName, params.hash)

# if Flow Router
if FlowRouter?
baseUrl = Utils.joinUrl Mailer.settings.baseUrl, FlowRouter.path.call(FlowRouter, routeName, params.hash)
```

Please note that for Flow Router you need to have your routes defined in a place where the server can see them, in order for the `emailUrlFor` helper to work.

#### The preview line

The *preview line* is the first text content of an email, usually visible in many email clients. That can be used to convey more info beyond the `subject` prop. It's possible to have your preview content in your parent layout but still provide the data from a child template.
@@ -362,9 +368,9 @@ Consult the `html-to-text` [documentation](https://www.npmjs.com/package/html-to

It's also possible to *send* emails to yourself or others for review in a real mail client.

Noticed the `route` property on the template? It uses Iron Router's server side routes under the hood.
Noticed the `route` property on the template? It uses `meteorhacks:picker` server side routes under the hood.

The `route` property expects a `path` property (feel free to use any of Iron Router's fanciness in here) and an optional `data` function providing the data context (an object). The function has access to the same scope as Iron Router's `action` hook, which means you can get a hold of parameters and the whole shebang.
The `route` property expects a `path` property and an optional `data` function providing the data context (an object). The function has access to the parameters of the route.

**Three routes** will be added:

@@ -375,7 +381,7 @@ The `route` property expects a `path` property (feel free to use any of Iron Rou
```
The `/emails` root prefix is configurable in `config` in the `routePrefix` key.

The Iron Router *route names* will be on the format
The *route names* will be on the format

```
[preview|send]Name
@@ -464,6 +470,7 @@ Why not try [`meteor-logger`](https://github.com/lookback/meteor-logger)? :)

## Version history

- `0.7.0` - Replaced Iron Router dependency with `meteorhacks:picker`, which means you can now use this package with Flow Router as well.
- `0.6.2` - Support passing options to `html-to-text` module in `Mailer.config()`.
- `0.6.1`- Fix critical runtime crash when sending emails.
- `0.6.0` - Automatically create and include plain text email version from your HTML templates, using [`html-to-text`](http://npmjs.com/package/html-to-text).
55 changes: 30 additions & 25 deletions emails.coffee
Original file line number Diff line number Diff line change
@@ -57,9 +57,15 @@ Helpers =
# creates an absolute URL.
#
# {{ emailUrlFor 'myRoute' param='foo' }} => http://root-domain.com/my-route/foo
emailUrlFor: (route, params) ->
if Router
Utils.joinUrl Mailer.settings.baseUrl, Router.path.call(Router, route, params.hash)
emailUrlFor: (routeName, params) ->
# if Iron Router
if Router?
Utils.joinUrl Mailer.settings.baseUrl, Router.path.call(Router, routeName, params.hash)

# if Flow Router
if FlowRouter?
baseUrl = Utils.joinUrl Mailer.settings.baseUrl, FlowRouter.path.call(FlowRouter, routeName, params.hash)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to store this in baseUrl here?

I also think we should have a fallback mechanism if the user has neither FlowRouter nor Iron Router installed. Like, doing a logger warning in the console.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ai, that line should be.

 # if Flow Router
if FlowRouter?
   Utils.joinUrl Mailer.settings.baseUrl, FlowRouter.path.call(FlowRouter, routeName, params.hash)

I'll change that. Sure, we can add a fallback mechanism



# # The mailer
#
@@ -258,18 +264,18 @@ MailerClass = (options) ->
# This function adds the `preview` route from a `template` object.
# It will apply the returned data from a `data` function on the
# provided `route` prop from the template.
previewAction = (opts) ->
previewAction = (opts, template, params) ->
check opts,
type: Match.OneOf('html', 'text')

return (template) ->
return (template, params) ->
try
data = template.route.data and template.route.data.apply(this, arguments)
data = template.route.data and template.route.data.call(this, params)
catch ex
msg = 'Exception in '+template.name+' data function: '+ex.message
Utils.Logger.error msg, TAG
@response.writeHead 500
return @response.end msg
@writeHead 500
return @end msg

# Compile, since we wanna refresh markup and CSS inlining.
compile template
@@ -285,21 +291,21 @@ MailerClass = (options) ->
Utils.Logger.error msg, TAG
content = msg

@response.writeHead 200, 'Content-Type': if opts.type is 'html' then 'text/html' else 'text/plain'
@response.end(content, 'utf8')
@writeHead 200, 'Content-Type': if opts.type is 'html' then 'text/html' else 'text/plain'
@end(content, 'utf8')

# This function adds the `send` route, for easy sending emails from
# the browser.
sendAction = (template) ->
sendAction = (template, params) ->
# Who to send to? It depends: it primarly reads from the `?to`
# query param, and secondly from the `testEmail` prop in settings.
to = @params.query.to or settings.testEmail
to = params.query.to or settings.testEmail

Utils.Logger.info "Sending #{template.name} ...", TAG

if to?
try
data = template.route.data and template.route.data.apply(this, arguments)
data = template.route.data and template.route.data.call(this, params)
catch ex
Utils.Logger.error 'Exception in '+template.name+' data function: '+ex.message, TAG
return
@@ -315,17 +321,17 @@ MailerClass = (options) ->
@response.writeHead 500
msg = 'Did not send test email, something went wrong. Check the logs.'
else
@response.writeHead 200
@writeHead 200
# If there's no `MAIL_URL` environment variable, Meteor cannot send
# the email and echoes it out to `STDOUT` instead.
reallySentEmail = !!process.env.MAIL_URL
msg = if reallySentEmail then "Sent test email to #{to}" else "Sent email to STDOUT"

@response.end(msg)
@end(msg)

else
@response.writeHead 400
@response.end("No testEmail provided.")
@writeHead 400
@end("No testEmail provided.")

# Adds all the routes from a template.
addRoutes = (template) ->
@@ -347,18 +353,17 @@ MailerClass = (options) ->
# Also capitalize the first character in the template name for
# the name of the route, so it will look like `previewSample` for a
# template named `sample`.
path = "#{settings.routePrefix}/#{type}" + template.route.path
path = "/#{settings.routePrefix}/#{type}" + template.route.path
name = Utils.capitalizeFirstChar(template.name)
routeName = "#{type}#{name}"

Utils.Logger.info "Add route: [#{routeName}] at path /" + path, TAG
Utils.Logger.info "Add route: [#{routeName}] at path " + path, TAG

# we use Picker for server side routes
Picker.route(path, (params, req, res) ->
action.call res, template, params
)

Router.route routeName,
path: path
where: 'server'
# An action still need the route context, but call it
# with our `template` as the sole parameter.
action: -> action.call(this, template)

# ## Init
#
6 changes: 3 additions & 3 deletions package.js
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ var where = 'server';
Package.describe({
name: 'lookback:emails',
summary: 'Send HTML emails with server side Blaze templates. Preview and debug in the browser.',
version: '0.6.2',
version: '0.7.0',
git: 'https://github.com/lookback/meteor-emails.git'
});

@@ -23,8 +23,8 @@ Package.onUse(function(api) {
'coffeescript',
'email',
'sacha:juice@0.1.3',
'iron:router@1.0.7',
'meteorhacks:ssr@2.1.2'
'meteorhacks:ssr@2.1.2',
'meteorhacks:picker@1.0.3'
], where);

api.addFiles([