Obtaining IMAP attachments using BODY parts - imap

I am creating an email client with API functionalities. One of the functionalities is to provide an API call to download a given attachment.
To obtain an attachment, given the filename and unique email ID (using the GMail X-MSG-ID unique identifier), I'm downloading the whole email, using the FETCH command with the RFC822 command. This is naturally very heavy.
What I want to do is download only the BODY part that is that attachment, such as BODY[1], BODY[2], etc. I know that obtaining the BODYSTRUCTURE gives me a list of parts in the format ("PART","ETC")("PART","ETC"). What I want to know is how these parts map to the BODY[0], BODY[1], etc.
Is the order that parts appear in the BODYSTRUCTURE response a direct mapping to the BODY indices? So if calling BODYSTRUCTURE I obtain ("123","ETC")("456","ETC")("789","ETC"), can I assume that BODY[0] is the "123" and that BODY[1] is the "456"? Or is there another way to map the elements in parenthesis in a BODYSTRUCTURE response to the BODY[0], BODY[1], etc?
Thank you

I have solved this through trial and error.
It would appear the BODY indeces are as they come in the BODYSTRUCTURE response. So, using the above example, if in the BODYSTRUCTURE response you obtain ("123","ETC")("456","ETC"), then when you call BODY[1] you will obtain the "123" part, when you call BODY[2] you will obtain "456", and so on.

Related

Extracting skiptoken to make next request safely

I am trying to retrieve all of a user's ownedObjects. If the user has more than 999 ownedObjects, then the results contain a nextLink.
The documentation here states that skiptoken should not be extracted to make a different request.
However, I would like to extract it to make my next request. If the other parts of the original request URL match the corresponding parts of the nextLink request URL, would this be safe?
According to your description, I assume you want to make an different request to get more result of the user's owenedObjects.
Based on my test, we can use the nextLink property to make a different request.
As the description of the official document, Do not try to extract the $skiptoken or $skip value and use it in a different request.

How can I secure this form post from manipulation

I have a very unique situation. I am building an application where a user uploads a QR code to my site, and when decoded, it has a matching ID already stored in the DB (as in I already have a record of the qr code before the user uploads it)
When they upload it, I decode it, which is a base64 string like so 6BbW0pxO0YENxn38HMUbcQ==
Like I said, That code corresponds to some information, and after they upload the QR image, I redirect them to one more page, which shows them the qr code, the corresponding information stored in the DB, and they are also prompted with a submit button. When pressed, I take note that they have confirmed, and I do some other things.
To elaborate
As a user I go to www.url.com/code/upload and upload an image. I am then redirected to /code/new with the page displaying the data stored in the DB from the correspond decoding of the image.
How can I make the submit button on /code/new reliable? Here are the solutions I can think of, and their vulnerabilities
Propagate /code/new with the correspond data stored in the DB, lets say #username and #movie into a form, with a submit button and POST the data to the server
This is dangerous because I don't think anything stops someone from editing the DOM and changing #username and #movie to something else
Pass the unique base64 identifier in the parameters such like, /code/new?id=STRING
Then when you submit, the string gets passed to the handling controller action, but i feel that this is not safe because then users can attempt to guess the strings and make concurrent post requests.
Essentially, I have a user upload a qr code, and after submission, I need to verify to verify that they were the one that uploaded the image. I lose all state, and information after they upload the image.
A proposed solution:
After the user uploads the image, create a unique string and store it in the session and also a record in the database (A user is logged in, so its the current_user.session_token), then when the user clicks submit on /uploads/new, I grab the session token, and verify that the current_user.session_token == session_token.
At this point, I can only verify that the current user was the one that uploaded the image.. I then need to somehow grab the base64 string that was from the uploaded QR code.
Another proposed solution: I temporarily put the base64 string as an attribute of the user when they upload the file. So I will have current_user.session_token and current_user.base64_string. Then when the user clicks on the 2nd submit button, I do something like
#check if the user's token is equal to the sessions, and the string is not nil
if current_user.session_token == session_token && !current_user.base64_string.nil?
data = current_user.base64_string
#hooray! I have the QR code
end
Then delete the session token, and then delete the current_user's base64_string and session_token
if a malicious user attempts to forge their session token, it won't match their's store in the database, then when I handle the post request, I will not proceed. But If a legitimate user makes the second post request, the session Id matches, and I am able to grab the base64 string.
TL;DR, I need 2 concurrent post requests that carry the information without losing it, and can verify that both the first and second post requests were done by the same user.
If anyone had the patience to read through that, I appreciate it! if there are any suggestions I would greatly appreciate it, or if you think my solution is sufficient or not, please let me know. Thanks!
Sign the parameters generated from the first request, and verify the signature when you process the second request.
The technology to use for this is HMAC. Here's how to use one version available in Ruby:
require 'openssl'
secret = 'ABCDEFGHIJKLMNOP'
data = 'user:code'
signature = OpenSSL::HMAC.hexdigest( 'sha256', secret, data )
p signature
Output:
"bd7194c0604902d6594694d25e7f27bdc2d10926638e0ce8bdda3f6debb37f6a"
This is how you can use it to link two HTTP routes together so that the second one can trust that parameters sent to it via the first one have not been tampered with:
When the first route is called, generate or fetch a secret. It is important that this secret value is not ever sent or exposed to the end user. It can simply be application configuration (which then applies to all linked requests), but if you can store it associated with perhaps the QR code, then the strongest protection is to generate a long random string just before creating the signature, and to store it ready to use to confirm the second step. Something like SecureRandom.hex is great for a short-term secret if you have somewhere server-side to store it.
Combine all the parameters on the form that you want to be tamper-free into one long message. Easiest thing to do is .join them in an array, and you should use a delimiter that is not allowed in any value, and that you are also not accepting due to validation. This string is the value to use for data in the example.
Generate the form that calls the second route. In addition to the params you want to accept at next stage, add the signature value generated as above. Do not send the value of secret to the client by putting in the form or cookie etc.
When you receive the request from the second route to finalise the multi-stage request, generate the signature from the user-sent params (after validating them), and compare with the one sent to you from the form. If it is the same, then the request is valid. If it is different then the data may have been tampered (provided you have no bugs - do check things such as consistent character encoding if any param can contain non-ASCII characters)
Provided you have kept the secret truly secret from the end user, they have next to no chance of generating a correct signature. Only your code in routes one and two knows how to do it (because it has access to correct secret, not because of any special fact on how it is written). Therefore you can trust that the values have not been modified.

