1 var Transport = require("./transport").Transport, 2 MailComposer = require("mailcomposer").MailComposer; 3 4 /* 5 * Version constants 6 */ 7 var X_MAILER_NAME = "Nodemailer", 8 X_MAILER_VERSION = "0.3.0; +http://www.nodemailer.org"; 9 10 11 // Export Transport constructor 12 module.exports.Transport = Transport; 13 14 // Export sendMail function (and the alias send_mail for legacy) 15 module.exports.sendMail = module.exports.send_mail = function(options, callback){ 16 var mailer = new Nodemailer(options); 17 18 mailer.validateSettings(function(err){ 19 if(err){ 20 // report validation error back to the client 21 return callback(err); 22 }else{ 23 // try to send the e-mail message 24 mailer.sendMail(callback); 25 } 26 }); 27 28 return mailer; 29 }; 30 31 32 /** 33 * <p>Generates a Nodemailer object which is the main 'hub' for managing the 34 * send process</p> 35 * 36 * @constructor 37 * @param {Object} options Message options object, see README for the complete list of possible options 38 */ 39 function Nodemailer(options){ 40 this.options = options || {}; 41 42 this.transport = this.options.transport; 43 44 this.mailcomposer = new MailComposer(); 45 46 if(!this.transport){ 47 this.transport = this.getGlobalTransport(); 48 } 49 } 50 51 /** 52 * <p>Add support for legacy transport settings by checking for global 53 * variables SMTP, sendmail and SES</p> 54 * 55 * @return {Object} {@link Transport} object 56 */ 57 Nodemailer.prototype.getGlobalTransport = function(){ 58 if(this.options.SMTP){ 59 // cache the transport for SMTP as it is actually a connection pool 60 if(!this.options.SMTP._smtp_transport){ 61 this.options.SMTP._smtp_transport = new Transport("SMTP", this.options.SMTP); 62 } 63 return this.options.SMTP._smtp_transport; 64 }else if(this.options.sendmail){ 65 return new Transport("sendmail", this.options.sendmail); 66 }else if(this.options.SES){ 67 return new Transport("SES", this.options.SES); 68 }else if(module.exports.SMTP){ 69 // cache the transport for SMTP as it is actually a connection pool 70 if(!module.exports._smtp_transport){ 71 module.exports._smtp_transport = new Transport("SMTP", module.exports.SMTP); 72 } 73 return module.exports._smtp_transport; 74 }else if(module.exports.sendmail){ 75 return new Transport("sendmail", module.exports.sendmail); 76 }else if(module.exports.SES){ 77 return new Transport("SES", module.exports.SES); 78 } 79 return false; 80 }; 81 82 /** 83 * <p>Doesn't do much currently, if the future should link to transport 84 * validation methods. For example in case of SES should check that AWS 85 * keys are set up etc.</p> 86 * 87 * @param {Function} callback Callback function to run after validation 88 */ 89 Nodemailer.prototype.validateSettings = function(callback){ 90 if(!this.transport || !this.transport.transport){ 91 return callback(new Error("No transport method defined")); 92 } 93 callback(null); 94 }; 95 96 /** 97 * <p>Send the e-mail message by using data from the original options object 98 * and selected transport</p> 99 * 100 * @param {Function} callback Callback function to run when the e-mail has been sent (or it failed) 101 */ 102 Nodemailer.prototype.sendMail = function(callback){ 103 // compose the e-mail 104 this.generateMailObject(); 105 // send the message using preselected transport method 106 this.transport.sendMail(this.mailcomposer, callback); 107 }; 108 109 /** 110 * <p>Uses the data from the original options object to compose a mailcomposer 111 * e-mail message that can be later streamed to the selected transport</p> 112 */ 113 Nodemailer.prototype.generateMailObject = function(){ 114 115 // set envelope data, subject etc. 116 this.setGeneralOptions(); 117 118 // set module defined headers (date, message-id, etc.) 119 this.setModuleHeaders(); 120 121 // set user defined headers (if any) 122 this.setUserHeaders(); 123 124 // set attachments (if any) 125 this.setAttachments(); 126 }; 127 128 /** 129 * <p>Uses the general options (message sender and receiver, subject body, etc.) 130 * to set mailcomposer properties. Includes support for legacy properties.</p> 131 */ 132 Nodemailer.prototype.setGeneralOptions = function(){ 133 var acceptedFields = ["from", "sender", "to", "subject", "replyTo", "debug", 134 "reply_to", "cc", "bcc", "body", "text", "html"], 135 mailOptions = {}, 136 keys = Object.keys(this.options), 137 key; 138 139 for(var i=0, len=keys.length; i<len; i++){ 140 key = keys[i]; 141 if(acceptedFields.indexOf(key) >=0 && this.options[key]){ 142 mailOptions[key] = this.options[key]; 143 } 144 } 145 146 if(this.options.debug){ 147 console.log(mailOptions); 148 } 149 150 this.mailcomposer.setMessageOption(mailOptions); 151 }; 152 153 /** 154 * <p>If the 'headers' property was set on the options, add the values to the 155 * header of the e-mail message</p> 156 */ 157 Nodemailer.prototype.setUserHeaders = function(){ 158 if(typeof this.options.headers != "object"){ 159 return; 160 } 161 var keys = Object.keys(this.options.headers), 162 key; 163 164 for(var i=0, len=keys.length; i<len; i++){ 165 key = keys[i]; 166 if(this.options.headers[key]){ 167 this.mailcomposer.addHeader(key, this.options.headers[key]); 168 } 169 } 170 }; 171 172 /** 173 * <p>Add some required headers to the message, such as Date: and Message-Id:</p> 174 */ 175 Nodemailer.prototype.setModuleHeaders = function(){ 176 177 // Mailer name + version 178 this.mailcomposer.addHeader("X-Mailer", X_MAILER_NAME+ 179 (X_MAILER_VERSION?" ("+X_MAILER_VERSION+")":"")); 180 181 // Date 182 this.mailcomposer.addHeader("Date", new Date().toUTCString()); 183 184 // Message ID 185 this.mailcomposer.addHeader("Message-Id", "<"+ 186 Date.now()+Math.random().toString(16).substr(1)+"@"+ 187 X_MAILER_NAME+">"); 188 }; 189 190 /** 191 * <p>If attachment array is set on the options object, add these attachments 192 * to the mailcomposer object</p> 193 */ 194 Nodemailer.prototype.setAttachments = function(){ 195 if(!Array.isArray(this.options.attachments)){ 196 return; 197 } 198 var attachment; 199 for(var i=0, len=this.options.attachments.length; i<len; i++){ 200 attachment = this.options.attachments[i]; 201 this.mailcomposer.addAttachment(attachment); 202 } 203 };