Duplicate emails sent and timeout #32

Closed
mkey opened this Issue Jun 8, 2012 · 4 comments

Comments

Projects
None yet
3 participants

mkey commented Jun 8, 2012

Hello.

I've been messing around with various email sending solutions for nodejs and after trying to use nodemailer now I'm getting the same issue with emailjs.

I'm using the following:

windows 32bit XP
nodejs 0.6.19
the latest emailjs (installed with npm --force)
precompiled windows binaries for buffertools from here https://github.com/springmeyer/node-buffertools/tree/win-binary (basically, I just deleted the content of "emailjs\node_modules\buffertools" and unpacked the archived files from the above mentioned repository into it)

This is the code I'm currently using to send some test emails

var email= require("emailjs"),
server= email.server.connect({
    user:       "sender@gmail.com",
    password:   "sender_password",
    host:       "smtp.gmail.com",
    ssl:        true
});

server.send({
    text:       'www.google.com Confirm',
    from:       "Sender <sender@gmail.com>",
    to:         "receiver@gmail.com",
    subject:    "test confirmation",
    attachment: [
        {
            data:           '<a href="www.google.com">Confirm</a>',
            alternative:    true
        }
    ]
}, function(e, r){
    console.log(e);
    console.log(r);
});

This is my console log

Express server listening on port 8080 in development mode
null
{ attachments: [],
alternative:
{ data: 'Confirm',
alternative: true,
charset: 'utf-8',
type: 'text/html',
inline: true },
header:
{ 'message-id': '1339153866494.0.1600@PC',
from: 'Sender sender@gmail.com',
to: 'receiver@gmail.com',
subject: 'test confirmation' },
content: 'text/plain; charset=utf-8',
text: 'www.google.com Confirm' }
null
{ attachments: [],
alternative:
{ data: 'Confirm',
alternative: true,
charset: 'utf-8',
type: 'text/html',
inline: true },
header:
{ 'message-id': '1339153986421.1.1600@PC',
from: 'Sender sender@gmail.com',
to: 'receiver@gmail.com',
subject: 'test confirmation' },
content: 'text/plain; charset=utf-8',
text: 'www.google.com Confirm' }

I received two emails on my gmail account, the second coming in 2 minutes after the first has arrived. On my client side javascript I have a function waiting for server response, it times out after additional 2 minutes, making a total of 4 after sending the first email.

Owner

eleith commented Jun 8, 2012

if i just run your script in an independent file, i can't replicate your experience.

it is possible there is something else in your script that is causing the server.send to run twice.

if you can put together a more complete gist of how you are calling this script from within express, we might have a better chance at seeing what is happening.

but for now, it seems like the error has more to do with your environment rather than emailjs in particular. please let me know if you do end up being able to narrow down the problem a bit.

mkey commented Jun 8, 2012

These are very simple scripts, I have just stared working on my project and I'm trying to modularize it as much as possible for the time being.
The only thing that stands out, I'm running this script locally, don't know if that can cause this problem.

The server.js file

var express = require('express'),
app         = express.createServer(),
email       = require('./routes/email'),
main        = require('./routes/main');

// Configuration
app.configure(function(){
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.cookieParser());
    app.use(express.session({ secret: 'little kitty' }));
    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
    app.use(express.errorHandler());
});

// Routes
app.get('/', main.index);
app.post('/confirmation', email.index);

app.listen(process.env['PORT_WWW'] || 8080, function(){
    console.log('Express server listening on port %d in %s mode', app.address().port, app.settings.env);
});

The main.js file - client side. Attaches an event listener to a button on the page.

if (window.addEventListener) window.addEventListener("load", Init, false);
else if (window.attachEvent) window.attachEvent("onload", Init);
else if (window.onLoad) window.onload= Init;

function Init(){
    document.getElementById('email').addEventListener('click', function(){
        Request("/confirmation", "token="+document.getElementById('token').value, function(r){
            alert(r.responseText);
        });
    }, false);
}

