Full Code of Marak/node_mailer for AI

master 325451bc1ed5 cached
12 files
20.4 KB
5.3k tokens
4 symbols
1 requests
Download .txt
Repository: Marak/node_mailer
Branch: master
Commit: 325451bc1ed5
Files: 12
Total size: 20.4 KB

Directory structure:
gitextract_c9ktmynw/

├── Changelog
├── MIT-LICENSE
├── Readme.md
├── demo-template-html.js
├── demo-template.js
├── demo.js
├── lib/
│   └── node_mailer.js
├── package.json
├── stubSMTP
├── templates/
│   ├── sample-html.txt
│   └── sample.txt
└── vendor/
    └── mustache.js

================================================
FILE CONTENTS
================================================

================================================
FILE: Changelog
================================================
node_mailer changelog:

0.6.4
- Don't sent plaintext body for templates, only send html, this should help w/ some confusion of email clients that are getting confused

0.6.3
- Fix for logging

0.6.2
- Fix for template logic
- Templates now default to html emails

0.6.1
- All Nodemailer arguments should now be merged in

0.6.0 [Breaking]
- Plaintext username/password

0.5.0
- NodeMailer as backing SmtpClient


================================================
FILE: MIT-LICENSE
================================================
Copyright (c) 2009 Marak Squires - http://github.com/marak/node_mailer
 
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
 
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.



================================================
FILE: Readme.md
================================================
# Project deprecated in favor of <a href="https://github.com/andris9/Nodemailer">nodemailer</a>

We merged the code-bases over a year ago, and it's time to get rid of this project.

================================================
FILE: demo-template-html.js
================================================
var email = require("./lib/node_mailer");

for(var i = 0; i < 10; i++){

  email.send({
    host : "localhost",               // smtp server hostname
    port : "25",                     // smtp server port
    domain : "localhost",             // domain used by client to identify itself to server
    to : "marak.squires@gmail.com",
    from : "obama@whitehouse.gov",
    subject : "node_mailer test email",
    template : "./templates/sample-html.txt",   // path to template name
    data : {
      "username": "Billy Bob",
      "color": function(){
        var arr = ["purple", "red", "green", "yello"];
        return arr[Math.floor(Math.random()*3)];
      },
      "animal": "monkey",
      "adverb": "quickly",
      "noun": "hot lava"
    },

    authentication : "login",        // auth login is supported; anything else is no auth
    username : undefined,            // username
    password : undefined,            // password
    debug: true                      // log level per message
  },
  function(err, result){
    if(err){ console.log(err); }
  });
}


================================================
FILE: demo-template.js
================================================
var email = require("./lib/node_mailer");

for(var i = 0; i < 10; i++){

  email.send({
    host : "localhost",               // smtp server hostname
    port : "25",                     // smtp server port
    domain : "localhost",             // domain used by client to identify itself to server
    to : "marak.squires@gmail.com",
    from : "obama@whitehouse.gov",
    subject : "node_mailer test email",
    template : "./templates/sample.txt",   // path to template name
    data : {
      "username": "Billy Bob",
      "color": function(){
        var arr = ["purple", "red", "green", "yello"];
        return arr[Math.floor(Math.random()*3)];
      },
      "animal": "monkey",
      "adverb": "quickly",
      "noun": "hot lava"
    },

    authentication : "login",        // auth login is supported; anything else is no auth
    username : undefined,            // username
    password : undefined,            // password
    debug: true                      // log level per message
  },
  function(err, result){
    if(err){ console.log(err); }
  });
}


================================================
FILE: demo.js
================================================
var email = require("./lib/node_mailer");

for(var i = 0; i < 1; i++){
  email.send({
    ssl: true,
    host : "smtp.gmail.com",              // smtp server hostname
    port : 465,                     // smtp server port
    domain : "[127.0.0.1]",            // domain used by client to identify itself to server
    to : "bradley.meck@gmail.com",
    from : "bradley.meck@gmail.com",
    subject : "node_mailer test email",
    reply_to:"bradley@bradleymeck.com",
    body: "Hello! This is a test of the node_mailer.",
    authentication : "login",        // auth login is supported; anything else is no auth
    username : undefined,            // username
    password : undefined,            // password
    debug: true                      // log level per message
  },
  function(err, result){
    if(err){ console.log(err); }
  });
}


================================================
FILE: lib/node_mailer.js
================================================
/* Copyright (c) 2009-2010 Marak Squires, Elijah Insua, Fedor Indutny - http://github.com/marak/node_mailer
 
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
 
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

var SMTPClient = require("nodemailer").SMTPClient;
var EmailMessage = require("nodemailer").EmailMessage;
var fs = require('fs');
var mustache = require('../vendor/mustache');
var _templateCache = {};

function SMTPClientPool() {
  this.servers = {};
}
SMTPClientPool.prototype.addClient = function(port,host,options) {
  if(this.servers[host] && this.servers[host][options.user]) return;
  var hostClients = this.servers[host] || (this.servers[host] = {});
  var pool = this;
  var client = hostClients[options.user] = new SMTPClient(host,port,options);
  client.on("close",function() {
    if(client == hostClients[options.user]) {
      //only because this could be crazy long lived and dynamic
      delete hostClients[options.user];
      if(Object.keys(hostClients).length == 0) {
	delete pool.servers[host]
      }
    }
  })
  client.on("empty",function(){
	delete hostClients[options.user];
	client.close();})
}
SMTPClientPool.prototype.send = function send(message, callback) {
  var hostpool = this.servers[message.SERVER.host]
  if(!hostpool) hostpool = {};
  var client = hostpool[message.SERVER.user]
  if(!client) {
    client = hostpool[message.SERVER.user] = new SMTPClient(message.SERVER.host,message.SERVER.port,message.SERVER);
    client.on("close",function() {
      if(client == hostClients[options.user]) {
          //only because this could be crazy long lived and dynamic
          delete hostClients[options.user];
          if(Object.keys(hostClients).length == 0) {
       delete pool.servers[host]
          }
        }
    })
    client.on("empty",function(){
     delete hostClients[options.user];
     client.close();})
  }
  client.sendMail(message,callback);
  client.on('error', callback);
}

function merge(x,y) {
  var z = {};
  for(var k in x) {
    z[k] = x[k];
  }
  for(var k in y) {
    z[k] = y[k];
  }
  return z;
}

var pool = new SMTPClientPool();

exports.send = function node_mail(message, callback) {
  var server = {
    host: message.host,
    hostname: message.domain,
    port: + message.port,
    use_authentication: message.authentication,
    ssl: message.ssl,
    user: message.username && message.username.toString(),
    pass: message.password && message.password.toString(),
    debug: message.debug || false
  };
  if(message.username || message.password) {
    pool.addClient(server.port, server.host, server);
  }

  function dispatchMail(message, server, callback) {
      var _message = {
          to: message.to,
          sender: message.from,
          subject: message.subject,
          server: server,
          debug: message.debug
      };
      if(message.html)_message.html = message.html;
      pool.send(new EmailMessage(merge(message, _message)), callback);
  }

  // If a template was passed in as part of the message
  if (message.template) {
    // If the template path is in the cache
    if (_templateCache[message.template]) {
      // If the template is already fully loaded in the cahe
      if (_templateCache[message.template].loaded) {
        // Use the cached template and send the email
        message.html = mustache.to_html(_templateCache[message.template].template, message.data);
        dispatchMail(message, server, callback);
      }
      else {
        // We've started to load the template, but it's not loaded yet. queue up this message to be sent later
        _templateCache[message.template].queue.push(message);
      }
    }
    else {
      // The template path wasn't found in the cache, start to load the template
      _templateCache[message.template]          = {};
      _templateCache[message.template].loaded   = false;
      _templateCache[message.template].template = '';
      _templateCache[message.template].queue    = [];

      fs.readFile(message.template, function(err, result){
        if (err) {
          callback(err);
          return;
        }

        _templateCache[message.template].template = result.toString();
        _templateCache[message.template].loaded   = true;

        // "Drain" the queue
        _templateCache[message.template].queue.push(message);
        _templateCache[message.template].queue.forEach(function(msg, i){
          msg.html = mustache.to_html(_templateCache[message.template].template, msg.data);
          dispatchMail(msg, server, callback);
        });

        // Clear the queue out
        _templateCache[message.template].queue = [];
      });
    }
  }
  else { // No template being used
    dispatchMail(message, server, callback);
  }
};


================================================
FILE: package.json
================================================
{
  "name": "mailer",
  "description": "send emails from node.js to a smtp server, simple as cake",
  "version": "0.6.7",
  "author": "Marak Squires",
  "contributors" : [
    "Elijah Insua <tmpvar@gmail.com> (http://tmvpar.com/)",
    "Fedor Indutny <fedor.indutny@gmail.com> (http://indutny.com/)",
    "Bradley Meck <bradley.meck@gmail.com> (http://bradleymeck.com)"
  ],
  "repository": {
    "type": "git",
    "url": "http://github.com/Marak/node_mailer.git"
  },
  "dependencies": {
    "nodemailer": "0.1.20",
    "colors": ">= 0.3.0"
  },
  "engine": [ "node >=0.3.0" ],
  "main": "lib/node_mailer"
}


================================================
FILE: stubSMTP
================================================
#!/usr/bin/env bash
if [ -z $1 ]
then port=1025
else port=$1
fi

echo "Starting dumb mail server on localhost:$port"
python -m smtpd -n -c DebuggingServer localhost:$port

================================================
FILE: templates/sample-html.txt
================================================
<div>Hello {{username}}, </div>
<br/>
<div>This is a sample template of the node mailer.</div>
<br/>
<div>It uses mustache templating to do basic search and replaces. </div>
<br/>
<div>The {{color}} {{animal}} {{adverb}} ran over the {{noun}}.</div>

================================================
FILE: templates/sample.txt
================================================
Hello {{username}}, 

This is a sample template of the node mailer.

It uses mustache templating to do basic search and replaces. 

The {{color}} {{animal}} {{adverb}} ran over the {{noun}}.

================================================
FILE: vendor/mustache.js
================================================
/*
 * CommonJS-compatible mustache.js module
 *
 * See http://github.com/janl/mustache.js for more info.
 */

