mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Improved log output for welcome email error (#9016)
* Improved log output for welcome email error no issue - if Ghost is unable to send a welcome email, the server log printe a huge error log - the reason was that each component wrapped the original error into a new error instance - so the stack grows and grows - the golden rule should always be: the smallest/lowest component should instanitate a specifc error - the caller can expect to receive a custom Ghost error * Tidy up error messages for mail failures and fix tests - We never use "Error:" notation in our translations - Make the error messages consistent and show a reason if possible
This commit is contained in:
parent
ca53a83569
commit
edf2348394
5 changed files with 49 additions and 41 deletions
|
@ -532,13 +532,11 @@ authentication = {
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
mailAPI.send(payload, {context: {internal: true}}).catch(function (error) {
|
mailAPI.send(payload, {context: {internal: true}})
|
||||||
logging.error(new errors.EmailError({
|
.catch(function (err) {
|
||||||
err: error,
|
err.context = i18n.t('errors.api.authentication.unableToSendWelcomeEmail');
|
||||||
context: i18n.t('errors.api.authentication.unableToSendWelcomeEmail'),
|
logging.error(err);
|
||||||
help: i18n.t('errors.api.authentication.checkEmailConfigInstructions', {url: 'http://docs.ghost.org/v1/docs/mail-config'})
|
});
|
||||||
}));
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.return(setupUser);
|
.return(setupUser);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ var Promise = require('bluebird'),
|
||||||
pipeline = require('../utils/pipeline'),
|
pipeline = require('../utils/pipeline'),
|
||||||
apiUtils = require('./utils'),
|
apiUtils = require('./utils'),
|
||||||
models = require('../models'),
|
models = require('../models'),
|
||||||
errors = require('../errors'),
|
|
||||||
i18n = require('../i18n'),
|
i18n = require('../i18n'),
|
||||||
mail = require('../mail'),
|
mail = require('../mail'),
|
||||||
notificationsAPI = require('./notifications'),
|
notificationsAPI = require('./notifications'),
|
||||||
|
@ -36,7 +35,7 @@ function sendMail(object) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(new errors.EmailError({err: err}));
|
return Promise.reject(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
// # Mail
|
// # Mail
|
||||||
// Handles sending email for Ghost
|
// Handles sending email for Ghost
|
||||||
var _ = require('lodash'),
|
var _ = require('lodash'),
|
||||||
Promise = require('bluebird'),
|
Promise = require('bluebird'),
|
||||||
validator = require('validator'),
|
validator = require('validator'),
|
||||||
config = require('../config'),
|
config = require('../config'),
|
||||||
|
errors = require('../errors'),
|
||||||
settingsCache = require('../settings/cache'),
|
settingsCache = require('../settings/cache'),
|
||||||
i18n = require('../i18n'),
|
i18n = require('../i18n'),
|
||||||
utils = require('../utils');
|
utils = require('../utils');
|
||||||
|
|
||||||
function GhostMailer() {
|
function GhostMailer() {
|
||||||
var nodemailer = require('nodemailer'),
|
var nodemailer = require('nodemailer'),
|
||||||
|
@ -47,14 +48,19 @@ GhostMailer.prototype.getDomain = function () {
|
||||||
// This assumes that api.settings.read('email') was already done on the API level
|
// This assumes that api.settings.read('email') was already done on the API level
|
||||||
GhostMailer.prototype.send = function (message) {
|
GhostMailer.prototype.send = function (message) {
|
||||||
var self = this,
|
var self = this,
|
||||||
to;
|
to,
|
||||||
|
help = i18n.t('errors.api.authentication.checkEmailConfigInstructions', {url: 'http://docs.ghost.org/v1/docs/mail-config'}),
|
||||||
|
errorMessage = i18n.t('errors.mail.failedSendingEmail.error');
|
||||||
|
|
||||||
// important to clone message as we modify it
|
// important to clone message as we modify it
|
||||||
message = _.clone(message) || {};
|
message = _.clone(message) || {};
|
||||||
to = message.to || false;
|
to = message.to || false;
|
||||||
|
|
||||||
if (!(message && message.subject && message.html && message.to)) {
|
if (!(message && message.subject && message.html && message.to)) {
|
||||||
return Promise.reject(new Error(i18n.t('errors.mail.incompleteMessageData.error')));
|
return Promise.reject(new errors.EmailError({
|
||||||
|
message: i18n.t('errors.mail.incompleteMessageData.error'),
|
||||||
|
help: help
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
message = _.extend(message, {
|
message = _.extend(message, {
|
||||||
|
@ -65,9 +71,15 @@ GhostMailer.prototype.send = function (message) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
self.transport.sendMail(message, function (error, response) {
|
self.transport.sendMail(message, function (err, response) {
|
||||||
if (error) {
|
if (err) {
|
||||||
return reject(new Error(error));
|
errorMessage += i18n.t('errors.mail.reason', {reason: err.message || err});
|
||||||
|
|
||||||
|
return reject(new errors.EmailError({
|
||||||
|
message: errorMessage,
|
||||||
|
err: err,
|
||||||
|
help: help
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.transport.transportType !== 'DIRECT') {
|
if (self.transport.transportType !== 'DIRECT') {
|
||||||
|
@ -75,23 +87,25 @@ GhostMailer.prototype.send = function (message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
response.statusHandler.once('failed', function (data) {
|
response.statusHandler.once('failed', function (data) {
|
||||||
var reason = i18n.t('errors.mail.failedSendingEmail.error');
|
|
||||||
|
|
||||||
if (data.error && data.error.errno === 'ENOTFOUND') {
|
if (data.error && data.error.errno === 'ENOTFOUND') {
|
||||||
reason += i18n.t('errors.mail.noMailServerAtAddress.error', {domain: data.domain});
|
errorMessage += i18n.t('errors.mail.noMailServerAtAddress.error', {domain: data.domain});
|
||||||
}
|
}
|
||||||
reason += '.';
|
|
||||||
return reject(new Error(reason));
|
return reject(new errors.EmailError({
|
||||||
|
message: errorMessage,
|
||||||
|
help: help
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
response.statusHandler.once('requeue', function (data) {
|
response.statusHandler.once('requeue', function (data) {
|
||||||
var errorMessage = i18n.t('errors.mail.messageNotSent.error');
|
|
||||||
|
|
||||||
if (data.error && data.error.message) {
|
if (data.error && data.error.message) {
|
||||||
errorMessage += i18n.t('errors.general.moreInfo', {info: data.error.message});
|
errorMessage += i18n.t('errors.mail.reason', {reason: data.error.message});
|
||||||
}
|
}
|
||||||
|
|
||||||
return reject(new Error(errorMessage));
|
return reject(new errors.EmailError({
|
||||||
|
message: errorMessage,
|
||||||
|
help: help
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
response.statusHandler.once('sent', function () {
|
response.statusHandler.once('sent', function () {
|
||||||
|
|
|
@ -167,7 +167,6 @@
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"maintenance": "Ghost is currently undergoing maintenance, please wait a moment then retry.",
|
"maintenance": "Ghost is currently undergoing maintenance, please wait a moment then retry.",
|
||||||
"moreInfo": "\nMore info: {info}",
|
|
||||||
"requiredOnFuture": "This will be required in future. Please see {link}",
|
"requiredOnFuture": "This will be required in future. Please see {link}",
|
||||||
"internalError": "Something went wrong."
|
"internalError": "Something went wrong."
|
||||||
},
|
},
|
||||||
|
@ -185,17 +184,15 @@
|
||||||
},
|
},
|
||||||
"mail": {
|
"mail": {
|
||||||
"incompleteMessageData": {
|
"incompleteMessageData": {
|
||||||
"error": "Error: Incomplete message data."
|
"error": "Incomplete message data."
|
||||||
},
|
},
|
||||||
"failedSendingEmail": {
|
"failedSendingEmail": {
|
||||||
"error": "Error: Failed to send email"
|
"error": "Failed to send email."
|
||||||
},
|
},
|
||||||
"noMailServerAtAddress": {
|
"noMailServerAtAddress": {
|
||||||
"error": " - no mail server found at {domain}"
|
"error": " No mail server found at {domain}."
|
||||||
},
|
},
|
||||||
"messageNotSent": {
|
"reason": " Reason: {reason}."
|
||||||
"error": "Error: Message could not be sent"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"models": {
|
"models": {
|
||||||
"subscriber": {
|
"subscriber": {
|
||||||
|
|
|
@ -96,7 +96,7 @@ describe('Mail: Ghostmailer', function () {
|
||||||
mailer.send(mailDataNoServer).then(function () {
|
mailer.send(mailDataNoServer).then(function () {
|
||||||
done(new Error('Stub did not error'));
|
done(new Error('Stub did not error'));
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
error.message.should.eql('Error: Stub made a boo boo :(');
|
error.message.should.containEql('Stub made a boo boo :(');
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
@ -113,7 +113,7 @@ describe('Mail: Ghostmailer', function () {
|
||||||
descriptors.forEach(function (d) {
|
descriptors.forEach(function (d) {
|
||||||
d.isFulfilled().should.be.false();
|
d.isFulfilled().should.be.false();
|
||||||
d.reason().should.be.an.instanceOf(Error);
|
d.reason().should.be.an.instanceOf(Error);
|
||||||
d.reason().message.should.eql('Error: Incomplete message data.');
|
d.reason().message.should.eql('Incomplete message data.');
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
|
@ -136,7 +136,7 @@ describe('Mail: Ghostmailer', function () {
|
||||||
mailer.send(mailDataNoDomain).then(function () {
|
mailer.send(mailDataNoDomain).then(function () {
|
||||||
done(new Error('Error message not shown.'));
|
done(new Error('Error message not shown.'));
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
error.message.should.startWith('Error: Failed to send email');
|
error.message.should.startWith('Failed to send email.');
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
@ -147,7 +147,7 @@ describe('Mail: Ghostmailer', function () {
|
||||||
mailer.send(mailDataNoServer).then(function () {
|
mailer.send(mailDataNoServer).then(function () {
|
||||||
done(new Error('Error message not shown.'));
|
done(new Error('Error message not shown.'));
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
error.message.should.eql('Error: Failed to send email.');
|
error.message.should.eql('Failed to send email.');
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
@ -158,7 +158,7 @@ describe('Mail: Ghostmailer', function () {
|
||||||
mailer.send(mailDataIncomplete).then(function () {
|
mailer.send(mailDataIncomplete).then(function () {
|
||||||
done(new Error('Error message not shown.'));
|
done(new Error('Error message not shown.'));
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
error.message.should.eql('Error: Incomplete message data.');
|
error.message.should.eql('Incomplete message data.');
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue