Cannot get the getCallbackTokenAsync to function correctly - outlook

I am a newbie to outlook js. I am developing a very simple add-in. The add-in simply will forward a selected email to a defined email address. So we click a button and forward the message. My command handler gets called, but that is about all I have gotten to work. The first problem is the authorization does not appear to work. I have followed the example on https://learn.microsoft.com/en-us/outlook/add-ins/use-rest-api.
The permission in my manifest is set to ReadWriteMailbox.
var accessToken;
Office.onReady(info => {
// If needed, Office.js is ready to be called
Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, function(result) {
if (result.status === "succeeded") {
accessToken = result.value;
} else {
accessToken = "error";
}
});
});
function MyButtonClick(event) {
const message = {
type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,
message: "Performed action. Access token: " + accessToken,
icon: "Icon.80x80",
persistent: true
}
Office.context.mailbox.item.notificationMessages.replaceAsync("action", message);
event.completed();
}
I have tried moving the getCallbackTokenAsync all around, but it seems not to work properly. The accessToken is always undefined.
I have been messing with this for the past day. So I am assuming I am missing something.
We are primarily targeting Outlook 2016 on the mac and windows 10.
Any thoughts?
Tom

Related

Window object is undefined after deploy to netlify

I want to build an email verification. After the user registers, the user gets an email and clicks on it for verification purposes. The email-link invokes a netlify lambda function (api end point). Inside the link is a jwt token, which I decode on the backend. I used
window.location.href
for it and sliced the part I needed and decoded it. On localhost, it works fine, however, if I deploy it to netlify, I get an
window is undefined
error. I read that you have to check for
typeof window !== 'undefined'
However, if I add that to my lambda function I don't get any console.log statements.
exports.handler = async (event, context, callback) => {
if (typeof window !== 'undefined') {
let url = window.location.href
let index = url.indexOf("=");
let token = url.slice(index+1)
console.log(token, 'token here')
const decoded = jwt.verify(token, process.env.SECRET);
console.log('confirm registration route triggered',decoded)
if (decoded) {
const { email } = decoded;
console.log(decoded, 'decoded here')
User.findOneAndUpdate({email: email}, {verified: true },(...e)=>{
console.log(e)
});
} else {
console.log('could not update user')
//redirect user to page with message about email confirmation link expiration
//and proposal to register again
}
console.log('confirm registration got invoked')
}
return {
statusCode: 400,
body: "Oops"
}
};
I read that the function first runs on the server when deployed and afterwards on the client. Seems like it does not run on my client, as I invoke the api-endpoint directly? I'm quite a beginner when it comes to API-Endpoints, thanks for reading!
In case you have the same issue when deploying to netlify, you have to run
event.queryStringParameters
which gives you access to the query parts of your url.

Get current mailbox from Outlook web addin

I just found this: https://learn.microsoft.com/en-us/office/dev/add-ins/reference/manifest/supportssharedfolders . Which tells me there is a way to load an addin into a postbox from another user. I have activated the feature via manifest, which is working fine.
To let the server know where to find the mail, I am currently working with, I need the postbox name, that I am currently in. So I went through the properties I get within Office.context. There seems to be no reference to the current mailbox. Just Office.context.mailbox.userProfile.emailAddress which is referring to my signed in user.
Since I need the current postbox to access the mail via Graph / EWS, there has to be a way to read it, else the SupportsSharedFolders would be senseless. How would I get the current postbox name/ID?
You can get an item's shared properties in Compose or Read mode by calling the item.getSharedPropertiesAsync method. This returns a SharedProperties object that currently provides the user's permissions, the owner's email address, the REST API's base URL, and the target mailbox.
The following example shows how to get the shared properties of a message or appointment, check if the delegate or shared mailbox user has Write permission, and make a REST call.
function performOperation() {
Office.context.mailbox.getCallbackTokenAsync({
isRest: true
},
function (asyncResult) {
if (asyncResult.status === Office.AsyncResultStatus.Succeeded && asyncResult.value !== "") {
Office.context.mailbox.item.getSharedPropertiesAsync({
// Pass auth token along.
asyncContext: asyncResult.value
},
function (asyncResult1) {
let sharedProperties = asyncResult1.value;
let delegatePermissions = sharedProperties.delegatePermissions;
// Determine if user can do the expected operation.
// E.g., do they have Write permission?
if ((delegatePermissions & Office.MailboxEnums.DelegatePermissions.Write) != 0) {
// Construct REST URL for your operation.
// Update <version> placeholder with actual Outlook REST API version e.g. "v2.0".
// Update <operation> placeholder with actual operation.
let rest_url = sharedProperties.targetRestUrl + "/<version>/users/" + sharedProperties.targetMailbox + "/<operation>";
$.ajax({
url: rest_url,
dataType: 'json',
headers:
{
"Authorization": "Bearer " + asyncResult1.asyncContext
}
}
).done(
function (response) {
console.log("success");
}
).fail(
function (error) {
console.log("error message");
}
);
}
}
);
}
}
);
}

Can I use https.request in vscode extension