/*
  mustache.js — Logic-less templates in JavaScript

  See http://mustache.github.com/ for more info.
*/

var Mustache = function() {
  var Renderer = function() {};

  Renderer.prototype = {
    otag: "{{",
    ctag: "}}",
    pragmas: {},
    buffer: [],
    pragmas_implemented: {
      "IMPLICIT-ITERATOR": true
    },
    context: {},

    render: function(template, context, partials, in_recursion) {
      // reset buffer & set context
      if(!in_recursion) {
        this.context = context;
        this.buffer = []; // TODO: make this non-lazy
      }

      // fail fast
      if(!this.includes("", template)) {
        if(in_recursion) {
          return template;
        } else {
          this.send(template);
          return;
        }
      }

      template = this.render_pragmas(template);
      var html = this.render_section(template, context, partials);
      if(in_recursion) {
        return this.render_tags(html, context, partials, in_recursion);
      }

      this.render_tags(html, context, partials, in_recursion);
    },

    /*
      Sends parsed lines
    */
    send: function(line) {
      if(line != "") {
        this.buffer.push(line);
      }
    },

    /*
      Looks for %PRAGMAS
    */
    render_pragmas: function(template) {
      // no pragmas
      if(!this.includes("%", template)) {
        return template;
      }

      var that = this;
      var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" +
            this.ctag);
      return template.replace(regex, function(match, pragma, options) {
        if(!that.pragmas_implemented[pragma]) {
          throw({message: 
            "This implementation of mustache doesn't understand the '" +
            pragma + "' pragma"});
        }
        that.pragmas[pragma] = {};
        if(options) {
          var opts = options.split("=");
          that.pragmas[pragma][opts[0]] = opts[1];
        }
        return "";
        // ignore unknown pragmas silently
      });
    },

    /*
      Tries to find a partial in the curent scope and render it
    */
    render_partial: function(name, context, partials) {
      name = this.trim(name);
      if(!partials || partials[name] === undefined) {
        throw({message: "unknown_partial '" + name + "'"});
      }
      if(typeof(context[name]) != "object") {
        return this.render(partials[name], context, partials, true);
      }
      return this.render(partials[name], context[name], partials, true);
    },

    /*
      Renders inverted (^) and normal (#) sections
    */
    render_section: function(template, context, partials) {
      if(!this.includes("#", template) && !this.includes("^", template)) {
        return template;
      }

      var that = this;
      // CSW - Added "+?" so it finds the tighest bound, not the widest
      var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag +
              "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag +
              "\\s*", "mg");

      // for each {{#foo}}{{/foo}} section do...
      return template.replace(regex, function(match, type, name, content) {
        var value = that.find(name, context);
        if(type == "^") { // inverted section
          if(!value || that.is_array(value) && value.length === 0) {
            // false or empty list, render it
            return that.render(content, context, partials, true);
          } else {
            return "";
          }
        } else if(type == "#") { // normal section
          if(that.is_array(value)) { // Enumerable, Let's loop!
            return that.map(value, function(row) {
              return that.render(content, that.create_context(row),
                partials, true);
            }).join("");
          } else if(that.is_object(value)) { // Object, Use it as subcontext!
            return that.render(content, that.create_context(value),
              partials, true);
          } else if(typeof value === "function") {
            // higher order section
            return value.call(context, content, function(text) {
              return that.render(text, context, partials, true);
            });
          } else if(value) { // boolean section
            return that.render(content, context, partials, true);
          } else {
            return "";
          }
        }
      });
    },

    /*
      Replace {{foo}} and friends with values from our view
    */
    render_tags: function(template, context, partials, in_recursion) {
      // tit for tat
      var that = this;

      var new_regex = function() {
        return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" +
          that.ctag + "+", "g");
      };

      var regex = new_regex();
      var tag_replace_callback = function(match, operator, name) {
        switch(operator) {
        case "!": // ignore comments
          return "";
        case "=": // set new delimiters, rebuild the replace regexp
          that.set_delimiters(name);
          regex = new_regex();
          return "";
        case ">": // render partial
          return that.render_partial(name, context, partials);
        case "{": // the triple mustache is unescaped
          return that.find(name, context);
        default: // escape the value
          return that.escape(that.find(name, context));
        }
      };
      var lines = template.split("\n");
      for(var i = 0; i < lines.length; i++) {
        lines[i] = lines[i].replace(regex, tag_replace_callback, this);
        if(!in_recursion) {
          this.send(lines[i]);
        }
      }

      if(in_recursion) {
        return lines.join("\n");
      }
    },

    set_delimiters: function(delimiters) {
      var dels = delimiters.split(" ");
      this.otag = this.escape_regex(dels[0]);
      this.ctag = this.escape_regex(dels[1]);
    },

    escape_regex: function(text) {
      // thank you Simon Willison
      if(!arguments.callee.sRE) {
        var specials = [
          '/', '.', '*', '+', '?', '|',
          '(', ')', '[', ']', '{', '}', '\\'
        ];
        arguments.callee.sRE = new RegExp(
          '(\\' + specials.join('|\\') + ')', 'g'
        );
      }
      return text.replace(arguments.callee.sRE, '\\$1');
    },

    /*
      find `name` in current `context`. That is find me a value
      from the view object
    */
    find: function(name, context) {
      name = this.trim(name);

      // Checks whether a value is thruthy or false or 0
      function is_kinda_truthy(bool) {
        return bool === false || bool === 0 || bool;
      }

      var value;
      if(is_kinda_truthy(context[name])) {
        value = context[name];
      } else if(is_kinda_truthy(this.context[name])) {
        value = this.context[name];
      }

      if(typeof value === "function") {
        return value.apply(context);
      }
      if(value !== undefined) {
        return value;
      }
      // silently ignore unkown variables
      return "";
    },

    // Utility methods

    /* includes tag */
    includes: function(needle, haystack) {
      return haystack.indexOf(this.otag + needle) != -1;
    },

    /*
      Does away with nasty characters
    */
    escape: function(s) {
      s = String(s === null ? "" : s);
      return s.replace(/&(?!\w+;)|["<>\\]/g, function(s) {
        switch(s) {
        case "&": return "&amp;";
        case "\\": return "\\\\";
        case '"': return '\"';
        case "<": return "&lt;";
        case ">": return "&gt;";
        default: return s;
        }
      });
    },

    // by @langalex, support for arrays of strings
    create_context: function(_context) {
      if(this.is_object(_context)) {
        return _context;
      } else {
        var iterator = ".";
        if(this.pragmas["IMPLICIT-ITERATOR"]) {
          iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
        }
        var ctx = {};
        ctx[iterator] = _context;
        return ctx;
      }
    },

    is_object: function(a) {
      return a && typeof a == "object";
    },

    is_array: function(a) {
      return Object.prototype.toString.call(a) === '[object Array]';
    },

    /*
      Gets rid of leading and trailing whitespace
    */
    trim: function(s) {
      return s.replace(/^\s*|\s*$/g, "");
    },

    /*
      Why, why, why? Because IE. Cry, cry cry.
    */
    map: function(array, fn) {
      if (typeof array.map == "function") {
        return array.map(fn);
      } else {
        var r = [];
        var l = array.length;
        for(var i = 0; i < l; i++) {
          r.push(fn(array[i]));
        }
        return r;
      }
    }
  };

  return({
    name: "mustache.js",
    version: "0.3.1-dev",

    /*
      Turns a template and view into HTML
    */
    to_html: function(template, view, partials, send_fun) {
      var renderer = new Renderer();
      if(send_fun) {
        renderer.send = send_fun;
      }
      renderer.render(template, view, partials);
      if(!send_fun) {
        return renderer.buffer.join("\n");
      }
    }
  });
}();

