How to send verification email from server to client's register email - meteor

I am using meteor for developing my application. I need to verify user as soon as he register himself. I used SendverificationEmail() method of meteor and i m getting link on the server side . Now i want to send that unique link to the client's register email. How it will done?

You will have to use meteor Email package to send email:
Meteor Email Package
After you have added package just write below code in your method to send an email
Email.send({ to, from, subject, text });

Sorry to See this post little late, but there are many folks out there who are willing to implement this even today. So below are the steps to achieve email verification flow.
NOTE: I am using Meteor 1.6.1.1, with Flow-routers + Blaze Templates. Also, make sure you have enabled 3rd party API access call to Gmail. You can do this from Gmail settings.
Import Packages: accounts-ui, accounts-password
In root_folder/server/ folder, inside main.js copy paste below code and make the necessary credential change to your file.
var username = 'asdasdasdas';
var password = 'sdasdasdasd';
var server = 'smtp.gmail.com';
var port = '465';
process.env.MAIL_URL = 'smtps://' +
encodeURIComponent(username) + ':' +
encodeURIComponent(password) + '#' +
encodeURIComponent(server) + ':' + port;
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
Accounts.emailTemplates.from = 'support_team#domain.com';
//-- Application name
Accounts.emailTemplates.siteName = 'Your Site Name';
//-- Subject line of the email.
Accounts.emailTemplates.verifyEmail.subject = function(user) {
return 'Email Confirmation.';
};
//-- Email text
Accounts.emailTemplates.verifyEmail.text = function(user, url) {
var newUrl = url.replace('/#','');
return 'Thank you for registering. Please click on the following link to verify your email address: \r\n' + newUrl;
};
// Configure to send the Email Verification mail as true
Accounts.config({
sendVerificationEmail: true,
restrictCreationByEmailDomain: function(email) {
var domain = email.slice(email.lastIndexOf("#")+1); // or regex
var allowed = ["gmail.com", "yahoo.co.in", "outlook.com", "yahoo.com", "yandex.com", "protonmail.com", "protonmail.ch", ];
return _.contains(allowed, domain);
},
loginExpirationInDays: 1
});
When you successfully create an account in Meteor app, you will get an email as below;
Inside the mail, You will see a link with route of pattern /verify-email/:token, hence go inside project/client/routes.js you need to add the route,
import { FlowRouter } from 'meteor/kadira:flow-router';
//force user to stay on home page instead of desired page
Accounts.onLogin(function(user){
var user = Meteor.user();
if(user.emails && user.emails[0].verified){
FlowRouter.go('dashboard');
}
});
FlowRouter.route('/verify-email/:tokenId', {
name: 'verify-email',
action: function(params, queryParams) {
var token = FlowRouter.getParam("tokenId");
console.log(token);
Accounts.verifyEmail(token, function(err){
if(!err){
FlowRouter.go("dashboard");
} else {
FlowRouter.go("error-page");
}
});
},
});
In case if you are using iron-router, you can refer this LINK

Related

I am using firebase as a Web client for an app to create a login system however when I enter a username & password & press login it say server error

