Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update add attachment interface #522

Merged
merged 9 commits into from
Nov 28, 2017
Merged

Update add attachment interface #522

merged 9 commits into from
Nov 28, 2017

Conversation

shortstuffsushi
Copy link
Contributor

@shortstuffsushi shortstuffsushi commented Sep 16, 2017

Support attachment adding via stream. I have a couple of question's I'd like to get feedback on. This ultimately addresses #511, though it doesn't add an overload for plain content being base64'd internally.

Anyway, questions:

  • I chose to make the method async, because it's reading an unknown stream. Would a non-async method be desirable as well?
  • The function currently just returns in several failure scenarios. It could instead return a result type value indicating status and error messages (think IdentityResult)
  • Unit tests don't currently seem to cover this, should I add them?
  • The example usage projects don't seem to show attachment handling, should I update them projects?
  • [Edited] I'm truncating the stream at int.MaxValue which will be 2gb. As discussed below, there's potential to check message length. Is that desired?

 * Support adding a single Attachment object
 * Clean up if else, just "if doesn't exist, create" then add item
 * Same for multiple, make if not exists, then add range
 * There likely would have been bug in the multiple because it was assigning a list passed in, which could have been modified from outside
 * Remove return at end of function in void functions
This caused confusion internally, so a little more detail would help.
Read a stream's bytes, base64 encode, attach.
Arrange usings.
@thinkingserious thinkingserious added the status: code review request requesting a community code review or review from Twilio label Sep 16, 2017
@SendGridDX
Copy link

SendGridDX commented Sep 16, 2017

CLA assistant check
All committers have signed the CLA.

@Jericho
Copy link

Jericho commented Sep 17, 2017

To your point regarding the size restriction: the way I understand SendGrid's documentation, the restriction applies to the total size of an email not just the size of its attachments which begs the question: how do you calculate the size of an email?

@shortstuffsushi
Copy link
Contributor Author

@Jericho the size of the email would be, as I understand it, the sum of the content size and attachment size. It could be calculated, but I didn't do it the first time around because I'm sure that'll all be double checked server side anyway.

To be honest, the reason I added any size check was to avoid the bizarre discrepancies in the Stream API, where Stream.length is a long but read is Stream.read(byte[] buffer, int offset, int count). If there are better thoughts around how to handle that, I'd love the hear them. I didn't really come across any good ideas for it yesterday, and took the easy route -- never handling anything bigger than int.MaxValue.

@Jericho
Copy link

Jericho commented Sep 17, 2017

Are you sure it's just the sum of content + sum of attachment size? What about recipients names and addresses? What about subject line? (these are just some example off the top of my head) Should they be included in "total" size? Also, is the size calculated using the JSON string including attributes? I'm just trying to point out that it's not as trivial as it may sound.

Also, in my opinion, the right place to check if an email exceeds the size limit is when it's about to be sent.

@shortstuffsushi
Copy link
Contributor Author

I guess I can't speak to what fields are all included in the SendGrid idea of "total size," and indeed -- it should (and likely will be) calculated by their servers before sending. As I mentioned, this was my way of avoiding the Stream API issue, if you have thoughts on that, I'd be interested in hearing them.

@Jericho
Copy link

Jericho commented Sep 17, 2017

I'm mentioning all this because I went through the exact same thought process when I was writing the StrongGrid library as you just did. In the end I had too many unanswered questions and I decided not to do any size checking. I am hoping SendGrid returns a meaningful error message if someone attempts to send an email that exceeds the limit (although I have to admit I have never actually tested this scenario).

@shortstuffsushi
Copy link
Contributor Author

shortstuffsushi commented Sep 17, 2017

Ok, so I decided to just take a look at your implementation to see if you had come up with a solution, but it appears that you chose to instead just truncate the stream which is what I was hoping to avoid. Obviously this won't matter in real use cases for a couple reason:

  • Loading an attachment > int.MaxValue into memory would be unrealistic in most applications (int.MaxValue I believe correlates to 2GB)
  • Uploading would take a while
  • SendGrid would ultimately just reject it anyway

So, perhaps the naive implementation is alright because it'll "mostly work" and fail in the extreme case for a number of reasons anyway. Again, I'd be interested in more graceful ways of handling this, as I've never run into the situation of trying to copy a stream in this manner, and I'm not sure what the usual implementation is.

@Jericho
Copy link

