I'm working on 'outlook-web-addon' that take the currently opened message and attache it to a new message and send it to a specific address.. all without allowing the user to interact (No compose screen)
The code below is passed till 'Create attachment' which generate the error:
"The requested web method is unavailable to this caller or application"
function sendMessage() {
//$("#y").load("x.html");
//var mailBody = document.load("MailBody");
//<object type="text/html" data="mailBody.html"></object>
if (Office.context.mailbox.item.itemType !== Office.MailboxEnums.ItemType.Message) {
return;
}
var parentId='';
var mimeContent='';
//Get current selected mail message Id
var mailbox = Office.context.mailbox;
var item = mailbox.item;
var itemId = item.itemId;
//1- Create Mime content from the current selected mail message
var request_MimeContent =
'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
' <soap:Body>' +
' <m:GetItem>' +
' <m:ItemShape>' +
' <t:BaseShape>IdOnly</t:BaseShape>' +
' <t:AdditionalProperties>' +
' <t:FieldURI FieldURI="item:MimeContent" />' +
' <t:FieldURI FieldURI="item:Subject" />' +
' </t:AdditionalProperties>' +
' </m:ItemShape>' +
' <m:ItemIds>' +
' <t:ItemId Id="' +itemId +'" />' +
' </m:ItemIds>' +
' </m:GetItem>' +
' </soap:Body>' +
'</soap:Envelope>';
Office.context.mailbox.makeEwsRequestAsync(request_MimeContent, createMail);
}
function createMail(asyncResult) {
if (asyncResult.status == "failed") {
return;
} else {
//2- Get MimeContent
var response = $.parseXML(asyncResult.value);
window.mimeContent = response.getElementsByTagName("MimeContent");
//3- Create mail request
var request_CreateMail =
'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
' <soap:Header><t:RequestServerVersion Version="Exchange2010" /></soap:Header>' +
' <soap:Body>' +
' <m:CreateItem MessageDisposition="SaveOnly">' +
' <m:SavedItemFolderId><t:DistinguishedFolderId Id="sentitems" /></m:SavedItemFolderId>' +
' <m:Items>' +
' <t:Message>' +
' <t:Subject>Phishing Mail Report!</t:Subject>' +
' <t:Body BodyType="HTML">This is a Test !!</t:Body>' +
' <t:ToRecipients>' +
' <t:Mailbox><t:EmailAddress>M.Ziada#Zinad.net</t:EmailAddress></t:Mailbox>' +
' </t:ToRecipients>' +
' </t:Message>' +
' </m:Items>' +
' </m:CreateItem>' +
' </soap:Body>' +
'</soap:Envelope>';
Office.context.mailbox.makeEwsRequestAsync(request_CreateMail, createAttachment);
}
}
function createAttachment(asyncResult) {
if (asyncResult.status == "failed") {
return;
} else {
//4- Get new message Id
var response = $.parseXML(asyncResult.value);
window.parentId = response.getElementsByTagName("ItemId");
//5- Create attachment from the mime content and belongs to the new message
var request_CreateAttachment =
'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
' <soap:Header><t:RequestServerVersion Version="Exchange2010" /></soap:Header>' +
' <soap:Body>' +
' <m:CreateAttachment>' +
' <m:ParentItemId Id="' +window.parentId +'" />' +
' <m:Attachments>' +
' <t:ItemAttachment>' +
' <t:Name>Play tennis?</t:Name>' +
' <t:IsInline>false</t:IsInline>' +
' <t:Message>' +
' <t:MimeContent CharacterSet="UTF-8">' +window.mimeContent +'</t:MimeContent>' +
' </t:Message>' +
' </t:ItemAttachment>' +
' </m:Attachments>' +
' </m:CreateAttachment>' +
' </soap:Body>' +
'</soap:Envelope>';
Office.context.mailbox.makeEwsRequestAsync(request_CreateAttachment, sendItem);
}
}
function sendItem(asyncResult) {
if (asyncResult.status == "failed") {
return;
} else {
//6- Get attachment Id
var response = $.parseXML(asyncResult.value);
var attachmentId = response.getElementsByTagName("AttachmentId");
//7- Send newly created message
var request_SendItem =
'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
' <soap:Header><t: RequestServerVersion Version="Exchange2010" /></soap:Header>' +
' <soap:Body>' +
' <m:SendItem SaveItemToFolder="true">' +
' <m:ItemIds>' +
' <t:ItemId Id="' +window.parentId +'"/>' +
' </m:ItemIds>' +
' <m:SavedItemFolderId>' +
' <t:DistinguishedFolderId Id="sentitems" />' +
' </m:SavedItemFolderId>' +
' </m:SendItem>' +
' </soap:Body>' +
'</soap:Envelope>';
Office.context.mailbox.makeEwsRequestAsync(request_SendItem,
function(asyncResult2) {
if (asyncResult2.status == "failed") {
return;
} else {
}
});
}
}
I'm trying on Chrome, and it gives me this error:
"The requested web method is unavailable to this caller or application"
Also, I wonder if this will work on desktop outlook application ?
As per https://learn.microsoft.com/en-us/outlook/add-ins/understanding-outlook-add-in-permissions#readwritemailbox-permission the attachment operations aren't allowed with MakeEWSRequestAsync. There is a ReadOnly method you can use for accessing attachments https://learn.microsoft.com/en-us/outlook/add-ins/get-attachments-of-an-outlook-item (but I don't believe this will allow you to create one).
The only workaround I know is that because CreateItem is allowed and you can create a Message from the MIMEContent if the message that you want to send is built in Mime first (with the attachment mime encoded) and then you create the Message from that content it should work.
Related
Good day everybody.
I bought a nice template and leaftlet is used to show maker.
Here is the demo . Actually when you clik on a marker, it open a widnows with a picture and some température value.
I would like to have all of the windows open. Of course, I am going to modify the html, to remove the picture and some information as GPS, and only keep the temperatue value. The goal is to be able to immediately see the temperature boxes below the markers. Optionaly, when I click on the marker it redirect to another page, same you click on the picture.
My first problem, I can not find the jacasvript script which work with the link of marker. The idea would be to cancel the effect of the click, or as I wrote, after we click it open the graph page instead of opening the windows.
My first question: how can I find a do to change the action of the click, on the marker
My second question (may be it be cancel the 1st question :) ), how can I change the behaviour of the bindpopup? Is there way "to tell" to the bindpopup, stay always open?
My thirst question: Or can we add one or two additional nice boxes, which show always the temperature below the marker, and keep the bindPopup, as it is? That would be nice as well
Here is the code of the map line 215
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// OpenStreetMap - Homepage
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function createHomepageOSM(_latitude,_longitude,_nbField){
setMapHeight();
if( document.getElementById('map') != null ){
var map = L.map('map', {
center: [_latitude,_longitude],
zoom: 18,
scrollWheelZoom: false
});
//L.tileLayer('http://openmapsurfer.uni-hd.de/tiles/roadsg/x={x}&y={y}&z={z}', {
L.tileLayer('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
//subdomains: '0123',
maxZoom: 20,
attribution: 'OpenStreetMap contributors, CC-BY-SA'
}).addTo(map);
var markers = L.markerClusterGroup({
showCoverageOnHover: false
});
function locateUser() {
$('#map').addClass('fade-map');
map.locate({setView : true})
}
$('.geo-location').on("click", function() {
locateUser();
});
$.ajax({
type: "POST",
url: "sql/get_map.mysql.php",
//data:'node=node1',
//data:{node_id:"firstnode", node2:"secondnode", node3:"thirdnode", from:"from", to:"to"}, // Send parameter to get.php
success: result,
error: error,
dataType: "json"
});
function error(data)
{
$('body').addClass('loaded');
alert("Error getting datas from DB");
console.log("Error getting datas from DB");
console.log(data);
}
function result(data){
console.info("data:",data);
var allMarkers=[];
var nhtml = '<img src="assets/img/property-types/vineyard.png">';
for (var i = 0; i < data.properties.length; i++) {
allMarkers.push(L.latLng(data.properties[i]['la'], data.properties[i]['lo']));
//data.properties[i]['b2'] = 0;
if((data.properties[i]['b1']>=data.properties[i]['se'] && data.properties[i]['b1'] < data.properties[i]['se']+1) ||
(data.properties[i]['b2']>=data.properties[i]['se'] && data.properties[i]['b2'] < data.properties[i]['se']+1) ||
(data.properties[i]['b3']>=data.properties[i]['se'] && data.properties[i]['b3'] < data.properties[i]['se']+1) ||
(data.properties[i]['b4']>=data.properties[i]['se'] && data.properties[i]['b4'] < data.properties[i]['se']+1)
)
{
nhtml = '<img src="assets/img/property-types/vineyard-orange.png">';
}
if(((data.properties[i]['b1'] < data.properties[i]['se']) && data.properties[i]['b1'] != null) ||
((data.properties[i]['b2'] < data.properties[i]['se']) && data.properties[i]['b2'] != null) ||
((data.properties[i]['b3'] < data.properties[i]['se']) && data.properties[i]['b3'] != null) ||
((data.properties[i]['b4'] < data.properties[i]['se']) && data.properties[i]['b4'] != null)
)
{
nhtml = '<img src="assets/img/property-types/vineyard-red.png">';
}
else{
nhtml = '<img src="assets/img/property-types/vineyard.png">';
}
var _icon = L.divIcon({
//html: '<img src="' + locations[i][7] +'">',
html: nhtml,
iconSize: [40, 48],
iconAnchor: [20, 48],
popupAnchor: [0, -48]
});
var title = data.properties[i]['station'];
var marker = L.marker(new L.LatLng(data.properties[i]['la'],data.properties[i]['lo']), {
title: title,
icon: _icon
});
var str ='';
if(data.properties[i]['b1'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b1'] + '°C</div>');
}
if(data.properties[i]['b2'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b2'] + '°C</div>');
}
if(data.properties[i]['b3'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b3'] + '°C</div>');
}
if(data.properties[i]['b4'] != null)
{
str = str.concat('<div class="tag price"> ' + data.properties[i]['b4'] + '°C</div>');
}
marker.bindPopup(
'<div class="property">' +
'<a data-field=' + data.properties[i]['id_field'] +'" data-station=' + data.properties[i]['id_station'] +'" href="charts.php?field='+ data.properties[i]['id_field'] +'">' +
'<div class="property-image">' +
'<img src="img/stations/station-' + data.properties[i]['id_station'] + '.jpg">' +
'</div>' +
'<div class="overlay">' +
'<div class="info">' +
'<h3>' + data.properties[i]['station'] + '</h3>' +
'<figure>' + data.properties[i]['da'] + '</figure>' +
'<figure>' + data.properties[i]['la'] + ' ' + data.properties[i]['lo'] +'</figure>' +
str +
'<div class="tag"> ' + data.properties[i]['se'] + '°C</div>' +
'</div>' +
'</div>' +
'</a>' +
'</div>'
);
markers.addLayer(marker);
}
if(_nbField>1){
bounds = L.latLngBounds(allMarkers);
map.fitBounds(bounds,{ padding: [10, 10] });
}
map.addLayer(markers);
map.on('locationfound', onLocationFound);
function onLocationFound(){
$('#map').removeClass('fade-map');
}
$('body').addClass('loaded');
setTimeout(function() {
$('body').removeClass('has-fullscreen-map');
}, 1000);
$('#map').removeClass('fade-map');
}
}
}
My last question, with firefox, id possible "to track" the javascript action?
Feel free to aks complementary question to better understand and help, if I missed to provide information.
Many thanks
You can add a click event to the marker:
marker.on('click',(e)=>{
console.log(e);
});
Show all Popups:
You need to set the options autoClose and closeOnClick to false:
marker.bindPopup(content,{autoClose: false, closeOnClick: false});
You can use Tooltips:
marker.bindTooltip('5.3°C', {direction: 'bottom', permanent: true});
I don't know exactly what do you mean, but it sounds like debugging. Use the developer console with the Debugger.
Thanks for your reply and help
Unfortunately 2. does not work. There is no differences. I added closeButton:true, and that works, but it's not what I need.
marker.bindPopup(
'<div class="property">' +
'<a data-field=' + data.properties[i]['id_field'] +'" data-station=' + data.properties[i]['id_station'] +'" href="charts.php?field='+ data.properties[i]['id_field'] +'#st-'+ data.properties[i]['id_station'] +'">' +
'<div class="property-image">' +
'<img src="img/stations/station-' + data.properties[i]['id_station'] + '.jpg">' +
'</div>' +
'<div class="overlay">' +
'<div class="info">' +
'<h3>' + data.properties[i]['station'] + '</h3>' +
'<figure>' + data.properties[i]['da'] + '</figure>' +
'<figure>' + data.properties[i]['la'] + ' ' + data.properties[i]['lo'] +'</figure>' +
str +
'<div class="tag"> ' + data.properties[i]['se'] + '°C</div>' +
'</div>' +
'</div>' +
'</a>' +
'</div>',{autoClose: true, closeOnClick: false, closeButton: true}
);
I also tried the interesting option with tooltip. Bellow the above code I added
marker.bindTooltip('5.3°C', {direction: 'bottom', permanent: true});
But that print an error message
marker.bindTooltip is not a function
Is there additionally library I have to add for tooltop, or is inlcuded into leafet.
(bindTootip would be great and enough for my need)
Thanks for helping
Cheers
https//127.0.0.1:111001 unexpectedly closed the connection
I need to hit https//127.0.0.1:111001 for Mantra Rd service connection . but not able to hit Getting error connection closed (I am using IONIC for mobile application) The same thing is working on web with angular8.
please help...
const xhr = new XMLHttpRequest();
let url = "https://127.0.0.1:11100"
xhr.open('DEVICEINFO', url);
const params = '<?xml version="1.0"?> <PidOptions ver="1.0"> <Opts fCount="' + 5 + '" fType="' + "FMR" + '" iCount="' + 1 + '" pCount="' + 1 + '" format="' + 0 + '" pidVer="' + 2.0 + '" timeout="' + 60000 + '" posh="UNKNOWN" env="' + 'P' + '" /> ' + 'this.DemoFinalString' + '<CustOpts><Param name="mantrakey" value="' + '' + '" /></CustOpts> </PidOptions>';
// set `Content-Type` header
xhr.setRequestHeader('Content-Type', 'text/xml');
xhr.send(params);
xhr.onload = async () => {
const parser = new DOMParser();
const xml = parser.parseFromString(xhr.responseText, 'text/xml');
this.obj = await this.xmlToJsonfn(xml);
this.currentdeviceInfoSubject.next(this.obj);
};
xhr.onerror = function (e) {
console.log('eoor', e);
if (e.type == 'error') {
// alert('please download the Driver');
}
};
Please provide a working solution for this, I'm getting 400 bad request error when doing a batch update. I tried Andrew Cornell's blog post in this regard. But couldn't get it to work yet. Below is the code I tried.
// create the changeset
batchContents.push('--changeset_' + changeSetId);
batchContents.push('Content-Type: application/http');
batchContents.push('Content-Transfer-Encoding: binary');
batchContents.push('');
batchContents.push('POST ' + webUrl + '(' + itemProperties[i].Id + ')' + ' HTTP/1.1'); //+ '(' +itemProperties[i].Id + ')'
batchContents.push('Content-Type: application/json;odata=verbose');
batchContents.push('Accept: application/json;odata=verbose');
batchContents.push('If-Match: ' + itemProperties[i].__metadata.etag);
//batchContents.push('X-HTTP-Method:' + 'MERGE');
batchContents.push('X-RequestDigest:' + $("#__REQUESTDIGEST").val());
batchContents.push('');
batchContents.push(JSON.stringify(itemUpdater));
batchContents.push('');
}
// END changeset to create data
batchContents.push('--changeset_' + changeSetId + '--');
// generate the body of the batch
var batchBody = batchContents.join('\r\n');
// start with a clean array
batchContents = new Array();
// create batch for creating items
batchContents.push('--batch_' + batchGuid);
batchContents.push('Content-Type: multipart/mixed; boundary="changeset_' + changeSetId + '"');
batchContents.push('Content-Length: ' + batchBody.length);
batchContents.push('Content-Transfer-Encoding: binary');
batchContents.push('');
batchContents.push(batchBody);
batchContents.push('');
//bath end
batchContents.push('--batch_' + batchGuid);
batchBody = batchContents.join('\r\n');
// create the request endpoint
var endpoint = _spPageContextInfo.webAbsoluteUrl
+ '/_api/$batch';
// batches need a specific header
var batchRequestHeader = {
'X-RequestDigest': jQuery("#__REQUESTDIGEST").val(),
'Content-Type': 'multipart/mixed; boundary="batch_' + batchGuid + '"'
};
url: endpointUri,
type: 'POST',
async: false,
headers: batchRequestHeader,
data: batchBody,
refered : part 1
part 2
I 'm working on an app in ionic framework in which I want to get location of device.
It works fine for getCurrentPosition
But when I try to use watchPosition, so that I can get new position whenever there is a change in location of device. it does nothing.
I 'm not sure what I 'm missing
my controllers.js code
.controller('LocCtrl', function($scope,$cordovaGeolocation) {
var posOptions = {timeout: 10000, enableHighAccuracy: false};
$cordovaGeolocation
.getCurrentPosition(posOptions)
.then(function (position) {
alert('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
}, function(err) {
alert(err);
});
var watchOptions = {
timeout : 3000,
enableHighAccuracy: false // may cause errors if true
};
var watch = $cordovaGeolocation.watchPosition(watchOptions);
watch.promise.then(
null,
function(err) {
alert("error:"+err);
},
function(position) {
var lat = position.coords.latitude
var long = position.coords.longitude
alert("Lat in Watch:"+lat);
});
$cordovaGeolocation.clearWatch(watch.watchId);
})
I used some alert messages to see whats happening,
In current setuation, it gives two alert messages giving getCurrentPosition, but noting happens on changing device Location.
I am creating a workflow process with Google Apps script. I have looked at this video for most of the layout.
I built a form in Google Apps script that takes input data from a user. The data is then submitted into rows with e.parameter values. That data is then emailed to an approver. The approver has an approve button that they press to change the "Status" column to approved.
Issue:
I cant get the data to approve the correct row. I am passing a row parameter that is supposed to correspond to the correct row but it isnt working.
Here is my code that submits data to the spreadsheet and once the data has been approved via email. The DoPost function runs and approves the row. Can someone Please help! I've been trying to find solutions all day.
function sendEmail_(e) {
var sheet = SpreadsheetApp.openById("0AuCblud0Ss7BdHA1bXZjYXA0Y0IyekhUQm5vWG02MVE").getActiveSheet();
var range = sheet.getRange(sheet.getLastRow() + 1, 1, 1, 13);
range.setValues([
[e.parameter.LastName, e.parameter.FirstName, e.parameter.DivisionName, e.parameter.EffectiveDate,
e.parameter.Network, e.parameter.EmployeeNewPosition, e.parameter.DivisionFolder, e.parameter.SpecificIndividual,
e.parameter.Email, e.parameter.username, e.parameter.who, e.parameter.Banner, "Unapproved"]
]);
var row = sheet.getLastRow() + 1;
//"https://script.google.com/a/macros/wichitafallstx.gov/s/AKfycbwOgTTGqNsVwnqs-xfqa7TEJWGc_lJZdoyoEoixngKdDemVQuo/exec
var body = '<form action= <form action = " https://sites.google.com/a/macros/wichitafallstx.gov/s/AKfycbxAOGO6q9ofauf34xlDA9sLG8sUXeZsuvQkDKATOQ/exec" method ="post">' +
"<b>Last Name:</b>" + e.parameter.LastName + '<br><br>' +
"<b>First Name:</b>" + e.parameter.FirstName + '<br><br>' +
"<b>Division Name:</b>" + e.parameter.DivisionName + '<br><br>' +
"<b>Effective Date:</b>" + e.parameter.EffectiveDate + '<br><br>' +
"<b>Network:</b>" + e.parameter.Network + '<br><br>' +
"<b>Employee New Position:</b>" + e.parameter.EmployeeNewPosition + '<br><br>' +
"<b>Division Folder:</b>" + e.parameter.DivisionFolder + '<br><br>' +
"<b>Specific Individual:</b>" + e.parameter.SpecificIndividual + '<br><br>' +
"<b>Email:</b>" + e.parameter.Email + '<br><br>' +
"<b>Username:</b>" + e.parameter.username + '<br><br>' +
"<b>who:</b>" + e.parameter.who + '<br><br>' +
"<b>Banner:</b>" + e.parameter.Banner +
'<br />' +
'<br />' +
'<input type="hidden" name="row" value=" ' + row + ' "/>' +
'<input type="submit" value="Approve" onclick="approve()" />' +
'</form>';
var owners = SitesApp.getSite("wichitafallstx.gov", "information-systems").getOwners();
var mail = MailApp.sendEmail(owners.join(","), "test", '', {
htmlBody: body
});
}
//handles the payload that is posted back to appscript..from the form that is passed from the form created in send email.
function doPost(e) {
var r = e.parameter["row"];
var sheet = SpreadsheetApp.openById("0AuCblud0Ss7BdHA1bXZjYXA0Y0IyekhUQm5vWG02MVE").getActiveSheet();
var values = sheet.getRange(r, 1, 1, 13).getValues();
sheet.getRange(r, 13).setValue("Approved");
}
I am passing a row parameter that is supposed to correspond to the correct row but it isnt working.
It appears that you are passing the row below the one intended.
var range = sheet.getRange(sheet.getLastRow() + 1, 1, 1, 13);
range.setValues([
[e.parameter.LastName, e.parameter.FirstName, e.parameter.DivisionName, e.parameter.EffectiveDate,
e.parameter.Network, e.parameter.EmployeeNewPosition, e.parameter.DivisionFolder, e.parameter.SpecificIndividual,
e.parameter.Email, e.parameter.username, e.parameter.who, e.parameter.Banner, "Unapproved"]
]);
// In assignment below 'new' lastRow is the row you just filled
// in with above and should not include + 1
var row = sheet.getLastRow() // no + 1;