CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sendgrid--mail

Twilio SendGrid NodeJS mail service for sending transactional and marketing emails with templates, attachments, and advanced delivery features.

Pending
Overview
Eval results
Files

attachments-content.mddocs/

Attachments and Content

Attachments and content management provide comprehensive support for file attachments, multiple content types, and rich media in emails. This includes file attachments, inline images, and various content formats.

Capabilities

File Attachments

Attach files to emails with support for various file types and configurations.

// Attachment data structure
interface AttachmentData {
  content: string;        // Base64-encoded file content (required)
  filename: string;       // File name (required)
  type?: string;         // MIME type (optional, auto-detected if not provided)
  disposition?: string;   // "attachment" or "inline" (default: "attachment")
  contentId?: string;    // Content-ID for inline attachments (for <img> tags)
}

// Add attachments to email
const msg = {
  to: 'recipient@example.com',
  from: 'sender@example.com',
  subject: 'Email with Attachments',
  text: 'Please find attached files.',
  attachments: [attachmentData]
};

Usage Examples:

const fs = require('fs');
const path = require('path');

// Basic file attachment
const pdfAttachment = {
  content: fs.readFileSync('./report.pdf', { encoding: 'base64' }),
  filename: 'monthly-report.pdf',
  type: 'application/pdf',
  disposition: 'attachment'
};

const msg = {
  to: 'client@example.com',
  from: 'reports@example.com',
  subject: 'Monthly Report',
  text: 'Please find your monthly report attached.',
  attachments: [pdfAttachment]
};

// Multiple attachments with different types
const attachments = [
  {
    content: fs.readFileSync('./invoice.pdf', { encoding: 'base64' }),
    filename: 'invoice-2024-03.pdf',
    type: 'application/pdf'
  },
  {
    content: fs.readFileSync('./data.csv', { encoding: 'base64' }),
    filename: 'export-data.csv',
    type: 'text/csv'
  },
  {
    content: fs.readFileSync('./image.jpg', { encoding: 'base64' }),
    filename: 'product-photo.jpg',
    type: 'image/jpeg'
  }
];

const multiAttachmentMsg = {
  to: 'customer@example.com',
  from: 'orders@example.com',
  subject: 'Order Complete - Invoice and Details',
  html: '<p>Your order is complete. Please find attached your invoice and order details.</p>',
  attachments: attachments
};

Inline Images

Embed images directly in HTML emails using Content-ID references.

// Inline image attachment
const inlineImage = {
  content: base64ImageContent,
  filename: 'image.jpg',
  type: 'image/jpeg',
  disposition: 'inline',
  contentId: 'myimage'  // Used in HTML as <img src="cid:myimage">
};

// HTML content referencing inline image
const htmlContent = `
  <html>
    <body>
      <h1>Welcome!</h1>
      <p>Here's our logo:</p>
      <img src="cid:myimage" alt="Company Logo" width="200">
    </body>
  </html>
`;

Usage Examples:

const fs = require('fs');

// Single inline image
const logoImage = {
  content: fs.readFileSync('./logo.png', { encoding: 'base64' }),
  filename: 'logo.png',
  type: 'image/png',
  disposition: 'inline',
  contentId: 'company-logo'
};

const emailWithLogo = {
  to: 'customer@example.com',
  from: 'welcome@example.com',
  subject: 'Welcome to Our Service',
  html: `
    <div style="text-align: center;">
      <img src="cid:company-logo" alt="Welcome" style="max-width: 300px;">
      <h1>Welcome to Example Corp!</h1>
      <p>We're excited to have you on board.</p>
    </div>
  `,
  attachments: [logoImage]
};

// Multiple inline images
const headerImage = {
  content: fs.readFileSync('./header.jpg', { encoding: 'base64' }),
  filename: 'header.jpg',
  type: 'image/jpeg',
  disposition: 'inline',
  contentId: 'header-image'
};

const productImage = {
  content: fs.readFileSync('./product.jpg', { encoding: 'base64' }),
  filename: 'product.jpg', 
  type: 'image/jpeg',
  disposition: 'inline',
  contentId: 'product-image'
};