I am using firebase as a Web client for an app to create a login system however when I enter a username & password & press login it say server error.
How do I resolve the server error and what does it mean by server error?
Thank you and help would be appreciated☺😊😃
The code I used to create the Web client
var ROOT_URL = "https://exampleapp.firebaseio.com/"; // Change to your Firebase App
var FIREBASE_CREDENTIAL = "yourAppSecret"; // Change to your Firebase App Secret
var firebase = {
register : function (email, password, callback) {
var emailReplace = email.replace(/\./g, ",");
var beginRegister = function () {
var requestObj = { "email" : email, "password" : password };
var requestJSON = JSON.stringify(requestObj);
var wcRegister = new SMF.Net.WebClient({
URL : ROOT_URL + "Users/" + emailReplace + ".json?auth=" + FIREBASE_CREDENTIAL,
httpMethod : "POST",
requestHeaders : ['Content-Type:application/json', 'X-HTTP-Method-Override:PATCH'],
requestBody : requestJSON,
onSyndicationSuccess : function (e) {
alert("Begin register success");
},
onServerError : function (e) {
alert("Begin register error");
}
});
wcRegister.run(true);
};
var isTaken = new SMF.Net.WebClient({
URL : ROOT_URL + "Users/" + emailReplace + ".json?auth=" + FIREBASE_CREDENTIAL,
httpMethod : "GET",
requestHeaders : ["Content-Type:application/json"],
onSyndicationSuccess : function (e) {
alert("Is taken sucess");
var response = JSON.parse(isTaken.responseText);
if (response !== null) {
//Email is taken, do something
} else {
beginRegister(); //Email is not taken, continue
}
}, onServerError : function (e) {
//Server Error, do something
alert("Is taken error");
}
});
isTaken.run();
}
};
I am using smartface app studio.
Server error means that your request to given URL couldn't successfully made. I have tested your code and it worked for me with my own firebase configurations.
If you are using custom certificate file, which located in Assets folder of your project and named 'cacert.pem', maybe that CA don't accept that domain I don't know. You can check error message in onServerError with
alert(e.message);
This will give more detailed information about error. Also did you test url and body with another HTTP request tool like hurl.it?
Well, I know it's working because I wrote this code :P but probably it's because you didn't change your Firebase rules to access with your app secret or you didn't properly add the variables values. Did you change FIREBASE_CREDENTIAL to your app secret? Did you change ROOT_URL to the root url of your Firebase app?
If you did both, check your firebase rules, it should be something like:
{
"rules": {
".read": "auth == 'YOUR_APP_SECRET'",
".write": "auth == 'YOUR_APP_SECRET'"
}
}
Remember to change YOUR_APP_SECRET with your app secret (pretty logical, huh :P).
If you already done that and still it doesn't work, check if you are calling the function right, and before trying to log in an user, register him. By the way, the code that you showed is incomplete, it doesn't have the login function, this could be the problem too.
And just to you know, if you want to add more info about the user, you can modify the functions to add as many parameters as you want, but this would be another question right? :P

Add url link to email

I'm trying to create a custom url and pass it into a HTML email. The email works however right now I have to manually change the url when I push the application live to contain the live url address. Is there a way to do this?
What I'm trying to do:
Dev enviroment
localhost:3000/profile
Live enviroment
www.address.com/profile
--
sendEmail: function (subject, userId) {
check([subject, userId], [String]);
// Let other method calls from the same client start running,
// without waiting for the email sending to complete.
this.unblock();
SSR.compileTemplate( 'htmlEmail', Assets.getText( 'sendEmail.html' ) );
// to find the users info for the logged in users
// var user = Meteor.user();
var emailData = {
url: Meteor.absoluteUrl() + "/profile"
};
Email.send({
to: to,
from: from,
subject: subject,
html: SSR.render( 'htmlEmail', emailData )
});
}
You need to configure ROOT_URL variable in your production environment. When you do so, the method Meteor.absoluteUrl("/profile") will return the correct URL.

Meteor registration verification email not sent on production

I have tested my meteor app on dev and the verification email is sent out. But on production it is not. Could it maybe the content of smtp.js? My code is as follows:
// server/smtp.js
Meteor.startup(function () {
var smtp = {
username: 'dummy#wbs.co.za',
password: 'hw783378hjshd',
server: 'smtp.wbs.co.za',
port: 25
}
process.env.MAIL_URL = 'smtp://' + encodeURIComponent(smtp.username) + ':' + encodeURIComponent(smtp.password)
+ '#' + encodeURIComponent(smtp.server) + ':' + smtp.port;
});
// (server-side)
Meteor.startup(function() {
// By default, the email is sent from no-reply#meteor.com. If you wish to receive email from users asking for help with their account, be sure to set this to an email address that you can receive email at.
Accounts.emailTemplates.from = 'NOREPLY <no-reply#meteor.com>';
// The public name of your application. Defaults to the DNS name of the application (eg: awesome.meteor.com).
Accounts.emailTemplates.siteName = 'No Reply';
// A Function that takes a user object and returns a String for the subject line of the email.
Accounts.emailTemplates.verifyEmail.subject = function(user) {
return 'Confirm Your Email Address';
};
// A Function that takes a user object and a url, and returns the body text for the email.
// Note: if you need to return HTML instead, use Accounts.emailTemplates.verifyEmail.html
Accounts.emailTemplates.verifyEmail.html = function(user, url) {
return 'click on the following link to verify your email address: ' + url;
};
});
// (server-side) called whenever a login is attempted
Accounts.validateLoginAttempt(function(attempt){
if (attempt.user && attempt.user.emails && !attempt.user.emails[0].verified ) {
console.log('email not verified');
throw new Meteor.Error(403, 'Verification email has been sent to your email address. Use the url in the email to verify yourself.');
return false; // the login is aborted
}
return true;
});
Please help.