Jericho commented Sep 17, 2017

I don't think overcoming the "long to int conversion causing the stream to be truncated if file exceeds 2GB" issue is worthwhile since we know that SendGrid would reject an email with a 3GB or 5GB or 10GB attachment anyway.

You are making me realize that checking the size before attaching a file makes sense in order to prevent a developer from attempting to add a file so large that it would take so much memory, be very slow and be rejected by SendGrid anyway. I'll add this attachment size check to my implementation (and give you credit!) but I still would like to know how SendGrid calculates an email "total" size in order to implement this check before attempting to send an email.

Instead, just truncate long to int.
More changes around stream truncation and not handling size.
@thinkingserious
Copy link
Contributor

@Jericho,

Thanks for jumping in with feedback!

The total size is calculated from the entire JSON payload. Note that you will need to handle the case where UTF-8 characters are included.

@shortstuffsushi,

Your PR is now queued up on our backlog for review. Thanks!

With Best Regards,

Elmer

@thinkingserious thinkingserious added the status: code review request requesting a community code review or review from Twilio label Sep 18, 2017
@thinkingserious thinkingserious added difficulty: medium fix is medium in difficulty hacktoberfest labels Sep 30, 2017
@mbernier
Copy link
Contributor

@Jericho can you please give this a look and let us know your thoughts? Should we modify anything before merge? Will it cause any issues with any of the suggested work we have in #530

@Jericho
Copy link

Jericho commented Oct 28, 2017

@shortstuffsushi you decided against checking size of each attachment and the total size of a message? The discussion you and I had about this topic inspired me to implement the size check in StrongGrid and I thought you were doing the same for SendGrid's library.

@shortstuffsushi
Copy link
Contributor Author

I did decide against the per file check. The total size would still be relevant, but I didn't choose to do it here. It was indicated above that I would need to check the entire json payload size, which seemed out of scope for my method add. Still probably worth doing, but not here imo.

@thinkingserious
Copy link
Contributor

Hi @shortstuffsushi,

My apologies for taking forever to review this :(

To merge this, I just need 2 more things:

  1. Please do add unit test(s)
  2. Please add an example of how to use this feature to USE_CASES.md

No worries if we don't merge this in October, you have earned your hacktoberfest swag :)

With Best Regards,

Elmer

@shortstuffsushi
Copy link
Contributor Author

Thanks @thinkingserious -- I'll try to get to this over the weekend.

@shortstuffsushi
Copy link
Contributor Author

@thinkingserious I added some tests and some notes to the markdown file. I wasn't able to get the integration tests working, and I didn't really look into why. Are those relevant for what I'm doing? Can you re-review this now?

@thinkingserious
Copy link
Contributor

Thanks @shortstuffsushi!

I am currently working through the flood of PRs we received from Hacktoberfest. There were over 1,000!

Thanks in advance for your patience.

With Best Regards,

Elmer

Copy link
Contributor

@thinkingserious thinkingserious left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

}

/// <summary>
/// Add attachments to the email.
/// </summary>
/// <param name="attachments">A list of Attachments.</param>
public void AddAttachments(List<Attachment> attachments)
public void AddAttachments(IEnumerable<Attachment> attachments)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like using the IEnumerable here, but I'm concerned about breaking changes by removing the old function signature. How about keeping the old function signature and adding this one as a function overload?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because List inherits from IEnumerable, this shouldn't be a breaking change. Anyone using lists should see things continue to work as though nothing changed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! Thanks for the super quick response :)

@thinkingserious thinkingserious merged commit a6fcf87 into sendgrid:master Nov 28, 2017
@thinkingserious
Copy link
Contributor

Hello @shortstuffsushi,

Thanks again for the PR!

We want to show our appreciation by sending you some swag. Could you please fill out this form so we can send it to you? Thanks!

Team SendGrid DX

@shortstuffsushi
Copy link
Contributor Author

Thanks @thinkingserious. I'm hoping to help out more in the future, but I've been a bit busy lately as you can probably tell by the slow responses. Hopefully I'll be talking to you again soon.

@shortstuffsushi shortstuffsushi deleted the update-add-attachment-interface branch December 6, 2017 15:06
@thinkingserious
Copy link
Contributor

That sounds excellent @shortstuffsushi! Thank you for the follow up :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty: medium fix is medium in difficulty status: code review request requesting a community code review or review from Twilio
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants