Downloading MIME using GRAPH API REST request is slow compared to MIME file download from outlook web (OWA) - microsoft-graph-api

In our project we started to use GRAPH API v.1.0 introduced some time ago and we wanted our users to be able to download *.eml file. For that we found that this is called MIME stream on MS side.
Long story short:
we use TypeScript (TS) and Graph Client library (#microsoft/microsoft-graph-client#^2.2.1);
We use request
await graphClient.api(/me/messages/${msgID}/$value).getStream()
The problem we started to notice is that 15MB email (with some attachments of 3-5MB) takes approximately 30sec to download whereas if email is downloaded via Outlook OWA (trhee dots on email > download) it takes few seconds.
Is there a way to increase the download speed using GRAPH api?
I tried to download MIME from graph and expected it to be as fast as downloading MIME from outlook web but it takes twice (maybe more) amount of time to download
EDITED:
As an example: downloading eml (13Mb) from https://outlook.live.com/mail
by uri like: https://attachment.outlook.live.net/owa/outlook_HEXNUM#outlook.com/service.svc/s/DownloadMessage?id=BASE64%3D&token=HUGETOKEN takes 2.5s
downloading eml using GraphApi by uri like:
client.api('/me/messages/${encodeURIComponent(this._fixId(mailId))}/$value').getStream() and reading stream takes 20-30s.

Related

How to create an upload (large, ie ~400MB) bytestream service in Vaadin?

In an earlier post from a few minutes ago, I asked a "general" question regarding creating general webservices in vaadin: How can one create webservices in Vaadin 12?
However, one specific unique case that I mainly need to support is the uploading via https of large (eg ~400MB) bytestream objects that would presumably be sent to Vaadin via an https "post" command (with the paylod being provided I presume in raw binary format as a bytestream.) I saw that Vaadin has built-in support for uploading files (which is essentially a post command of a bytestream, I presume?) and then I saw a reference to StreamReceiver here: https://vaadin.com/docs/v12/flow/advanced/tutorial-stream-resources.html
which seems to sound like a custom file importer, but I couldn't find any (simple & more-or-less complete) examples on how to use it. Ideally, a quick few lines of Java to show the "receiving" of the bytestream and a few quick lines (ideally in Java) which "posts" to the receivestream's url would be all that's needed to show how this manual upload of bytes can be accomplished in Vaadin. (In DropWizard & Jersey, I can find such examples reasonably easily, but I'm not sure how to gain that level of control in Vaadin.)
(Very very minor bonus: is there a size limit to the post command? eg, can a bytestream of over say ~4GB be sent and received?)
In Vaadin the Upload API is optimised for streaming into File (unlike handling the stream as in Servlet and JAX-RS API). One way is to first stream to a temp file and then when the file is fully on the server side, handle the data from temp file.
Alternatively you can use Flow Viritin add-on and a helper class UploadFileHandler, which give you and API where you read the contents from InputStream, in same way as with Servlet API. See a usage example is in this test.
This isn't a first time this is asked and I actually have a more verbose blog draft about this subject. I'll add a link to that once I get that published.

Google Speech API gRPC sync request processes first word(s) only

Google Speech API via gRPC recognizes first few words only. Tested using several short (<10s) audio files in several (wav, flac) formats.
I am trying to get Google's speech API to work with Delphi using gRPC. (Calling the Speech API from Delphi using JSON works OK, but does not support streaming)
As Google does not support Delphi as gRPC client, I use Grijjy's protocolbuffers for Serializing/Deserializing audio request/response, and Grijjy's scalable sockets for the http/2 request.
As I think the code is too large to share here, I created a MVCE. A zip file containing source code (Delphi 10.3), executable and audio file can be found here. The audio file contains the text "How old is the Brooklyn Bridge", which is flawlessly recognized when calling the Speech API via JSON.
To run the executable, only a Google API key is necessary. Necessary support file nghttp2.dll is included. After sending a request, a messagebox is displayed containing the deserialized response. I checked this is the complete Google response by checking response data size. The response only shows "how old", where I would have expected a full recognized sentence. No errors are returned, confidence factor is also returned.
To compile the source code, Grijjy's code as mentioned above must downloaded from Github and the folder(s) containing the downloaded code made available to the Delphi project.
Also, for Google to accept the request, in grijjy.http, line 1215 needs to modified from
FInternalHeaders.AddOrSet('host', FURI.Host);
to
FInternalHeaders.AddOrSet(':authority', FURI.Host);
(I failed to create a pull request for this earlier today, will try again later)
During my debugging efforts, I also checked response headers (200 OK), also tried other files (same issue).
For now, I do not know how to continue. Any ideas regarding how to get find the cause (or even better, a solution:-) of this issue would be highly appreciated.

Group DriveItem not converting to PDF

Microsoft Graph allows downloading documents and conversion to PDF. This functionality works well for me when downloading it from OneDrive for Business, but when used with Groups, the format parameter is ignored and I just get original content (no conversion).
A request with URL constructed as /drive/root:/{path and filename}:/content?format=pdf works and the doc is converted to PDF before downloading.
A request with a URL constructed as /groups/{group-id}/drive/root:/{path and filename}:/content?format=pdf, however, ignores the conversion request.
I've tried with both /v1.0 and /beta endpoints.
Relevant API doc is Download the contents of a DriveItem and next topic for content conversion.

How can I download a OneDrive file with Office365 REST API into a Ruby variable?

I'm building a Ruby on Rails app, and I'd like to integrate some Office365 features.
For instance : I would like to download a file from OneDrive and then attach it to an Email in order to send it via Outlook rest API.
I found this get Item content OneDrive REST API but I dont understand how to use it.
I understand that I have to send a GET request (formated as explained in msdn.microsoft.com) with Rails, which will then provide me a "a pre-authenticated download URL" to download the file.
Then I will have to send a second GET request with this a pre-authenticated download URL to start the download, but I don't understand how to deal with the Response in order to save the file into a variable.
How can I retrieve the file into a variable of my Ruby on Rails App, so that I can attach it to an Email with an Outlook REST API to send it from my own Rail controller ?
Also this workflow is really not optimized in term of Bandwidth and Processing (3 REST API request + 1 download + 1 upload), it will work.
However if it exist a single REST API that direclty attach a OneDrive file to an email to send it, that would ease a lot my life, save energy, save money from Microsoft datacenter, and spare the planet ecology.
Any tutorial, examples, or more explanatory doc would be much appreciated.
--- EDIT ---
Adding link to the email is not wished as the email may have to be send to someone outside of Office365 users, and public link are a security issue for confidential documents.
Any help is welcome.
There isn't a single REST API call you can make currently to do what you want, although being able to easily attach a file from OneDrive to a new email message is a great scenario for Microsoft Graph API, it just isn't supported right now.
If you want to attach the file, you need to do as you mentioned, download the contents of the file, and then upload it again as an attachment to the message.
However, I'd recommend sending a link to the file instead, even though you mentioned you don't want to do that. OneDrive for Business now supports "company shareable links" which are scoped to just the user's organization instead of being available totally anonymously.
Something else to consider: The security concerns of sending an anonymous link aren't that different than sending an attached file. In fact, the anonymous link can be more secure, because access to the file can be monitored and revoked in the future (unlike the attachment, which will always be out there).

Send large size data with Rails

I need to send to the customers a raw emails via my rails app.
When they click a link, a new page must open and they need to be able to see the source code of an email. I have a lot of cases where there are emails really big (even 40/50 mb), and it takes a lot of time to server to send it.
E.G.
I have an email with 3 attachments, the total size is 30mb. My
controller method it takes 700 ms to process it and to retrieve the
raw source from imap server, but in the broswer, it takes up to 5
seconds. (2.5 to the first byte, 2.5 to download it).
Right now I just send the string with the render method. Is there a better way? where I am losing all that time?
To be more clear:
With the word 'send' I mean when the server has to 'send' the source code to the browser so the suer can visualize it
What about storing attachments on your server and include in email only links to those attachments? This way your emails will be blazingly fast and clients may download attachments separately. If you don't want to store files on your server, you may use Amazon S3 or some other cloud storage (there are many in these days).
To ease file uploading, I'd recommend you carrierwave library, Amazon S3 integration goes from the box.
I would suggest you to use Delayed Job: https://github.com/collectiveidea/delayed_job or Sidkiq: https://github.com/mperham/sidekiq
When the job is in processing state, you can mark that email as Sending.... and once the background job is completed you can mark it as Sent
Hope this helps
I think you could benefit from looking into solutions for HTTP streaming, which would allow you to start sending data while still processing the request.
This is difficult with Rack based servers, so Rails might have some issues with this approach.
Another approach is to try and split the raw source into chunks and request each chunk using Ajax.
This will allow your app to be more responsive and offer a better user experience. This is also known as a perceived performance approach, since the user experiences the app as more responsive even if it takes the same amount of time to load.
If I were trying to resolve the issue, I would look into an Ajax solution that would allow me to leverage IMAP's partial fetch feature, referenced in it's RFC.
It's possible to write a simple server side API that fetches a part of an email or returns a signal when there is no more to download and than use Javascript to request the data from the server until the 'no more data' return value is received.
This would allow you to display the downloaded data as it's being received.

Resources