I'm trying to send a email using form and also save the history of all the email. and I have a field in database named success to track if the email has send or not. How to update values of a field from client script based on user activities or email sent status.
var success = app.models.ChangeSystem.fields.Success.possibleValues;
google.script.run
.withFailureHandler(function(error){
status.text = error.message;
success = False;
})
.withSuccessHandler(function(result){
status.text = 'Email sent';
success = True;
clearEmailForm();
})
.sendEmailMessage(to, subject, msg);
Here success is a field in my database. My script is sending email. and update the
I was expecting to update the value of success which has two possible values(I'm fine if I have to change the field to boolean). Anyone can give me a direction how to achieve that?? Thanks in Advance.
Typically if you are creating a record that has a dependency on an email being sent then you need to implement the email function and call back inside the success function of the record being created like so:
Lets say you have a form with a button that creates a record that has an email sent status field then your 'Submit Button' should have the following code:
var status = app.pages.Email.descendants.EmailStatus;
widget.datasource.createItem({
success: function(result) {
google.script.run
.withFailureHandler(function(e) {
status.text = e.message;
result.Success = false;
})
.withSuccessHandler(function() {
status.text = 'Email sent';
result.Success = true;
})
.sendEmailMessage(to, subject, msg);
},
failure: function(error) {
status.text = error.message;
}
});
Related
I am new to AppMaker but I have developer experience.
The application is a Project Tracker Application
What I expect to happen: When creating a project the user uses a User Picker to select the users associated with that project. When the project is created I want to email the users associated with that project.
The issue: On clicking the Add button addProject(addButton) client script function is called.
Inside this function sendEmailToAssignees(project, assignees) is called which should reach out to the Server script and run the notifyAboutProjectCreated(project, assignees) but that is not happening.
Things to know: With logging I never reach 'Trying to send email' so I seem to never reach my server script. Also, On client script when I comment out sendEmailToAssignees function everything runs smooth. I have looked at this documentation as a resource so I feel my implementation is okay. https://developers.google.com/appmaker/scripting/client#client_script_examples
The final error message I get is:
Failed due to illegal value in property: a at addProject
(AddProject:110:24) at
AddProject.Container.PanelAddProject.Form1.Spring.ButtonAdd.onClick:1:1
Am I missing something here? Any help would be greatly appreciated. Thank you!
Client Script
function sendEmailToAssignees(project, assignees) {
google.script.run
.withSuccessHandler(function() {
console.log('Sending Email Success');
}).withFailureHandler(function(err) {
console.log('Error Sending Email: ' + JSON.stringify(err));
})
.notifyAboutProjectCreated(project, assignees);
}
function addProject(addButton) {
if (!addButton.root.validate()) {
return;
}
addButton.datasource.createItem(function(record) {
var page = app.pages.AddProject;
var pageWidgets = page.descendants;
var trainees = pageWidgets.AssigneesGrid.datasource.items;
var traineesEmails = trainees.map(function(trainee) {
return trainee.PrimaryEmail;
});
record.Assignee = traineesEmails.toString();
var assignees = traineesEmails.toString();
var project = record;
updateAllProjects(record);
console.log('update all projects done');
sendEmailToAssignees(project, assignees);
console.log('Send Email done');
if (app.currentPage !== app.pages.ViewProject) {
return;
}
gotoViewProjectPageByKey(record._key, true);
});
gotoViewProjectPageByParams();
}
Server Script
function notifyAboutProjectCreated(project, assignees) {
console.log('Trying to send email');
if (!project) {
return;
}
var settings = getAppSettingsRecord_()[0];
if (!settings.EnableEmailNotifications) {
return;
}
var data = {
appUrl: settings.AppUrl,
assignee: project.Assignee,
owner: project.Owner,
startDate: project.StartDate,
endDate: project.EndDate,
jobType: project.Type,
jobId: project.Id
};
// Email Subject
var subjectTemplate = HtmlService.createTemplate(settings.NotificationEmailSubjectJob);
subjectTemplate.data = data;
var subject = subjectTemplate.evaluate().getContent();
// Email Body
var emailTemplate =
HtmlService.createTemplate(settings.NotificationEmailBodyJob);
emailTemplate.data = data;
var htmlBody = emailTemplate.evaluate().getContent();
console.log('About to send email to:', assignees);
sendEmail_(null, assignees, subject, htmlBody);
}
The reason you are getting this error is because you are trying to pass the client "project record" to the server. If you need to access the project, then pass the record key to the server and then access the record on the server using the key.
CLIENT:
function sendEmailToAssignees(project, assignees) {
var projectKey = project._key;
google.script.run
.withSuccessHandler(function() {
console.log('Sending Email Success');
}).withFailureHandler(function(err) {
console.log('Error Sending Email: ' + JSON.stringify(err));
})
.notifyAboutProjectCreated(projectKey , assignees);
}
SERVER:
function notifyAboutProjectCreated(projectKey, assignees) {
console.log('Trying to send email');
var project = app.models.<PROJECTSMODEL>.getRecord(projectKey);
if (!project) {
return;
}
//Rest of the logic
}
The project record object in the client is not the same as the project record object in the server; hence the ilegal property value error.
Is there a way to check if email is verified through cloud functions
i.e. if I have a uid for the user, can I check if the email is verified for that particular user. In my use case, I need to make sure that email is verified before transaction is executed. I want to check it server side
Sample cloud function:
exports.executeTransaction = functions.https.onCall((data,context)=>{
const userid = context.auth.uid
//Check if email is verified
//I want to use context variable to somehow extract whether email is verified. Is there a way to do it ?
//Execute Transaction if email is verified
})
Never Mind, I managed to figure it out.
See following for anyone with similar issue:
exports.executeTransaction = functions.https.onCall((data,context)=>{
const userid = context.auth.uid
//Check if email is verified
return admin.auth().getUser(context.auth.uid).then(user => {
//Check if email verified
if(user.emailVerified)
{
return "Verified"
}
else{
console.log("User Email not verified")
return "Not Verified"
}
}).catch(function(err){
console.log(err)
throw new functions.https.HttpsError('Error Validating', err.message, err)
})
})
According to the docs, context includes decodedIdToken, which already contains an email_verified field.
Thus all you need to do is this:
exports.executeTransaction = functions.https.onCall((data, context) => {
const { token } = context.auth;
if (!token.firebase.email_verified)
throw new functions.https.HttpsError(
"failed-precondition",
"The function must be called while authenticated."
);
// ...do stuff
})
https://firebase.google.com/docs/reference/functions/functions.https#.CallableContext
https://firebase.google.com/docs/reference/admin/node/admin.auth.DecodedIdToken#email_verified
I have to login with firebse but after enter email and password I got error in the console every time "the password is invalid or the user does not have a password"
But my UID is generated properly in firebase. I don't understand why every time I get an error Anyone know how to fix this issue?
//createUserAccount after click on button
createUserAccount(event){
//Get the input value assign into object format and pass in the API
let object = {
"email" : this.createAccountForm.value.email,
"password" : this.createAccountForm.value.newPassword
}
//Call the signupUserFB function for get the add the user into the firebase
self.authData.signupUserFB(function(isSuccess, newUser){
console.log("signupUserFB isSuccess: " + isSuccess);
}, object);
}
//singInUserInFb for store user in FB
singInUserInFb(callback: any, object : any): any {
var self = this;
//Enable the loader after call the FB function
var loading = self.loadingCtrl.create({
content: "Loading..."
});
loading.present();
//passing the email & password.
this.fireAuth.signInWithEmailAndPassword(object.email, object.password).then((authData) => {
console.log(authData.uid);
});
}
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.
I just got done with the rough draft of my app, and thought it was time to remove autopublish and insecure mode. I started transfering all the stray update and insert methods I had been calling on the client to methods. But now I'm having trouble returning a username from an ID.
My function before: (that worked, until I removed autopublish)
challenger: function() {
var postId = Session.get('activePost');
var post = Posts.findOne(postId);
if (post.challenger !== null) {
var challenger = Meteor.users.findOne(post.challenger);
return challenger.username;
}
return false;
}
Now what I'm trying:
Template.lobby.helpers({
challenger: function() {
var postId = Session.get('activePost');
var post = Posts.findOne(postId);
if (post.challenger !== null) {
var userId = post.challenger;
Meteor.call('getUsername', userId, function (err, result) {
if (err) {
console.log(err);
}
return result;
});
}
return false;
},
Using:
Meteor.methods({
getUsername: function(userId) {
var user = Meteor.users.findOne({_id: userId});
var username = user.username;
return username;
},
...
})
I have tried blocking the code, returning values only once they're defined, and console.logging in the call-callback (which returned the correct username to console, but the view remained unchanged)
Hoping someone can find the obvious mistake I'm making, because I've tried for 3 hours now and I can't figure out why the value would be returned in console but not returned to the template.
Helpers need to run synchronously and should not have any side effects. Instead of calling a method to retrieve the user, you should ensure the user(s) you need for that route/template are published. For example your router could wait on subscriptions for both the active post and the post's challenger. Once the client has the necessary documents, you can revert to your original code.