Add url link to email - meteor

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.

Related

Scraping an ASP.NET website with NodeJS

i am trying to login to my supplier website programatically and get the resseller price by code. i have my username and password provided by the supplier to use in the website which is powred by ASP.NET. i tried to use the request module but got no luck with it.
this the code i used so far :
var request = require('request');
var j = request.jar();
var request = request.defaults({ jar : j }) //it will make the session default for every request
//...
request({
url:"https://www.XXXXX.com/login.aspx",
method:"POST",
form:{
ctl00$cpholder$txtUserName:"YYYYYYYY",
ctl00$cpholder$txtPassword:"ZZZZZZZZ"
}
},
function(err,response,body){
console.log(err);
// here i try to access the product page like a reseller
request({
url:"https://www.XXXXXX.com/productdetails.aspx?id=20000028&itemno=90NB0CL1-M08420",
method:"GET",
}, function(err, response, body){
console.log(err);
//Some logic
});
});
}
this is the login form code ( in pastebin because it is very long )
https://pastebin.com/kwuRdLX4
please help

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

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

How to check if email already exist for a user (emails[0].address) before try to use it to change the email of another user?

I have a method to change the user's address (every user has only one address, so it's emails[0].address).
In the method, Accounts.addEmail(this.userId, newemail); block finely the adding of an emails[0].address if another user has the same. I receive in client the error.reason === 'Email already exists.' Great.
But before calling Accounts.addEmail(this.userId, newemail);, I need to call Accounts.removeEmail(this.userId, emailold); who will remove the old address and leave emails[0].address free for Accounts.addEmail(this.userId, newemail); (wich, when there is no email address in an account, use nicely by default emails[0].address).
So how can I handle and stop Accounts.removeEmail(this.userId, emailold); if newemail is used as emails[0].address by any other user?
Below my method.
Thanks
// Change Email Address of the User
Meteor.methods({
addNewEmail: function(emailold, newemail) {
// this function is executed in strict mode
'use strict';
// Consistency var check
check([emailold, newemail], [String]);
// Let other method calls from the same client start running,
// without waiting this one to complete.
this.unblock();
//Remove the old email address for the user (only one by default)
Accounts.removeEmail(this.userId, emailold);
//Add the new email address for the user: by default, setted to verified:false
Accounts.addEmail(this.userId, newemail);
// Send email verification to the new email address
Accounts.sendVerificationEmail(this.userId, newemail);
return true;
}
});
You can update the users collection directly, and handle any errors yourself. This is what I do:
Meteor.methods({
"users.changeEmail"(address) {
check(address, String);
const existingAddressCheck = Meteor.users.findOne({"emails.0.address": address});
if(existingAddressCheck) {
if(existingAddressCheck._id === Meteor.userId()) {
throw new Meteor.Error("users.changeEmail.sameEmail", "That's already your registered email address!");
} else {
throw new Meteor.Error("users.changeEmail.existing", "An account with that address already exists");
}
}
return Meteor.users.update({_id: Meteor.userId()}, {$set: {"emails.0": {address, verified: false}}});
}
});

How to emit data only to one client in Meteor streams

