Skip to content

Commit

Permalink
Add coffeescript markdown
Browse files Browse the repository at this point in the history
  • Loading branch information
doomhz committed Jun 18, 2012
1 parent 19e0cd1 commit 0291c11
Showing 1 changed file with 151 additions and 139 deletions.
290 changes: 151 additions & 139 deletions articles/sending-e-mails-with-node-and-nodemailer.markdown
Expand Up @@ -7,176 +7,188 @@ Sending e-mails with [NodeJS][] is almost a breeze. Almost. First, you have to p


The first thing you tend to do is to create a wrapper class to manage all this tasks. So, I wrapped it in an Eamiler class to centralize the mail sending in my app. The first thing you tend to do is to create a wrapper class to manage all this tasks. So, I wrapped it in an Eamiler class to centralize the mail sending in my app.


```coffeescript
# /lib/emailer.coffee

emailer = require("nodemailer")
fs = require("fs")
_ = require("underscore")

class Emailer

options: {}

data: {}

# Define attachments here
attachments: [
fileName: "logo.png"
filePath: "./public/images/email/logo.png"
cid: "logo@myapp"
]

constructor: (@options, @data)->

send: (callback)->
html = @getHtml(@options.template, @data)
attachments = @getAttachments(html)
messageData =
to: "'#{@options.to.name} #{@options.to.surname}' <#{@options.to.email}>"
from: "'Myapp.com'"
subject: @options.subject
html: html
generateTextFromHTML: true
attachments: attachments
transport = @getTransport()
transport.sendMail messageData, callback

getTransport: ()->
emailer.createTransport "SMTP",
service: "Gmail"
auth:
user: "myappemail@gmail.com"
pass: "secretpass"

getHtml: (templateName, data)->
templatePath = "./views/emails/#{templateName}.html"
templateContent = fs.readFileSync(templatePath, encoding="utf8")
_.template templateContent, data, {interpolate: /\{\{(.+?)\}\}/g}

getAttachments: (html)->
attachments = []
for attachment in @attachments
attachments.push(attachment) if html.search("cid:#{attachment.cid}") > -1
attachments

exports = module.exports = Emailer
```


# /lib/emailer.coffee


emailer = require("nodemailer") In a standard [ExpressJS][] project structure you'll store this file in `/lib/emailer.coffee`.
fs = require("fs") You'll need to have the email templates stored in `/views/emails/` as HTML files and the attachments in `/public/images/email/`.
_ = require("underscore")

class Emailer

options: {}

data: {}


# Define attachments here A potential email view will look like this:
attachments: [
fileName: "logo.png"
filePath: "./public/images/email/logo.png"
cid: "logo@myapp"
]


constructor: (@options, @data)->


send: (callback)-> ```html
html = @getHtml(@options.template, @data) &lt;!-- invite.html --&gt;
attachments = @getAttachments(html) &lt;html&gt;
messageData = &lt;head&gt;
to: "'#{@options.to.name} #{@options.to.surname}' <#{@options.to.email}>" &lt;title&gt;Invite from Myapp&lt;/title&gt;
from: "'Myapp.com'" &lt;/head&gt;
subject: @options.subject &lt;body&gt;
html: html &lt;p&gt;
generateTextFromHTML: true Hi {{name}} {{surname}},
attachments: attachments &lt;/p&gt;
transport = @getTransport() &lt;p&gt;
transport.sendMail messageData, callback Myapp would like you to join it's network on &lt;a href="http://myapp.com"&gt;Myapp.com&lt;/a&gt;.
&lt;br /&gt;
Please follow the link bellow to register:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://myapp.com/register?invite={{id}}"&gt;http://myapp.com/register?invite={{id}}&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Thank you,
&lt;br /&gt;
Myapp Team
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://myapp.com">&lt;img src="cid:logo@myapp" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
```


getTransport: ()->
emailer.createTransport "SMTP",
service: "Gmail"
auth:
user: "myappemail@gmail.com"
pass: "secretpass"


getHtml: (templateName, data)-> [UnderscoreJS][] template will take care about your variables in the template and the `getAttachments()` function will automatically attache the files you need by the `cid` from the template.
templatePath = "./views/emails/#{templateName}.html"
templateContent = fs.readFileSync(templatePath, encoding="utf8")
_.template templateContent, data, {interpolate: /\{\{(.+?)\}\}/g}