const newsletterMsg = {
  to: 'subscriber@example.com',
  from: 'newsletter@example.com',
  subject: 'March Newsletter - New Products',
  html: `
    <html>
      <body>
        <img src="cid:header-image" alt="Newsletter Header" style="width: 100%; max-width: 600px;">
        <h2>Featured Product This Month</h2>
        <div style="display: flex; align-items: center;">
          <img src="cid:product-image" alt="Product" style="width: 200px; margin-right: 20px;">
          <div>
            <h3>Amazing Product</h3>
            <p>This month's featured product offers incredible value...</p>
          </div>
        </div>
      </body>
    </html>
  `,
  attachments: [headerImage, productImage]
};

Attachment Class

Use the Attachment class for programmatic attachment creation and management.

const { Attachment } = require('@sendgrid/helpers').classes;

/**
 * Create a new attachment instance
 * @param data - Optional initial attachment data
 */
const attachment = new Attachment(data);

// Setter methods
attachment.setContent(content);           // Set base64 content
attachment.setFilename(filename);         // Set filename
attachment.setType(type);                // Set MIME type
attachment.setDisposition(disposition);   // Set disposition
attachment.setContentId(contentId);       // Set content ID

// Data population
attachment.fromData(data);               // Populate from data object

// JSON conversion
const jsonData = attachment.toJSON();    // Convert to API format

Usage Examples:

const { Attachment } = require('@sendgrid/helpers').classes;
const fs = require('fs');

// Create attachment using class
const attachment = new Attachment();
attachment.setContent(fs.readFileSync('./document.pdf', { encoding: 'base64' }));
attachment.setFilename('important-document.pdf');
attachment.setType('application/pdf');
attachment.setDisposition('attachment');

// Create multiple attachments programmatically
const files = [
  { path: './file1.txt', name: 'document1.txt', type: 'text/plain' },
  { path: './file2.jpg', name: 'image1.jpg', type: 'image/jpeg' },
  { path: './file3.pdf', name: 'report1.pdf', type: 'application/pdf' }
];

const attachments = files.map(file => {
  const attachment = new Attachment();
  attachment.setContent(fs.readFileSync(file.path, { encoding: 'base64' }));
  attachment.setFilename(file.name);
  attachment.setType(file.type);
  return attachment;
});

const msg = {
  to: 'recipient@example.com',
  from: 'sender@example.com',
  subject: 'Multiple Documents',
  text: 'Please find all requested documents attached.',
  attachments: attachments
};

Content Types and Management

Manage various content types including text, HTML, and custom formats.

// Content structure
interface MailContent {
  type: string;   // MIME type (e.g., "text/plain", "text/html")
  value: string;  // Content body
}

// Using Mail class for content management
const mail = new Mail();

// Content management methods
mail.setContent(content);         // Set content array
mail.addContent(content);         // Add single content item
mail.addTextContent(text);        // Add plain text
mail.addHtmlContent(html);        // Add HTML content

Usage Examples:

const { Mail } = require('@sendgrid/helpers').classes;

// Multiple content types
const mail = new Mail();
mail.setFrom('sender@example.com');
mail.addTo('recipient@example.com');
mail.setSubject('Multi-format Email');

// Add text version
mail.addTextContent(`
Welcome to Our Service!

Thank you for signing up. Here are your next steps:
1. Verify your email address
2. Complete your profile
3. Start using our features

Best regards,
The Team
`);

// Add HTML version
mail.addHtmlContent(`
<html>
  <body style="font-family: Arial, sans-serif;">
    <h1 style="color: #333;">Welcome to Our Service!</h1>
    <p>Thank you for signing up. Here are your next steps:</p>
    <ol>
      <li>Verify your email address</li>
      <li>Complete your profile</li>
      <li>Start using our features</li>
    </ol>
    <p style="color: #666;">Best regards,<br>The Team</p>
  </body>
</html>
`);

// Custom content type (e.g., calendar invite)
mail.addContent({
  type: 'text/calendar; method=REQUEST',
  value: `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp//CalDAV Client//EN
BEGIN:VEVENT
UID:meeting-12345@example.com
DTSTART:20240315T140000Z
DTEND:20240315T150000Z
SUMMARY:Team Meeting
DESCRIPTION:Weekly team sync meeting
ORGANIZER:mailto:organizer@example.com
ATTENDEE:mailto:recipient@example.com
END:VEVENT
END:VCALENDAR`
});