I am creating a VSCode Extension.
I have added MSTranslator as a node module because I want to call the Microsoft Translator API
but when I run the example either nothing happens,
or I get a Error Connect EACCES. I get this error 2 or 3 times but now it has stopped returning anything, it just jumps the code and continues
I am running this on a MacBook
if (!api_key) {
console.log('missing api_key');
}
var params = {
text: 'How\'s it going?',
from: 'en',
to: 'es'
};
var client = new MsTranslator({ api_key: api_key });
client.initialize_token(function (err) {
if (err) {
console.log("initialize_token", err);
return;
}
client.translate(params, function (err, data) {
if (err) console.log('error:' + err.message);
console.log(data);
process.exit();
});
});
and when it enters client.initialize_token it reaches this line in MsTranslator and does nothing, just jumps out of function.
var req = https.request(self.options, function(res) {
My Radio Silence firewall is switched off, and the network monitor shows no activity.
If I call the same URL using the same details in self.options using Postman, I get back a token as expected.
Is there a problem running https.request within a VSCode extension, or do I have a different problem?

YouTube Data API: add a subscription

I'm using YouTube's V3 Data API to add a subscription to a channel. This occurs on a Wordpress installation.
I added Google APIs (for oauth) on Wordpress theme functions:
wp_enqueue_script( 'googleapi', 'https://apis.google.com/js/client.js?onload=googleApiClientReady', array(), '1.0.0', true );
I added in the same way the oauth javascript file, which is the first one here: https://developers.google.com/youtube/v3/code_samples/javascript.
Following this guide(https://developers.google.com/youtube/v3/docs/subscriptions/insert (Apps Script)), I extended the OAuth js with the addSubscription method.
Google Client API seems to be loaded and working as it calls correctly googleApiClientReady on the oauth javascript.
So, this is how the subscription is being inserted:
OAUTH JAVASCRIPT
... ... ...
// After the API loads
function handleAPILoaded() {
addSubscription();
}
function addSubscription() {
// Replace this channel ID with the channel ID you want to subscribe to
var channelId = 'this is filled with the channel ID';
var resource = {
snippet: {
resourceId: {
kind: 'youtube#channel',
channelId: channelId
}
}
};
try {
var response = YouTube.Subscriptions.insert(resource, 'snippet');
jQuery('#success').show();
} catch (e) {
if(e.message.match('subscriptionDuplicate')) {
jQuery('#success').show();
} else {
jQuery('#fail').show();
alert("Please send us a mail () with the following: ERROR: " + e.message);
}
}
So, the first error comes with
YouTube.Subscriptions.insert(resource, 'snippet')
It says YouTube is not defined. I replaced it with:
gapi.client.youtube.subscriptions.insert(resource, 'snippet');
And that error went away. When checking response, as the subscription isn't completed, this is what I get
{"wc":1,"hg":{"Ph":null,"hg":{"path":"/youtube/v3/subscriptions","method":"POST","params":{},"headers":{},"body":"snippet","root":"https://www.googleapis.com"},"wc":"auto"}}
So, I would like to know what's happening on that POST request and what's the solution to this.
I can post the full OAuth file, but it's just as in the example, plus that addSubscription method at the end.
Okay, I got it working, the problem was on the POST request. Here is the full method working:
// Subscribes the authorized user to the channel specified
function addSubscription(channelSub) {
var resource = {
part: 'id,snippet',
snippet: {
resourceId: {
kind: 'youtube#channel',
channelId: channelSub
}
}
};
var request = gapi.client.youtube.subscriptions.insert(resource);
request.execute(function (response) {
var result = response.result;
if (result) {
// alert("Subscription completed");
}
} else {
// alert("Subscripion failed");
// ...
}
});
}
Also make sure to load Google Apps API (in fact without it the authorize/login button won't work) and jQuery.
Any chance you can post everything that made this work...all the JS entire auth.js save for your private keys, im working on this exact problem.

No callback when calling yam.platform.login

When using Yammer SDK and using yam.platform.login method, I don't get any callback when authentication fails or when the user closes dialog window. Is this a bug or something you have seen in your Yammer integration tasks?
My code
yam.platform.getLoginStatus(function (response) {
if (response.authResponse) {
}
else {
yam.platform.login(function (response) {
if (response.authResponse) {
console.dir(response);
}
else {
### CODE NEVER EXECUTED IF LOGIN FAILS OR USER CLOSE POPUP###
}
});
}
});
Make sure to add your web application url to "Javascript Origins" of your registered yammer app.
Make sure you added your web app url to "Trusted Sites" and other Yammer urls.
We get this problem (no callback on yam.platform.login) when the user is currently logged into a network other than the home network (network where app is registered). If your users use multiple networks, you may need to add your app to the global app register.
An alternative (hacky) way is to 'try' the approach below. This worked for us as it only needed to happen once (to get the auth token).
yam.getLoginStatus(function(resp){
if (resp.authResponse) {
//success
} else {
// not logged in
var yamLoginSuccess=0;
try {
yam.platform.login( function (response) { //prompt login
console.log('no response here if user in another network');
if (response.authResponse) {
//success
yamLoginSuccess=1;
}
});
}
catch(err) {
// does not throw an error so this bit is not helpful
}
finally{
if(yamLoginSuccess===0){
alert('Need to be logged into the home yammer first :-/ /n '
+ 'Redirecting now, hit back to come back');
window.location='https://www.yammer.com/YOURNETWORK/';
}
}
}
});

Resources