Hi Michael!
It seems totally plausible that Gmail hasn't updated the draft with it's body contents by the time you make your Gmail API request. Unfortunately at the moment we have no API that really satisfies that need — the 'destroy' event is fired as soon as the ComposeView's DOM element is removed so even that won't help. We don't typically recommend taking over email sending via the Gmail API, simply because it can be a slightly unexpected/unreliable experience — i.e. if your Gmail API code fails for whatever reason, your users may think their email has been sent when really it hasn't, or they may see their 'sent' message in the Drafts folder if they navigate to Drafts before your Gmail API code has finished, etc. Obviously if your use case is important enough that you are willing to take on that risk then the reward may be worth it.
To answer your question re: the ComposeView.send() function saving all changes before sending: you are correct that calling .send() would avoid an out-of-date message. Behind the scenes .send() just delegates to Gmail's native send, so the behavior is precisely the same as if the user themselves clicked the send button. The one downside of using .send() for this case is that you'd either have to visually hide the ComposeView or leave it open and visible while you do your async work (whether they are API calls or something else), then modify the body, then call .send(). Since InboxSDK doesn't currently have a good way to programmatically hide the ComposeView without closing it, you'd probably have to write your own DOM manipulation code, which could be annoying and prone to periodic breakage.
How long does the async operation you're performing take before you modify the email body? If it is a consistently fast operation (which probably rules out any network/API calls), you could probably get away with just keeping the ComposeView open and visible while you do the work.