function Request(url, data, f){
    var r= new XMLHttpRequest();
    if (!r) return;
    r.open((data) ? "POST" : "GET", url, true);
    // r.setRequestHeader('User-Agent','XMLHTTP/1.0');
    if (data) r.setRequestHeader('Content-type','application/x-www-form-urlencoded');
    r.onreadystatechange = function (){
        if (r.readyState!=4) return;
        if (r.status!=200 && r.status!=304){ alert('HTTP error '+r.status); return }
        if (f) f(r);
    }
    if (r.readyState==4) return;
    r.send(data);
}

The email.js file, responding to the "confirmation" request.

exports.index= function(req, res){
    if (!req.session.auth || req.body.token!=req.session.token)
        res.redirect('/');
    else {
var email= require("emailjs"),
server= email.server.connect({
    user:       "@gmail.com",
    password:   "",
    host:       "smtp.gmail.com",
    ssl:        true
});

console.log("--- sending mail ---");
server.send({
    text:       'www.google.com Confirm',
    from:       " <@gmail.com>",
    to:         "@gmail.com",
    subject:    "test confirmation",
    attachment: [
        {
            data:           '<a href="www.google.com">Confirm</a>',
            alternative:    true
        }
    ]
}, function(e, r){
    console.log(e);
    console.log(r);
});

    }
};

The main.js file - server side. This one renders the page where the button sending mail is located.

var lang=   require('../routes/lang'),
tb=         require('../toolbox.js');

exports.index= function(req, res){
    if (req.session.auth!=1){
        req.session.auth=           1;
        req.session.lang=           lang.en;
        req.session.token= tb.sha1(Math.random());
    }
    res.render('main', { title: '', s: req.session });
};

As you may have seen, I have added this just before the send method

console.log("--- sending mail ---");

The console log

$ node server.js
Express server listening on port 8080 in development mode
--- sending mail ---
null
{ attachments: [],
alternative:
{ data: 'Confirm',
alternative: true,
charset: 'utf-8',
type: 'text/html',
inline: true },
header:
{ 'message-id': '1339178853241.0.3704@Markec-PC',
from: 'Sender sender@gmail.com',
to: 'receiver@gmail.com',
subject: 'test confirmation 2' },
content: 'text/plain; charset=utf-8',
text: 'www.google.com Confirm' }
--- sending mail ---
null
{ attachments: [],
alternative:
{ data: 'Confirm',
alternative: true,
charset: 'utf-8',
type: 'text/html',
inline: true },
header:
{ 'message-id': '1339178973218.1.3704@Markec-PC',
from: 'Sender sender@gmail.com',
to: 'receiver@gmail.com',
subject: 'test confirmation 2' },
content: 'text/plain; charset=utf-8',
text: 'www.google.com Confirm' }

Result is the same, 2 mails and 4 minutes to timeout. So, the script does run two times lol The question is, "why the hell?"

... figured it out, my email.js didn't actually send anything back to the browser, a very stupid mistake to make :D

The updated email.js

exports.index= function(req, res){
    if (!req.session.auth || req.body.token!=req.session.token)
        res.send('Sending failure');
    else {
var email= require("emailjs"),
server= email.server.connect({
    user:       "@gmail.com",
    password:   "",
    host:       "smtp.gmail.com",
    ssl:        true
});

console.log("--- sending mail ---");
server.send({
    text:       'www.google.com Confirm',
    from:       " <@gmail.com>",
    to:         "@gmail.com",
    subject:    "test confirmation",
    attachment: [
        {
            data:           '<a href="www.google.com">Confirm</a>',
            alternative:    true
        }
    ]
}, function(e, r){
    if (!e) res.send('Sending OK');
    console.log(e);
    console.log(r);
});

    }
};

Thanks for your time.

Owner

eleith commented Jun 8, 2012

have you ruled out the possibility that two requests from the page are being sent, thus calling the email send snippet twice?

also, it is best to end the request from the page with a res.send(200) either before the email is sent or afterwards if you don't want to send a 200 till the email has been sent.

the timeout you reported earlier may be an express timeout since you are not explicitly ending the request.

since you are actually receiving the emails, emailjs is not timing out.

in order to debug, i'ld put some console logs right before you require emailjs to see how many times that is being called, chances are you'll see it being called more than once!

good luck.

@eleith eleith closed this Jun 8, 2012

thanks! I was making the same mistake of not sending anything back in response.
Lalit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment