I need to send email by using Meteor. I did the code to regarding send mail. I have added a package email. But I got an error. I have no idea what happening. Check out the error & code below.
Error :
=> Meteor server running on: http://localhost:3000/
I20140118-10:54:35.900(5.5)? Exception while invoking method 'sendEmail' Referen
ceError: email is not defined
I20140118-10:54:35.989(5.5)? at Meteor.methods.sendEmail (app/loginapp.js:13
7:39)
I20140118-10:54:35.989(5.5)? at maybeAuditArgumentChecks (packages/livedata/
livedata_server.js:1349)
I20140118-10:54:35.990(5.5)? at packages/livedata/livedata_server.js:569
I20140118-10:54:35.990(5.5)? at _.extend.withValue (packages/meteor/dynamics
_nodejs.js:35)
I20140118-10:54:35.990(5.5)? at packages/livedata/livedata_server.js:568
I20140118-10:54:35.992(5.5)? at _.extend.withValue (packages/meteor/dynamics
_nodejs.js:35)
I20140118-10:54:35.992(5.5)? at _.extend.protocol_handlers.method (packages/
livedata/livedata_server.js:567)
I20140118-10:54:35.992(5.5)? at packages/livedata/livedata_server.js:472
JS Code :
if (Meteor.isClient)
{
Template.hello.greeting = function ()
{
return "Welcome to email.";
};
Template.hello.events
({
'click input' : function ()
{
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
// In your client code: asynchronously send an email
Meteor.call('sendEmail',
'*****#gmail.com',
'****#gmail.com',
'Hello from Meteor!',
'This is a test of Email.send.');
}
});
}
if (Meteor.isServer)
{
Meteor.startup(function ()
{
// code to run on server at startup
process.env.MAIL_URL = 'smtp://****#gmail.com:**password**#smtp.sendgrid.net:587';
});
Meteor.methods
({
sendEmail: function (to, from, subject, text)
{
console.log("*** sendEmail ***");
// Let other method calls from the same client start running,
// without waiting for the email sending to complete.
this.unblock();
Email.send
({
to: to,
from: from,
subject: subject,
text: text
});
}
});
}
i think you need to have email package installed
meteor add email
Related
I'm making an app that allows user to like and comment on other user post. I'm using Parse as my backend. I'm able to notified user everytime their post liked or commented. However if current user like or comment on their own post this current user still notified. How can I prevent this?
Here is the js code that I use:
Parse.Cloud.afterSave('Likes', function(request) {
// read pointer async
request.object.get("likedPost").fetch().then(function(like){
// 'post' is the commentedPost object here
var liker = like.get('createdBy');
// proceed with the rest of your code - unchanged
var query = new Parse.Query(Parse.Installation);
query.equalTo('jooveUser', liker);
Parse.Push.send({
where: query, // Set our Installation query.
data: {
alert: message = request.user.get('username') + ' liked your post',
badge: "Increment",
sound: "facebook_pop.mp3",
t : "l",
lid : request.object.id,
pid: request.object.get('likedPostId'),
lu : request.user.get('username'),
ca : request.object.createdAt,
pf : request.user.get('profilePicture')
}
}, {
success: function() {
console.log("push sent")
},
error: function(err) {
console.log("push not sent");
}
});
});
});
If I understand the context of where this code is correctly,
I recommend checking
if request.user.get("username") != Parse.CurrentUser.get("username")
Before sending out the push notification
Where is your cloud function being called from? If you're calling it from your ios code, then before you call the cloud code function, just prelude it with something like this:
if (PFUser.currentUser?.valueForKey("userName") as! String) != (parseUser.valueForKey("userName") as! String)
I'am trying to run a Skype SDK on my site, which will allow me to log into Skype initially. The code I'am using is from https://msdn.microsoft.com/EN-US/library/dn962162(v=office.16).aspx but when running the javascript through it complains of an undefined object. Here is the javascript code (ignore the $j, this is needed by us to run jQuery),
/**
* This script demonstrates how to sign the user in and how to sign it out.
*/
$j(function () {
'use strict'; // create an instance of the Application object;
// note, that different instances of Application may
// represent different users
var Application
var client;
Skype.initialize({
apiKey: 'SWX-BUILD-SDK',
}, function (api) {
Application = api.application;
client = new Application();
}, function (err) {
alert('some error occurred: ' + err);
});
// whenever state changes, display its value
client.signInManager.state.changed(function (state) {
$j('#application_state').text(state);
});
// when the user clicks on the "Sign In" button
$j('#signin').click(function () {
// start signing in
client.signInManager.signIn({
username: $j('#username').text(),
password: $j('#password').text()
}).then(
//onSuccess callback
function () {
// when the sign in operation succeeds display the user name
alert('Signed in as ' + client.personsAndGroupsManager.mePerson.displayName());
},
//onFailure callback
function (error) {
// if something goes wrong in either of the steps above,
// display the error message
alert(error || 'Cannot sign in');
});
});
// when the user clicks on the "Sign Out" button
$j('#signout').click(function () {
// start signing out
client.signInManager.signOut()
.then(
//onSuccess callback
function () {
// and report the success
alert('Signed out');
},
//onFailure callback
function (error) {
// or a failure
alert(error || 'Cannot sign in');
});
});
});
When I run this through, it doesn't enter into the "Skype.initialize({" code but jumps to "client.signInManager.state.changed(function (state) {", which is when it throws this error "Uncaught TypeError: Cannot read property 'signInManager' of undefined". When running this though the source debugger in chrome it shows that "Application" is undefined and that "client" is also undefined. So my question is why aren't these 2 objects getting initialised in the Skype.initialize code?
You will have to add the listener, after the client is initialized. So in the initialize "success" callback. The way you have it implemented at the moment, the script tries to add the listener before the client is initialized, on an undefined object attribute, hence the error.
Simple package. Does something like as follows.
CylonMessages = new Mongo.Collection('_cylon_messages');
if (Meteor.isServer) {
class CylonSocket extends net.Socket {
constructor(name, host, port) {
this._name = name;
this.on('connect', Meteor.bindEnvironment(function () {
console.log('Connected'); // use this to confirm the action happened
CylonMessages.insert({
socket: name,
message: 'Connected.'
});
}));
this.connect(port, host);
}
}
}
My package.js includes the cylon messages and cylon socket.
api.export('CylonMessages', both);
api.export('CylonSocket', 'server');
api.export('Cylon', 'server');
I also create a simple publication.
Meteor.publish(null, function () {
return CylonMessages.find();
}, { is_auto: true });
However, nothing is ever added to the collection. The console.log runs, so I know that they are running the callback on connect. I do get the following message.
There is no such publish handler named: undefined
Why isn't my collection being written to? What is being done that's wrong in meteor terms?
I need to test a protractor test case in which a user signs up, receives an email, goes to the link provided in the email and fills up his/her details in activation signup form.
The problem is how can I get the redeem token from the email. My email has a link to the activation page which has the auth token like following:
http://127.0.0.1:3000/#/signup/redeem/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJlOTRhYzY3MC1kYTNlLTQyYTUtODVkZS02NDU4ZjVmZGMwYjAiLCJzdWIiOiJ0ZXN0QGNvZWYuY28iLCJpYXQiOjE0Mjc0OTM5MDMsImV4cCI6MTQyODA5ODcwM30.
But how do I fetch that token so that I can build the url or how can I click that button in my email so that I can complete the flow ? I am using mailcatcher to simulate email.
This is something I've solved recently. Hope the solution would also apply for your use-case.
Prerequisites:
mail-listener2 package
understanding of the concept of promises
Step by step instructions:
Install mail-listener2:
npm install mail-listener2 --save-dev
In your protractor config initialize Mail Listener and make it available globally:
onPrepare: function () {
var MailListener = require("mail-listener2");
// here goes your email connection configuration
var mailListener = new MailListener({
username: "imap-username",
password: "imap-password",
host: "imap-host",
port: 993, // imap port
tls: true,
tlsOptions: { rejectUnauthorized: false },
mailbox: "INBOX", // mailbox to monitor
searchFilter: ["UNSEEN", "FLAGGED"], // the search filter being used after an IDLE notification has been retrieved
markSeen: true, // all fetched email willbe marked as seen and not fetched next time
fetchUnreadOnStart: true, // use it only if you want to get all unread email on lib start. Default is `false`,
mailParserOptions: {streamAttachments: true}, // options to be passed to mailParser lib.
attachments: true, // download attachments as they are encountered to the project directory
attachmentOptions: { directory: "attachments/" } // specify a download directory for attachments
});
mailListener.start();
mailListener.on("server:connected", function(){
console.log("Mail listener initialized");
});
global.mailListener = mailListener;
}),
onCleanUp: function () {
mailListener.stop();
},
Create a helper getLastEmail() function which would wait for an email to be retrieved:
function getLastEmail() {
var deferred = protractor.promise.defer();
console.log("Waiting for an email...");
mailListener.on("mail", function(mail){
deferred.fulfill(mail);
});
return deferred.promise;
};
Example test case:
describe("Sample test case", function () {
beforeEach(function () {
browser.get("/#login");
browser.waitForAngular();
});
it("should login with a registration code sent to an email", function () {
element(by.id("username")).sendKeys("MyUserName");
element(by.id("password")).sendKeys("MyPassword");
element(by.id("loginButton")).click();
browser.controlFlow().await(getLastEmail()).then(function (email) {
expect(email.subject).toEqual("New Registration Code");
expect(email.headers.to).toEqual("myemail#email.com");
// extract registration code from the email message
var pattern = /Registration code is: (\w+)/g;
var regCode = pattern.exec(email.text)[1];
console.log(regCode);
});
});
});
The solution I implemented was using mailcatcher API, if you scroll down a bit you'll find the following about the API:
A fairly RESTful URL schema means you can download a list of messages
in JSON from /messages, each message's metadata with
/messages/:id.json, and then the pertinent parts with
/messages/:id.html and /messages/:id.plain for the default HTML and
plain text version, /messages/:id/:cid for individual attachments by
CID, or the whole message with /messages/:id.source.
So we first fetched the whole json response, parse it and fetch the latest email id:
// Returns the last email id
function(emails, user) {
var email, recipient;
for(var i = emails.length - 1; i >= 0; i--) {
email = emails[i];
for(var j = 0; j < email.recipients.length ; j++) {
recipient = email.recipients[j];
if(recipient == "<"+user+">") {
return email.id;
}
}
}
};
using that email id we can get the body of the email by hitting /messages/:id.plain(of course there are more variants like fetching the email source code or email rendered html, we only needed the message) then we can just parse the body to fetch what we want, following is the code:
browser.driver.get(mailcatcherUrl+"/messages");
browser.driver.findElement(by.tagName('body')).getText().then(function(response) {
var emails, lastEmailId, partialTokens ;
emails = JSON.parse(response);
lastEmailId = getLastEmailId(emails, user);
browser.driver.get(mailcatcherUrl+"/messages/"+lastEmailId+".plain");
browser.driver.findElement(by.tagName('body')).getText().then(function(lastEmail) {
// use latestEmail to get what you want.
});
});
And Cheers!
I had to do the same thing but the mail testing server we were using did not have imap support.
So in case anyone runs into the same issue, I achieved a similar solution as alecxe using mailpop3 npm library.
The thing with the pop3 client, however, was that it doesn't act as a listener so we had to define a helper function that would connect, login and fetch the latest email when we needed to test the latest email.
Something like this:
function getLastEmail() {
var deferred = protractor.promise.defer();
var POP3Client = require("mailpop3");
var client = new POP3Client(port, host, {
tlserrs: false,
enabletls: true,
debug: false
});
client.on("connect", function() {
console.log("CONNECT success");
client.login(username, password);
});
client.on("login", function(status, rawdata) {
if (status) {
console.log("LOGIN/PASS success");
client.retr(1);
} else {
console.log("LOGIN/PASS failed");
client.quit();
}
});
client.on("retr", function(status, msgnumber, data, rawdata) {
if (status === true) {
console.log("RETR success for msgnumber " + msgnumber);
deferred.fulfill(data);
} else {
console.log("RETR failed for msgnumber " + msgnumber);
}
client.quit();
});
return deferred.promise;
}
I'm trying to send an "app" invite to user friends using the Facebook JavaScript SDK.
Here is a template event when click the Facebook button:
"click #fb": function (e, tmp) {
Meteor.loginWithFacebook({
requestPermissions: ['user_likes',
'friends_about_me',
'user_birthday',
'email',
'user_location',
'user_work_history',
'read_friendlists',
'friends_groups',
'user_groups']
}, function (err) {
if (err) {
console.log("error when login with facebook " + err);
} else {
FB.api('/' + Meteor.user().services.facebook.id + '/friends', { fields: 'name,picture' }, function (response) {
if (response && response.data) {
friends = response.data;
friends_dep.changed();
}
});
}
});
}
after that i want the user to invite people to my app, my code looks like this (another template event):
FB.ui({method: 'apprequests',
message: 'My Great Request'
}, function(response) {
if (response && response.post_id) {
alert('Post was published.');
} else {
alert('Post was not published.');
}
}
);
And it's working. There is a Facebook dialog with all the user friends, but when trying to send the message, I get the response error = 'Post was not published.'
What am I doing wrong here?
Basically the user can build a group - and I want the user to be able to invite his facebook friends into that group. Is there anyway that when sending the request the reciver will just press "yes" and will be automatically added to the sender group?
note I'm using my local machine aka localhost:3000
Can you try removing the && response.post_id portion from the if statement?
According to the Facebook API docs for the Requests Dialog: https://developers.facebook.com/docs/reference/dialogs/requests/ the response will just have 'request' and 'to' data. It looks like you've copy and pasted your callback from an example they give for the Posts Dialog. If you still get an error after removing this then you aren't getting a response, I am unsure how the JS SDK handles responses. If you can get other API calls to work using js sdk then I'm really not sure.
I recently worked with the Facebook API and opted not to use the JS SDK because it seemed to be at odds with using the accounts-facebook package. I'm curious if you're using that too.
Some Facebook API calls like creating a Post (and possibly this one) do require a dialog box, I'll outline how I got around this without using the JS SDK in case it helps you or anyone else. I would just form the URL client side and open a popup window e.g. here's how I handled sending a post:
'click .send-message': function() {
var recipient = this.facebook_id;
var config = Accounts.loginServiceConfiguration.findOne({service: 'facebook'});
var url = "http://www.facebook.com/dialog/feed?app_id=" + config.appId +
"&display=popup&to=" + recipient + "&redirect_uri=" + Meteor.absoluteUrl('_fb?close');
window.open(url, "Create Post", "height=240,width=450,left=100,top=100");
}
Then to get the response server side:
WebApp.connectHandlers
.use(connect.query())
.use(function(req, res, next) {
if(typeof(Fiber)=="undefined") Fiber = Npm.require('fibers');
Fiber(function() {
try {
var barePath = req.url.substring(0, req.url.indexOf('?'));
var splitPath = barePath.split('/');
if (splitPath[1] !== '_fb') {
return next();
}
if (req.query.post_id) {
//process it here
}
res.writeHead(200, {'Content-Type': 'text/html'});
var content = '<html><head><script>window.close()</script></head></html>';
res.end(content, 'utf-8');
} catch (err) {
}
}).run();
});
This code is very similar to the code used in the oauth packages when opening the login popup and listening out for responses.