facebook graph api returns error 2500 when there are commas in the id url

I'm attempting to retrieve the "shares" graph data for a number of pages in JSON format. I suspect that the errors I am encountering stem from the fact that some of the URLs have commas in them, and are being parsed as an attempt to pass multiple ids.
Returns graph data.
https://graph.facebook.com/?ids=http://celebritybabies.people.com/2012/08/23/backstreet-boys-howie-dorough-expecting-second-son/
Returns error 2500 "Cannot specify an empty identifier"
https://graph.facebook.com/?ids=http://www.people.com/people/article/0,,20624518,00.html
Encode the commas, still returns 2500
https://graph.facebook.com/?ids=http://www.people.com.people.article/0%2C%2C20624518%2C00.html
There doesn't seem to a way around it other than to use the normal inspection
http://graph.facebook.com/http://www.people.com/people/article/0,,20624518,00.html
You may have to file a bug at http://developers.facebook.com/bugs though I feel as the answer would most likely be "Status by design".
You could try using FQL instead, querying the link_stat table:
SELECT url, normalized_url, share_count, comments_fbid FROM link_stat
WHERE url = 'http://www.people.com/people/article/0,,20624518,00.html'
(See result in Graph API Explorer.) You can also use WHERE url IN ("…", "…", …) to check multiple URLs at once.
This also returns a comments_fbid of 10151022112466453, and that one you can look up via the API, https://graph.facebook.com/10151022112466453
Maybe this can work as a workaround, until Facebook fixes this problem.

URL length limit for google reader api

I am using "/reader/api/0/stream/items/ids" API to get the item ids for sources that I want.
I have quite a number of sources, so I repeated "s=" parameter to include in the api url.
However, google has given me an error of "URL is too long".
So the question is that How can I solve it so that I just use one time api call to get item ids for that many sources?
Thanks
It seems that /reader/api/0/stream/items/ids path supports a POST method. This means the amount of data you could pass by using POST verb is much more than by using a query string and a GET method.
So use https://www.google.com/reader/api/0/stream/items/ids URL for the post, and pass your query string as a post data. Don't forget to include an action token(T) which is required for POST requests.

Does imap.fetch(uid,'RFC822')[0].attr['RFC822'] return the entire message, including attachments?

Wondering if there's a way I can avoid fetching the attachments as well.
Yes, it returns the entire email source. The attachments are encoded as email parts.
You can use the Ruby Mail library to extracts all the attachments.
If all you want to do, is download the email body(ies), there isn't a clean way of doing this (at least none that I disovered).
What I had to do, was first download the headers and the body structures. Once I had the headers, I could determine what type of email it was (multi-part, alternative, or just a single bodied email).
Once I knew the structure, I could download the plain text or html body part as a body section.
Does that help?
--Dave
I don't know about ruby , but it can be done only fetching Email Header.
I am Fetching Email header in Python like below:
resp, data = obj.uid('FETCH' , ','.join(map(str,uid_lst)),'(RFC822.HEADER RFC822.SIZE)')
where uid_lst is the list of uids of emails which you want to fetch.
Note: Email which has value of header field Content-Type = 'Multipart-Mixed' has an attachment.

Resources