exports.name = Mustache.name;
exports.version = Mustache.version;

exports.to_html = function() {
  return Mustache.to_html.apply(this, arguments);
};
Download .txt
gitextract_c9ktmynw/

├── Changelog
├── MIT-LICENSE
├── Readme.md
├── demo-template-html.js
├── demo-template.js
├── demo.js
├── lib/
│   └── node_mailer.js
├── package.json
├── stubSMTP
├── templates/
│   ├── sample-html.txt
│   └── sample.txt
└── vendor/
    └── mustache.js
Download .txt
SYMBOL INDEX (4 symbols across 2 files)

FILE: lib/node_mailer.js
  function SMTPClientPool (line 31) | function SMTPClientPool() {
  function merge (line 75) | function merge(x,y) {
  function dispatchMail (line 103) | function dispatchMail(message, server, callback) {

FILE: vendor/mustache.js
  function is_kinda_truthy (line 220) | function is_kinda_truthy(bool) {
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (22K chars).
[
  {
    "path": "Changelog",
    "chars": 411,
    "preview": "node_mailer changelog:\n\n0.6.4\n- Don't sent plaintext body for templates, only send html, this should help w/ some confus"
  },
  {
    "path": "MIT-LICENSE",
    "chars": 1099,
    "preview": "Copyright (c) 2009 Marak Squires - http://github.com/marak/node_mailer\n \nPermission is hereby granted, free of charge, t"
  },
  {
    "path": "Readme.md",
    "chars": 180,
    "preview": "# Project deprecated in favor of <a href=\"https://github.com/andris9/Nodemailer\">nodemailer</a>\n\nWe merged the code-base"
  },
  {
    "path": "demo-template-html.js",
    "chars": 1074,
    "preview": "var email = require(\"./lib/node_mailer\");\n\nfor(var i = 0; i < 10; i++){\n\n  email.send({\n    host : \"localhost\",         "
  },
  {
    "path": "demo-template.js",
    "chars": 1069,
    "preview": "var email = require(\"./lib/node_mailer\");\n\nfor(var i = 0; i < 10; i++){\n\n  email.send({\n    host : \"localhost\",         "
  },
  {
    "path": "demo.js",
    "chars": 844,
    "preview": "var email = require(\"./lib/node_mailer\");\n\nfor(var i = 0; i < 1; i++){\n  email.send({\n    ssl: true,\n    host : \"smtp.gm"
  },
  {
    "path": "lib/node_mailer.js",
    "chars": 5657,
    "preview": "/* Copyright (c) 2009-2010 Marak Squires, Elijah Insua, Fedor Indutny - http://github.com/marak/node_mailer\n \nPermission"
  },
  {
    "path": "package.json",
    "chars": 610,
    "preview": "{\n  \"name\": \"mailer\",\n  \"description\": \"send emails from node.js to a smtp server, simple as cake\",\n  \"version\": \"0.6.7\""
  },
  {
    "path": "stubSMTP",
    "chars": 170,
    "preview": "#!/usr/bin/env bash\nif [ -z $1 ]\nthen port=1025\nelse port=$1\nfi\n\necho \"Starting dumb mail server on localhost:$port\"\npyt"
  },
  {
    "path": "templates/sample-html.txt",
    "chars": 249,
    "preview": "<div>Hello {{username}}, </div>\n<br/>\n<div>This is a sample template of the node mailer.</div>\n<br/>\n<div>It uses mustac"
  },
  {
    "path": "templates/sample.txt",
    "chars": 190,
    "preview": "Hello {{username}}, \n\nThis is a sample template of the node mailer.\n\nIt uses mustache templating to do basic search and "
  },
  {
    "path": "vendor/mustache.js",
    "chars": 9301,
    "preview": "/*\n * CommonJS-compatible mustache.js module\n *\n * See http://github.com/janl/mustache.js for more info.\n */\n\n/*\n  musta"
  }
]

About this extraction

This page contains the full source code of the Marak/node_mailer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (20.4 KB), approximately 5.3k tokens, and a symbol index with 4 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!