I am building a realtime game with Meteor streams. I need to update only one client - send a room ID from server. Users are not logged in so Meteor.userId() is null and therefore I can't use this: http://arunoda.github.io/meteor-streams/communication-patterns.html#streaming_private_page
There is only one URL (homepage) where all things happen. So I don't use any URL parameters for room. Everything is on the server.
I have tried to use Meteor.uuid() instead of Meteor.userId() but uuid is changed after each emit (which is strange).
In socket.io I would do this:
//clients is an array of connected socket ids
var clientIndex = clients.indexOf(socket.id);
io.sockets.socket(clients[clientIndex]).emit('message', 'hi client');
Is there any way to do this in Meteor streams or Meteor itself?
Well, this can be easily done if you decided to use database, but I guess it is not the best option if you have a large number of clients.
So another way to achieve this - without database - is to make a good use of the Meteor's publish/subscribe mechanism. Basically the way it could work is the following:
1. client asks server for a communication token (use Meteor.methods)
2. client subscribes to some (abstract) data set using that token
3. server publishes the required data based on the received token
So you will need to define a method - say getToken - on the server that generates tokens for new users (since you don't want to use accounts). This could be something more or less like this:
var clients = {}
Meteor.methods({
getToken: function () {
var token;
do {
token = Random.id();
} while (clients[token]);
clients[token] = {
dependency: new Deps.Dependency(),
messages: [],
};
return token;
},
});
A new client will need to ask for token and subscribe to the data stream:
Meteor.startup(function () {
Meteor.call('getToken', function (error, myToken) {
// possibly use local storage to save the token for further use
if (!error) {
Meteor.subscribe('messages', myToken);
}
});
});
On the server you will need to define a custom publish method:
Meteor.publish('messages', function (token) {
var self = this;
if (!clients[token]) {
throw new Meteor.Error(403, 'Access deniend.');
}
send(token, 'hello my new client');
var handle = Deps.autorun(function () {
clients[token].dependency.depend();
while (clients[token].messages.length) {
self.added('messages', Random.id(), {
message: clients[token].messages.shift()
});
}
});
self.ready();
self.onStop(function () {
handle.stop();
});
});
and the send function could defined as follows:
var send = function (token, message) {
if (clients[token]) {
clients[token].messages.push(message);
clients[token].dependency.changed();
}
}
That's a method I would use. Please check if it works for you.
I think using Meteor.onConnection() like a login would enable you to do what you want pretty easily in a publish function.
Something like this:
Messages = new Meteor.Collection( 'messages' );
if ( Meteor.isServer ){
var Connections = new Meteor.Collection( 'connections' );
Meteor.onConnection( function( connection ){
var connectionMongoId = Connections.insert( connection );
//example Message
Message.insert( {connectionId: connection.id, msg: "Welcome"});
//remove users when they disconnect
connection.onClose = function(){
Connections.remove( connectionMongoId );
};
});
Meteor.publish( 'messages', function(){
var self = this;
var connectionId = self.connection.id;
return Messages.find( {connectionId: connectionId});
});
}
if ( Meteor.isClient ){
Meteor.subscribe('messages');
Template.myTemplate.messages = function(){
//show all user messages in template
return Messages.find();
};
}
I have used database backed collections here since they are the default but the database is not necessary. Making Messages a collection makes the reactive publishing easy whenever a new message is inserted.
One way that this is different from streams is that all the messages sent to all clients will end up being kept in server memory as it tries to keeps track of all data sent. If that is really undesirable then you could use a Meteor.method so send data instead and just use publish to notify a user a new message is available so call the method and get it.
Anyway this is how I would start.

How to get Meteor.user() to return on the server side?

in a file called /server/main.js (in order to ensure it is loaded last).
console.dir(Meteor.user());
Throws:
Error: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.
So I try to use, in the same file:
console.dir(this.userId);
returns:
undefined
so, not giving up, I'm thinking "that's fine I'll just read from the cookies in the header":
var connect = Npm.require('connect');
__meteor_bootstrap__.app.use(connect.query()).use(function(req, res, next) {
console.dir(req.headers);
next();
});
.... returns nothing in terms of cookies except for 'cookie: 'uvf=1''
I'm not sure what to conclude - this is senseless as I can otherwise use the Meteor.Account framework just fine, read/set user properties, etc. The server is clearly aware of the user, and the current user clearly logged in.
I'm at a complete loss, any explanation / hint / pointer would be greatly appreciated.
You have to use Meteor.user() in a place where a request is made from the client (such as a Meteor.methods or a Meteor.publish).
It can't be placed anywhere else because meteor wouldn't know at that point in the code the user is supposed to bound to. If there is a place a request of some form is made from the client it can do this:
In a Meteor.publish:
Meteor.publish("collection", function() {
//returns undefined if not logged in so check if logged in first
if(this.userId) {
var user = Meteor.users.findOne(this.userId);
//var user is the same info as would be given in Meteor.user();
}
});
In a Meteor.methods:
Meteor.methods({
"test":function() {
//should print the user details if logged in, undefined otherwise.
console.log(Meteor.user());
}
}
To use Meteor.user() on a server side route:
You need Meteor router installed as a package via meteorite to allow you to have a server rendered page. (installed via mrt install router)
A server side route could then handle the web request:
Meteor.Router.add('/awebpage', function(id) {
var userId = this.params.userid;
var logintoken = this.params.logintoken;
var isdirect = this.param.direct;
var user = Meteor.users.findOne({_id:userId,"services.resume.loginTokens.token":logintoken});
if(user) {
//the user is successfully logged in
return "You, "+user.profile.name+", are logged in!";
}
else
{
if(isdirect) {
return "<h3>Loading</h3><script>window.location.href="/awebpage?direct=true&userid="+localStorage.getItem("Meteor.userId") +"&logintoken="+localStorage.getItem("Meteor.loginToken")</script>";
}
else
{
return "Not logged in"
}
}
});
So now when you visit /awebpage it would check whether the user is logged in and do the thing you want when they are logged in. Initially there is a redirect to relay the data from localstorage back to the URI.
You can expose the userId with Meteor.publish() to global scope. Then you can use it with Meteor.Router's server side routes.
--
/server/publications.js
CurrentUserId = null;
Meteor.publish(null, function() {
CurrentUserId = this.userId;
});
-
/server/routes.js
Meteor.Router.add('/upload', 'POST', function() {
if (!CurrentUserId)
return [403, 'Forbidden'];
// proceed with upload...
});
You can use the logged in callback
Accounts.onLogin((obj)->
user = ob.user
)
Accounts.onLogin(function(obj){
var user = ob.user
})
I recently wrote a blog post describing solution to this: https://blog.hagmajer.com/server-side-routing-with-authentication-in-meteor-6625ed832a94.
You basically need to set up a server route using a https://atmospherejs.com/mhagmajer/server-router package and you can get current user with this.userId just like with Meteor methods.

Resources