getAttachments: (html)-> To use the class in your code you have to instantiate a new Emailer object with the desired options, the template data and send the email:
attachments = []
for attachment in @attachments
attachments.push(attachment) if html.search("cid:#{attachment.cid}") > -1
attachments


exports = module.exports = Emailer


In a standard [ExpressJS][] project structure you'll store this file in `/lib/emailer.coffee`. ```coffeescript
You'll need to have the email templates stored in `/views/emails/` as HTML files and the attachments in `/public/images/email/`. options =
to:
email: "username@domain.com"
name: "Rick"
surname: "Roll"
subject: "Invite from Myapp"
template: "invite"


A potential email view will look like this: data =
name: "Rick"
surname "Roll"
id: "3434_invite_id"


&lt;!-- invite.html --&gt; Emailer = require "../lib/emailer"
&lt;html&gt; emailer = new Emailer options, data
&lt;head&gt; emailer.send (err, result)->
&lt;title&gt;Invite from Myapp&lt;/title&gt; if err
&lt;/head&gt; console.log err
&lt;body&gt; ```
&lt;p&gt;
Hi {{name}} {{surname}},
&lt;/p&gt;
&lt;p&gt;
Myapp would like you to join it's network on &lt;a href="http://myapp.com"&gt;Myapp.com&lt;/a&gt;.
&lt;br /&gt;
Please follow the link bellow to register:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://myapp.com/register?invite={{id}}"&gt;http://myapp.com/register?invite={{id}}&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Thank you,
&lt;br /&gt;
Myapp Team
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://myapp.com">&lt;img src="cid:logo@myapp" /&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;




[UnderscoreJS][] template will take care about your variables in the template and the `getAttachments()` function will automatically attache the files you need by the `cid` from the template. Using a [MongooseJS]: http://mongoosejs.com/ model for the invites you would have something like this:


To use the class in your code you have to instantiate a new Emailer object with the desired options, the template data and send the email:


```coffeescript
InviteSchema = new Schema
email:
type: String
name:
type: String
surname:
type: String
status:
type: String
enum: ["pending", "accepted"]
default: "pending"
clicks:
type: Number
default: 0
created_at:
type: Date
default: Date.now

InviteSchema.methods.send = ()->
options = options =
to: to:
email: "username@domain.com" email: @email
name: "Rick" name: @name
surname: "Roll" surname: @surname
subject: "Invite from Myapp" subject: "Invite from Myapp"
template: "invite" template: "invite"

data =
name: "Rick"
surname "Roll"
id: "3434_invite_id"

Emailer = require "../lib/emailer" Emailer = require "../lib/emailer"
emailer = new Emailer options, data emailer = new Emailer options, @
emailer.send (err, result)-> emailer.send (err, result)->
if err if err
console.log err console.log err



Invite = mongoose.model("Invite", InviteSchema)
Using a [MongooseJS]: http://mongoosejs.com/ model for the invites you would have something like this: exports = module.exports = Invite

```

InviteSchema = new Schema
email:
type: String
name:
type: String
surname:
type: String
status:
type: String
enum: ["pending", "accepted"]
default: "pending"
clicks:
type: Number
default: 0
created_at:
type: Date
default: Date.now

InviteSchema.methods.send = ()->
options =
to:
email: @email
name: @name
surname: @surname
subject: "Invite from Myapp"
template: "invite"
Emailer = require "../lib/emailer"
emailer = new Emailer options, @
emailer.send (err, result)->
if err
console.log err

Invite = mongoose.model("Invite", InviteSchema)
exports = module.exports = Invite




And you'll call it from an ExpressJS router: And you'll call it from an ExpressJS router:




Invite = require('../models/invite') ```coffeescript
Invite = require('../models/invite')


module.exports = (app)-> module.exports = (app)->


app.post '/invites', (req, res)-> app.post '/invites', (req, res)->
data = req.body data = req.body
invite = new Invite data invite = new Invite data
invite.save ()-> invite.save ()->
invite.send() invite.send()
res.writeHead(303, {'Location': "/invites"}) res.writeHead(303, {'Location': "/invites"})
res.end() res.end()


app.get '/invites', (req, res)-> app.get '/invites', (req, res)->
Invite.find().desc("created_at").run (err, invites)-> Invite.find().desc("created_at").run (err, invites)->
res.render 'invites/invites', {title: "Invites", invites: invites} res.render 'invites/invites', {title: "Invites", invites: invites}
```




That's all about it. That's all about it.
Expand Down

0 comments on commit 0291c11

Please sign in to comment.