Why the attachment option needs a Blob, not a URL
The attachments key inside GmailApp.sendEmail()'s options object expects an array of Blob objects. A Blob (Binary Large Object) is Apps Script's in-memory representation of file bytes plus a MIME type. It is not a URL, not a Drive link, and not a file ID string.
The first time I hit this, I passed a Drive sharing URL as the attachment value and the email arrived clean — body only, no file. No error was thrown. GmailApp silently drops values it cannot serialize as RFC 2822 MIME parts, which makes this failure invisible unless you check the sent message.
The correct path: DriveApp.getFileById(fileId) returns a File object, and calling .getBlob() on that File object fetches the bytes and wraps them with the file's detected MIME type. That Blob is what you put in the array.