File Upload Helpers

Utility functions for common file operations and encoding.

// File encoding utility functions
function encodeFileToBase64(filePath) {
  return fs.readFileSync(filePath, { encoding: 'base64' });
}

function createAttachmentFromFile(filePath, filename, mimeType) {
  return {
    content: encodeFileToBase64(filePath),
    filename: filename || path.basename(filePath),
    type: mimeType || getMimeType(filePath),
    disposition: 'attachment'
  };
}

function createInlineImageFromFile(filePath, contentId, filename) {
  return {
    content: encodeFileToBase64(filePath),
    filename: filename || path.basename(filePath),
    type: getMimeType(filePath),
    disposition: 'inline',
    contentId: contentId
  };
}

// MIME type detection
function getMimeType(filePath) {
  const ext = path.extname(filePath).toLowerCase();
  const mimeTypes = {
    '.pdf': 'application/pdf',
    '.doc': 'application/msword',
    '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    '.xls': 'application/vnd.ms-excel',
    '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.png': 'image/png',
    '.gif': 'image/gif',
    '.txt': 'text/plain',
    '.csv': 'text/csv',
    '.json': 'application/json',
    '.zip': 'application/zip'
  };
  return mimeTypes[ext] || 'application/octet-stream';
}

Usage Examples:

const fs = require('fs');
const path = require('path');

// Helper function usage
const documentAttachment = createAttachmentFromFile('./reports/monthly.pdf', 'March-Report.pdf');
const logoInline = createInlineImageFromFile('./assets/logo.png', 'company-logo');

const msg = {
  to: 'client@example.com',
  from: 'reports@example.com',
  subject: 'Monthly Report with Branding',
  html: `
    <div>
      <img src="cid:company-logo" alt="Logo" style="max-width: 200px;">
      <h1>Monthly Report</h1>
      <p>Please find your detailed monthly report attached.</p>
    </div>
  `,
  attachments: [documentAttachment, logoInline]
};

// Batch file processing
const attachmentDirectory = './attachments';
const files = fs.readdirSync(attachmentDirectory);

const attachments = files
  .filter(file => !file.startsWith('.')) // Skip hidden files
  .map(file => createAttachmentFromFile(
    path.join(attachmentDirectory, file),
    file
  ));

const batchMsg = {
  to: 'recipient@example.com',
  from: 'sender@example.com',
  subject: `Batch Documents - ${attachments.length} files`,
  text: `Please find ${attachments.length} documents attached.`,
  attachments: attachments
};

Best Practices

File Size and Performance

  1. Optimize file sizes: Compress images and documents before attaching
  2. Base64 encoding overhead: Remember that base64 encoding increases file size by ~33%
  3. Email size limits: Keep total email size under 25MB (including all attachments)
  4. Consider alternatives: For large files, consider linking to cloud storage instead

Security Considerations

  1. Validate file types: Only allow expected file extensions
  2. Scan for malware: Consider virus scanning for user-uploaded attachments
  3. Content-ID security: Use unique, non-guessable content IDs for inline images
  4. File name sanitization: Sanitize file names to prevent directory traversal

Deliverability Impact

  1. Attachment reputation: Some file types (like .exe) may trigger spam filters
  2. Image optimization: Optimize inline images for email clients
  3. Alternative text: Always provide alt text for images
  4. Fallback content: Provide text alternatives for rich content

Error Handling

sgMail.send(msgWithAttachments)
  .catch(error => {
    if (error.response && error.response.body) {
      const { errors } = error.response.body;
      
      errors.forEach(err => {
        if (err.field === 'attachments') {
          console.error('Attachment error:', err.message);
          // Common issues: file too large, invalid base64, unsupported type
        } else if (err.field === 'content') {
          console.error('Content error:', err.message);
          // Common issues: missing required content, invalid HTML
        }
      });
    }
  });

Install with Tessl CLI

npx tessl i tessl/npm-sendgrid--mail

docs

advanced-delivery.md

attachments-content.md

email-service.md

index.md

message-construction.md

templates-personalization.md

tracking-analytics.md

tile.json