Upon using the Gmail API in Javascript to send a message with an HTML body and a ~100KB PDF attachment, the attachment correctly appears attached to the message in the sender's Gmail Sent folder, but does not appear on the message for the recipient.
The API call is a POST
to:
https://www.googleapis.com/upload/gmail/v1/users/me/messages/send?uploadType=media
The request body sent to the API is:
{
"headers": {
"Authorization": "Bearer authToken-removedForThisPost"
},
"method": "POST",
"contentType": "message/rfc822",
"contentLength": 134044,
"payload": "exampleBelow",
"muteHttpExceptions": true
}
This is what the payload looks like:
MIME-Version: 1.0
To: =?utf-8?B?TWlrZSBD?=<[email protected]>
CC: =?utf-8?B?TWlrZSBD?=<[email protected]>
BCC: =?utf-8?B??=<[email protected]>
From: =?utf-8?B?TWlrZSBxWXsd2lr?=<[email protected]>
Subject: =?utf-8?B?subjectLine-removedForThisPost?=
Content-Type: multipart/alternative; boundary=__boundary__
--__boundary__
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64
base64EncodedStringHere-removedForThisPost
--__boundary__
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: base64
base64EncodedStringHere-removedForThisPost
--__boundary__
Content-Type: application/pdf; name="File Name.pdf"
Content-Disposition: attachment; filename="File Name.pdf"
Content-Transfer-Encoding: base64
base64EncodedStringHere-removedForThisPost
--__boundary__--
Note: The Gmail API Uploading Attachments documentation states that when uploading a simple attachment (under 5MB) Content-Length
is required. I made it so that my code produces an integer value of the total number of bytes of the PDF attachment. However, I noticed that Content-Length
is not included in the payload.
I tried changing the multipart/alternative
Content-Type for the message to multipart/mixed
- this made it so that the PDF attachment IS correctly attached to the recipient's message, but the HTML body of the message is rendered as plain text (the HTML tags are shown) and there is an additional attachment called noname.html which includes the HTML content rendered as HTML.
I need to make it so that the email in the recipient's message has both an HTML-rendered body AND the PDF attachment.
Update: I uploaded examples of the raw email messages here. The sent message is on the left, and the received message is on the right.
Why can't I see attachments on Gmail? The messages with attachments may be collapsed behind newer messages, so you don't see the attachments, but they do show in the conversation list if you use the Default density and the paperclip icons should be visible in the list.
First, sign in to Gmail. Click on Trash icon or you can go to Settings > labels tab and after that tap the show link next to Trash label, this is how you can recover lost attachments.
Just replace:
Content-Type: multipart/alternative; boundary=__boundary__
for:
Content-Type: multipart/mixed; boundary=__boundary__
This is my full function written in JS
function createMimeMessage_(msg) {
var nl = "\n"; var boundary = "ctrlq_dot_org";
var mimeBody = [
"MIME-Version: 1.0", "To: " + msg.to.email,//+ encode_(msg.to.name) + "<" + msg.to.email + ">", "Cc: " + msg.cc.email, "Bcc: " + msg.bcc.email, "From: " + msg.from.email,//+ encode_(msg.from.name) + "<" + msg.from.email + ">", "Subject: " + encode_(msg.subject), // takes care of accented characters "In-Reply-To: " + (msg.reply_to || ""), "References: " + (msg.reply_to || ""), "Content-Type: multipart/mixed; boundary=" + boundary + nl, "--" + boundary, // "Content-Type: text/plain; charset=UTF-8", // "Content-Transfer-Encoding: 7bit", // "Content-Disposition: inline" + nl, // msg.body.text + nl, // "--" + boundary, "Content-Type: text/html; charset=UTF-8", "Content-Transfer-Encoding: base64" + nl, new Buffer(msg.body.text).toString('base64') + nl,
];
for (var i = 0; i < msg.files.length; i++) {
var attachment = [ "--" + boundary, "Content-Type: " + msg.files[i].mimeType + '; name="' + msg.files[i].fileName + '"', 'Content-Disposition: attachment; filename="' + msg.files[i].fileName + '"', "Content-Transfer-Encoding: base64" + nl, msg.files[i].bytes ]; mimeBody.push(attachment.join(nl));
}
mimeBody.push("--" + boundary + "--"); //console.log(mimeBody);
return mimeBody.join(nl);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With