Custom Meteor enroll template

In my application I want to seed the database with users and send them an enrollment link to activate their account (and choose a password). I also want them to verify/change some profile data.
On the server I seed the database like this:
Meteor.startup(function () {
if(Meteor.users.find().count() === 0) {
var user_id = Accounts.createUser({ email: 'some#email.com', profile: { some: 'profile' } });
Accounts.sendEnrollmentEmail(user_id);
}
})
The enrollment link is sent as expected, but I want to create a custom template for when the url in the email is clicked. Preferably handled by iron-router. (Not using the accounts-ui package).
I tried things like redirecting the user to a custom route like this:
var doneCallback, token;
Accounts.onEnrollmentLink(function (token, done) {
doneCallback = done;
token = token;
Router.go('MemberEnroll')
});
which is not working (it changes the url but not rendering my template)
I also tried to change the enroll URL on the server like this:
Accounts.urls.enrollAccount = function (token) {
return Meteor.absoluteUrl('members/enroll/' + token);
};
But when I do this, the Accounts.onEnrollmentLink callback does not fire.
Also, changing the URL is not documented so I'm not sure its a good practice at all.
Any help is appreciated.
In my application I'm doing like this
this.route('enroll', {
path: '/enroll-account/:token',
template: 'enroll_page',
onBeforeAction: function() {
Meteor.logout();
Session.set('_resetPasswordToken', this.params.token);
this.subscribe('enrolledUser', this.params.token).wait();
},
data: function() {
if(this.ready()){
return {
enrolledUser: Meteor.users.findOne()
}
}
}
})
As enrollment url is like this
http://www.yoursite.com/enroll-account/hkhk32434kh42hjkhk43
when users click on the link they will redirect to this template and you can render your template
In my publication
Meteor.publish('enrolledUser', function(token) {
return Meteor.users.find({"services.password.reset.token": token});
});
After taking the password from the user
Accounts.resetPassword(token, creds.password,function(e,r){
if(e){
alert("Sorry we could not reset your password. Please try again.");
}else{
alert("Logged In");
Router.go('/');
}
})
enroll link
Accounts.urls.enrollAccount = function (token) {
return Meteor.absoluteUrl('enroll-account/' + token);
};
Im afraid now isnt possible, what i did is changing the html and css using "rendered" function but it has some probs with delay
Meteor.startup(function(){
Template["_enrollAccountDialog"].rendered = function(){
document.getElementById('enroll-account-password-label').innerHTML = 'Escolha sua senha';
$('.accounts-dialog').css('background-color','#f4f5f5');
$('.accounts-dialog').css('text-align','center');
$('.accounts-dialog').removeAttr('width');
document.getElementById('login-buttons-enroll-account-button').className = ' create-account-button';
document.getElementById('login-buttons-enroll-account-button').innerHTML = 'Criar conta';
}
});

How to make sign-up invitation only?

