When a verification email is sent, a link is added that allows the new user to click on and complete the registration.
The link points to a host address and port, which is where the Strongloop API is hosted on. My issue is that I would like to have the clickable link point to a host address that is different than the email server address that is sending the verification email.
For example, let's say that my email server is Mailgun (I know they have API and SMTP options, so let's assume we go with SMTP to illustrate my point), and my Strongloop app is hosted by Heroku.
So when configuring the verification call, if I set the options host and port to Mailgun's address, the email gets sent fine but the link will also point to Malgun's host and address instead of Heroku's, and obviously this will not work.
On the other hand, if I put the Heroku host and port in the configuration, the email will never get sent because it will try to use Heroku as the email server.
Since the email verification procedure is a prototype defined in node_modules/loopback/common/models/user.js, I can't modify this code as every deploy in Heroku re-installs Strongloop every time (not sure if this can be avoided or not, but for now I'm not aware I can).
Also, since the token is generated inside the prototype's verify() method, I'm guessing I can't easily extract the email verification process, unless I do the token generation outside (and also persist to DB, build the link, etc), since the token is generated as part of the link generation code.
I.e. in node_modules/loopback/common/models/user.js
User.prototype.verify = function(options, fn) {
...
options.host = options.host || (app && app.get('host'));
options.port = options.port || (app && app.get('port'));
options.restApiRoot = options.restApiRoot || (app && app.get('restApiRoot')) || '/api';
options.verifyHref = options.verifyHref ||
options.protocol +
'://' +
options.host +
':' +
options.port +
options.restApiRoot +
userModel.http.path +
userModel.sharedClass.find('confirm', true).http.path +
'?uid=' +
options.user.id +
'&redirect=' +
options.redirect;
// Email model
var Email = options.mailer || this.constructor.email || registry.getModelByType(loopback.Email);
var tokenGenerator = options.generateVerificationToken || User.generateVerificationToken;
tokenGenerator(user, function(err, token) {
if (err) { return fn(err); }
user.verificationToken = token;
user.save(function(err) {
if (err) {
fn(err);
} else {
sendEmail(user); //sendEmail() is defined inside verify(), and the options object passed to Email is the same, so the same host and port are used
}
});
In my overriding method (inside server/boot/0-model-override.js) I have:
User.afterRemote('create', function(context, user, next) {
var options = {
type: 'email',
to: user.email,
from: myEmailAddress,
subject: 'My subject',
template: path.resolve(__dirname, '../views/verify.ejs'),
redirect: '/verified',
user: user,
protocol: 'https',
host : hostAddress,
port : portNumber
};
user.verify(options, function(err, response) {
if (err) {
next(err);
return;
}
console.log("Account verification email sent to " + options.to);
next();
return;
});
});
And so the host and port in options is used for both link and email server address.
I have also tried to use the "mailer" field
i.e. adding
mailer: Email,
to the options, where Email is already correctly configured via the datasources.json file and model-config.json.
Also, I'm getting the email object as such:
var Email = app.models.Email;
So is there a way to accomplish this via configuration objects?
Or is there no other way than overriding the complete method, so I have to manually build the link, generate the token, etc, just so that I can use two different hoist addresses?
I would have guessed that people already using Strongloop hosted by Heroku, would want to send email from elsewhere and so this is probably a solved problem, but I just can't see how to easily do it.
Any pointers are greatly appreciated!
AkramEnter code here...