Lambda Node.js用SES sendRawEmail发带附件邮件遇Nested group错误求助
Hey there, sorry you're stuck with that "Nested group" error when sending attachments via SES sendRawEmail! I’ve run into this before—it almost always boils down to an invalid MIME message structure that SES can’t parse correctly. Let’s break this down and get your attachments sending smoothly.
Why the Error Happens
The "Nested group" error means SES is seeing an invalid nested MIME multipart structure. Common culprits include:
- Using the same boundary string for multiple nested multipart sections
- Nesting multipart groups in a non-standard way (like putting
multipart/alternativedirectly at the top without wrapping it inmultipart/mixedwhen attachments are present) - Forgetting to properly close boundary sections with the trailing
--
Working Node.js Example (AWS SDK v3)
Here’s a complete, tested example using the latest AWS SDK v3. This builds a valid MIME structure that supports both plain text/HTML content and attachments:
const { SESClient, SendRawEmailCommand } = require("@aws-sdk/client-ses"); const fs = require('fs'); const { Buffer } = require('buffer'); // Initialize your SES client with your region const sesClient = new SESClient({ region: 'us-east-1' }); // Replace with your region async function sendEmailWithAttachment() { // Create unique boundary strings (ensure they don't appear in your email content!) const mainBoundary = '----=_MainBoundary_000_12345ABCDEF'; const altBoundary = `${mainBoundary}_Alternative`; // Read and encode your attachment to base64 const attachmentPath = './invoice.pdf'; // Replace with your file path const attachmentData = fs.readFileSync(attachmentPath); const attachmentBase64 = attachmentData.toString('base64'); // Build the full MIME message (follow MIME standards strictly!) const mimeContent = [ `From: "Your Name" <your-email@example.com>`, `To: "Recipient Name" <recipient-email@example.com>`, `Subject: Your Invoice Attached`, `MIME-Version: 1.0`, `Content-Type: multipart/mixed; boundary="${mainBoundary}"`, ``, `This is a multi-part message in MIME format.`, ``, // Start the alternative section (plain text + HTML) `--${mainBoundary}`, `Content-Type: multipart/alternative; boundary="${altBoundary}"`, ``, `--${altBoundary}`, `Content-Type: text/plain; charset="UTF-8"`, ``, `Hi there,`, ``, `Please find your invoice attached to this email.`, ``, `Thanks,`, `Your Team`, ``, `--${altBoundary}`, `Content-Type: text/html; charset="UTF-8"`, ``, `<h3>Hi there,</h3>`, `<p>Please find your invoice attached to this email.</p>`, `<p>Thanks,<br>Your Team</p>`, ``, `--${altBoundary}--`, ``, // Start the attachment section `--${mainBoundary}`, `Content-Type: application/pdf; name="invoice.pdf"`, // Match your file type `Content-Disposition: attachment; filename="invoice.pdf"`, `Content-Transfer-Encoding: base64`, ``, attachmentBase64, ``, // Close the main boundary `--${mainBoundary}--` ].join('\r\n'); // Critical: Use CRLF line breaks for MIME compliance // Send the raw email try { const command = new SendRawEmailCommand({ RawMessage: { Data: Buffer.from(mimeContent) } }); const response = await sesClient.send(command); console.log(`Email sent! Message ID: ${response.MessageId}`); } catch (error) { console.error('Error sending email:', error); } } // Run the function sendEmailWithAttachment();
Key Things to Note
- Boundary Uniqueness: The main boundary and alternative boundary are distinct—this prevents SES from misinterpreting nested groups.
- Correct MIME Structure: We wrap the
multipart/alternative(plain text + HTML) inside amultipart/mixedcontainer (which holds the alternative content + attachments). This is the standard structure for emails with attachments. - CRLF Line Breaks: MIME requires
\r\nline breaks, not just\n. Using.join('\r\n')ensures compliance. - Attachment Encoding: Attachments must be encoded in base64, with matching
Content-TypeandContent-Dispositionheaders.
If You’re Using AWS SDK v2
If you’re still on SDK v2, the core logic is the same—just adjust the client initialization and send call:
const AWS = require('aws-sdk'); AWS.config.update({ region: 'us-east-1' }); const ses = new AWS.SES({ apiVersion: '2010-12-01' }); // ... (build mimeContent same as above) ses.sendRawEmail({ RawMessage: { Data: mimeContent } }, (err, data) => { if (err) console.error(err); else console.log('Email sent:', data); });
Double-check your MIME structure against the example above—this should resolve the "Nested group" error. Let me know if you hit any other snags!
内容的提问来源于stack exchange,提问作者jenish