Using Meteor accounts (and accounts-ui) is there an easy way to make new user sign-ups invitation only? For example by providing an invitation link or an invitation code.
The only thing related I could find in the Meteor documentation is Meteor.sendEnrollmentEmail but it doesn't solve my problem.
You can do this with the built in package, but I found it alot easier and powerful to roll a simple implementation.
You'll need to:
Create a collection, eg UserInvitations to contain the invites to become a user.
Create UI for making UserInvitations / insert some using meteor mongo
Using iron-router or similar create a route, eg:
Router.map ->
#route 'register',
path: '/register/:invitationId'
template: 'userRegistration'
data: ->
return {
invitationId: #params.invitationId
}
onBeforeAction: ->
if Meteor.userId()?
Router.go('home')
return
When the form in userRegistration is submitted - call
Accounts.createUser({invitationId: Template.instance().data.invitationId /*,.. other fields */})
On the server, make an Accounts.onCreateUser hook to pass through the invitationId from options to the user
Accounts.onCreateUser(function(options, user){
user.invitationId = options.invitationId
return user;
});
Also, on the server make an Accounts.validateNewUser hook to check the invitationId and mark the invitation as used
Accounts.validateNewUser(function(user){
check(user.invitationId, String);
// validate invitation
invitation = UserInvitations.findOne({_id: user.invitationId, used: false});
if (!invitation){
throw new Meteor.Error(403, "Please provide a valid invitation");
}
// prevent the token being re-used.
UserInvitations.update({_id: user.invitationId, used: false}, {$set: {used: true}});
return true
});
Now, only users that have a valid unused invitationId can register.
EDIT: Oct 2014 - Updated to use meteor 0.9.x API's
To do it with the built in stuff, you can plumb together the existing Accounts.sendEnrollmentEmail - however it's a little more complicated than the other solution given.
Using the example code below, call the enroll method as such:
Meteor.call('enroll', 'john.smith', 'js#harvard.edu', {name: 'John Smith'});
Meteor will then email the user a link (You can configure the template with Accounts.emailTemplates)
When they click the link, meteor calls the function passed to Accounts.onEnrollmentLink - in this case you can take them to a password setup page; but you have to mess around with their done callback.
Modify the following code, where it says INSERT XXX HERE ; then in your code call SomeGlobalEnrollmentObjectThing.cancel() if the user cancels, or SomeGlobalEnrollmentObjectThing.complete(theUsersNewPassword) if they submit the new password.
if (Meteor.isServer){
Meteor.methods({
"enroll": function(username, email, profile){
var userId;
check(username, String);
check(email, String); // Or email validator
check(profile, {
name: String
}); // your own schema
// check that the current user is privileged (using roles package)
if (!Roles.isInRole(this.userId, 'admin')){
throw new Meteor.Error(403);
}
userId = Accounts.createUser({
username: username,
email: email,
profile: profile
});
Accounts.sendEnrollmentEmail(userId);
}
});
} else {
// uses `underscore`, `reactive-var` and `tracker` packages
function Enrollment(){
this.computation = null;
this.token = new ReactiveVar(null);
this.password = new ReactiveVar(null);
this.cancelled = new ReactiveVar(false);
this.done = null;
this._bind();
}
_.extend(Enrollment.prototype, {
_bind: function(){
Accounts.onEnrollmentLink(_.bind(this.action, this));
},
reset: function(){
this.token.set(null);
this.password.set(null);
this.cancelled.set(false);
this.done = null;
if (this.computation !== null){
this.computation.stop();
this.computation = null;
}
},
cancel: function(){
this.cancelled.set(true);
},
complete: function(password){
this.password.set(password);
},
action: function(token, done){
this.reset();
this.token.set(token);
this.done = done;
this.computation = Tracker.autorun(_.bind(this._computation, this));
// --- INSERT REDIRECT LOGIC HERE [TAKE TO PASSWORD SETUP PAGE]--- //
},
_computation: function(){
var password;
if (this.cancelled.get()){
this.reset();
this.done();
// --- INSERT REDIRECT LOGIC HERE [USER CANCELLED]--- //
} else {
password = this.password.get();
if (password !== null){
Accounts.resetPassword(this.token.get(), password, _.bind(this._complete, this));
}
}
},
_complete: function(err){
// TODO - check if we were reset before callback completed
this.reset();
this.done();
if (err){
// --- INSERT REDIRECT LOGIC HERE [RESET FAILED] --- //
} else {
// --- INSERT REDIRECT LOGIC HERE [SUCCESS] --- //
}
}
});
SomeGlobalEnrollmentObjectThing = new Enrollment();
}
I have created a specific solution to this, since all the other solutions only allow you to explicitly create password-based accounts. The t3db0t:accounts-invite package allows account creation with any service only when you allow them, such as with an 'accept invitation' route. Live demo here.

Resources