Notice: Due to size constraints and loading performance considerations, scripts referenced in blog posts are not attached directly. To request access, please complete the following form: Script Request Form Note: A Google account is required to access the form.
Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

Prevent Manual Email Testing: Automate It with Google Apps Script

When looking to switch to a new e-mail platform it is critical to test e-mail workflows these requests need to come from outside our organisation to ensure our internal email systems were handling various scenarios correctly, simulating real-world email conditions - different content types, attachment sizes, formatting variations, and encoding scenarios that might come from external senders.

Testing email functionality manually is tedious and time-consuming, especially when you need to verify different content types, attachments, and formatting scenarios repeatedly. 

This is where, if testing from Google you can use Google Apps Script which provides a reliable solution for this external email testing that doesn't require external hosting or complex authentication setup, you need to ensure you have a test Google account for this to avoid exposing your personal e-mail address.

Important Prerequisites and Account Setup

Critical Security Requirement

Before you begin, you cannot run Google Apps Script if you have Advanced Protection Program enrollment enabled on your Google account. Apps Script requires access to your Gmail that Advanced Protection blocks for security reasons.

Testing Account Recommendation

I strongly recommend creating a dedicated Google account specifically for testing purposes. The emails will be sent from whatever Google account you're logged into when running the script, so having a separate testing account helps maintain clear separation between your personal/work email and automated testing.

Setting Up and Running the Script

Here's exactly how I set up and executed the testing suite:

Step 1: Access Google Apps Script

  1. Navigate to script.google.com in your browser
  2. Make sure you're logged into your dedicated testing Google account
  3. Click "New Project" to create a fresh script



    Then give it a name, by clicking on Untitled Project then giving it a new name:


    You will then see your Project there in the main window as below:


Step 2: Add the Testing Code

  1. Delete the default myFunction() code that appears


  2. Copy and paste the testing code (you can get this from the blue banner at the top of this blog)

Step 3: Configure the Recipient

Update the configuration at the top of the script:

const TEST_CONFIG = {
  recipient: 'slithering.sloth@bythepowerofgreyskull.com',
  senderName: 'Automated Testing',
  delayBetweenEmails: 2000
};

Step 4: Execute the Tests

  1. In the function dropdown at the top, select "runAllEmailTests"


  2. Click the "Run" button (▶️ play icon)


  3. The first time, you'll need to authorize the script to access Gmail
  4. Monitor progress in the "Execution log" at the bottom

The script runs directly in the Google Apps Script environment. You can execute it manually whenever you need to run tests, or set up triggers for automated execution, you will need to give it mailbox permissions for this to work.

Step 5: Monitor Results

Watch the execution log for status messages like:

Starting Gmail Test Suite...
✓ Basic text email sent
✓ HTML formatted email sent
✓ Email with attachments sent
All email tests completed successfully!

Creating the Master Test Function

I designed the main function to run all tests sequentially with proper error handling:

function runAllEmailTests() {
  console.log('Starting Gmail Test Suite...');
  
  try {
    sendBasicTextEmail();
    Utilities.sleep(TEST_CONFIG.delayBetweenEmails);
    
    sendHTMLFormattedEmail();
    Utilities.sleep(TEST_CONFIG.delayBetweenEmails);
    
    // ... additional tests
    
    console.log('All email tests completed successfully!');
    
  } catch (error) {
    console.error('Error during testing:', error.toString());
  }
} 

The Utilities.sleep() function ensures you do not overwhelm Gmail's servers (which for free accounts is 100 emails daily) and the try-catch block helps me identify which specific test might be failing. 

Document Format Attachments

This will simulate real business files that have the size and extensions to make testing seem more life like:

function sendDocumentAttachments() {
  const wordDoc = createWordDocument();
  const excelDoc = createExcelDocument();
  const powerpointDoc = createPowerPointDocument();
  const pdfDoc = createPDFDocument();
  const rtfDoc = createRTFDocument();
  
  const subject = '[ATTACH TEST 1] Document Format Attachments';
  
  GmailApp.sendEmail(TEST_CONFIG.recipient, subject, '', {
    htmlBody: htmlBody,
    name: TEST_CONFIG.senderName,
    attachments: [wordDoc, excelDoc, powerpointDoc, pdfDoc, rtfDoc]
  });
}

The data in this function simulates real data:

function createWordDocument() {
  const content = `CONFIDENTIAL BUSINESS CONTRACT
  
Contract Value: £2,450,000
Duration: 24 months
Party A: Our Company Inc.
Party B: Business Partner LLC

CONFIDENTIAL - NOT FOR DISTRIBUTION`;
  
  return Utilities.newBlob(content, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'contract.docx');
}

Media and Archive Files

For media testing, lets simulate various file types that commonly appear in business communications:

function sendMediaAttachments() {
  const jpegImage = Utilities.newBlob(
    'JPEG image data simulation',
    'image/jpeg',
    'company_photo.jpg'
  );
  
  const mp4Video = Utilities.newBlob(
    'MP4 video file simulation',
    'video/mp4',
    'training_video.mp4'
  );
  
  // Additional media types...
}

Archive testing focuses on compressed files that might contain multiple files:

function sendArchiveAttachments() {
  const zipFile = Utilities.newBlob(
    'PK\x03\x04 ZIP archive simulation with multiple files inside',
    'application/zip',
    'project_files.zip'
  );
  
  // Tests ZIP, RAR, TAR, GZIP formats
}

Security and Executable Files

This test specifically challenges email security systems:

function sendExecutableAttachments() {
  const exeFile = Utilities.newBlob(
    'MZ executable header simulation - Windows executable file',
    'application/octet-stream',
    'software_installer.exe'
  );
  
  const batFile = Utilities.newBlob(
    '@echo off\necho This is a test batch file\necho Safe testing content only\npause',
    'text/plain',
    'automation_script.bat'
  );
  
  // Tests EXE, BAT, SH, MSI, SCF, VBS files
}

Important note: I had to fix MIME type issues here. Google Apps Script doesn't recognize some specialized MIME types, so I used application/octet-stream for binary executables and text/plain for script files.

DLP (Data Loss Prevention) Testing

The DLP testing became the most comprehensive part of my enhanced suite. I created tests specifically for UK data patterns:

function sendDLPTestEmail() {
  const subject = '[DLP TEST 1] 🚨 Sensitive Data Patterns Detection';
  const htmlBody = `
    <h3>🔢 National Insurance Numbers:</h3>
    <p>Employee NINumbers: AB123456C, CD987654E, EF555123G</p>
    
    <h3>🏦 Bank Account Information:</h3>
    <p>Sort Code: 20-00-00 (Barclays Bank)</p>
    <p>Account Number: 12345678</p>
    <p>IBAN: GB29 NWBK 6016 1331 9268 19</p>
    
    <h3>🏥 NHS Data:</h3>
    <p>NHS Numbers: 123 456 7890, 987 654 3210</p>
  `;
}

Financial Data with UK Currency Markers

I updated all financial testing to use British Pounds and UK-specific data:

function sendFinancialDataEmail() {
  const htmlBody = `
    <h3>📊 Q4 2024 Financial Results:</h3>
    <table>
      <tr><td>Total Revenue</td><td>£12,450,000</td></tr>
      <tr><td>Net Profit</td><td>£3,120,000</td></tr>
      <tr><td>Cash on Hand</td><td>£45,670,000</td></tr>
    </table>
    
    <h3>💸 Executive Compensation:</h3>
    <ul>
      <li>CEO Base Salary: £450,000 + £1,200,000 bonus</li>
      <li>CFO Base Salary: £320,000 + £800,000 bonus</li>
    </ul>
  `;
}

UK Personal Data Patterns

The PII testing now uses realistic UK data formats:

function sendPIIDataEmail() {
  const htmlBody = `
    <h3>📋 Employee Directory Information:</h3>
    <table>
      <tr>
        <td>John Michael Smith</td>
        <td>15/03/1985</td>
        <td>020 7946 0123</td>
        <td>42 Baker Street, London, NW1 6XE</td>
      </tr>
    </table>
    
    <h3>🏥 Health Information:</h3>
    <p>NHS Number: 123 456 7890</p>
    <p>GP: Dr. Sarah Wilson, Surgery: London Medical Centre</p>
  `;
}

Large File Testing

I created a function to generate large files approaching Gmail's 25MB limit:

function createLargeDataFile(filename, targetSizeMB) {
  let content = `LARGE DATA FILE: ${filename}\n`;
  const targetBytes = targetSizeMB * 1024 * 1024;
  const linesNeeded = Math.floor(targetBytes / 200); // 200 chars per line
  
  for (let i = 0; i < linesNeeded; i++) {
    if (filename.includes('.csv')) {
      content += `${i + 1},Customer_${i + 1},${Math.random().toString(36).substring(7)}@email.co.uk,£${(Math.random() * 1000).toFixed(2)}\n`;
    }
    // Additional format handling...
  }
  
  return Utilities.newBlob(content, mimeType, filename);
}

Suspicious Filename Testing

This test specifically targets filename-based security filtering:

function sendSuspiciousFilenameAttachments() {
  const doubleExtension = Utilities.newBlob(
    'Safe test content',
    'text/plain',
    'invoice_2024.pdf.exe'
  );
  
  const hiddenExtension = Utilities.newBlob(
    'Safe test content',
    'text/plain',
    'report_2024.doc‎.exe'  // Unicode character hides real extension
  );
  
  // Tests various suspicious naming patterns
}

Performance Considerations and Quota Management

function checkEnhancedGmailLimits() {
  console.log('Enhanced Gmail Testing Limits:');
  console.log('- Daily email sending limit: 100 emails (free) / 1,500 emails (Google Workspace)');
  console.log('- Attachment size limit: 25 MB total per email');
  console.log('- DLP scanning: Sensitive data patterns may be flagged or blocked');
  
  try {
    const emailQuotaRemaining = MailApp.getRemainingDailyQuota();
    console.log('Remaining email quota today:', emailQuotaRemaining);
  } catch (error) {
    console.log('Could not check email quota:', error.toString());
  }
}

Key lessons about Gmail limits:

  • Large attachments (approaching 25MB) significantly slow down sending
  • DLP-flagged emails may not count against quotas if they're blocked
  • Complex emails with multiple attachments consume more processing time
  • Some security-flagged emails may fail silently

File Extension Restrictions in Google Apps Script

During testing, I discovered that Google Apps Script has specific security restrictions on file extensions that can cause tests to fail with Exception: Invalid argument: fileName. which behind the scenes means the file is being blocked, which leads nicley on to:

Extensions That Google Apps Script Blocks

Through individual testing of each attachment, I found that Google Apps Script completely blocks these high-risk file extensions:

  • .exe - Windows executable files (completely blocked)
  • .bat - Windows batch script files (completely blocked)
  • .vbs - VBScript files (completely blocked)

These extensions fail regardless of the MIME type used or the content of the file. Google's security policies prevent creating attachments with these extensions, even for testing purposes.

  • ty-flagged)

Updating Executable Attachment Test

This update was required to the executable check to prevent it being blocked:

function sendExecutableAttachments() {
  const exeFile = Utilities.newBlob(
    'MZ executable header simulation',
    'application/octet-stream',
    'software_installer.bin'  // Changed from .exe
  );
  
  const batFile = Utilities.newBlob(
    '@echo off\necho Test batch file\npause',
    'text/plain',
    'automation_script.cmd'  // Changed from .bat
  );
  
  const scriptFile = Utilities.newBlob(
    'console.log("Script file simulation");',
    'text/plain',
    'test_script.js'  // Changed from .vbs
  );
}

Finally lets cover the "basic" version of this testing that does not cover DLP and enhanced file attachments.

Test Case 1: Basic Text Email

I started with the simplest case - a plain text email:

function sendBasicTextEmail() {
  const subject = '[TEST 1] Basic Text Email';
  const body = `This is a basic plain text email test.
  
Testing basic functionality:
- Plain text content
- Line breaks
- Simple formatting

Sent at: ${new Date().toLocaleString()}`;

  GmailApp.sendEmail(TEST_CONFIG.recipient, subject, body);
  console.log('✓ Basic text email sent');
}

This test verifies that basic email delivery works and helps establish a baseline for more complex tests.

Test Case 2: HTML Formatted Content

For testing rich formatting, I created an HTML email with various styling elements:

function sendHTMLFormattedEmail() {
  const subject = '[TEST 2] HTML Formatted Email';
  const htmlBody = `
    <html>
      <head>
        <style>
          body { font-family: Arial, sans-serif; line-height: 1.6; }
          .header { background-color: #4285f4; color: white; padding: 20px; }
          .highlight { background-color: #fff3cd; padding: 10px; }
        </style>
      </head>
      <body>
        <div class="header">
          <h1>HTML Email Test</h1>
        </div>
        <div class="content">
          <h2>Testing HTML Features:</h2>
          <ul>
            <li><strong>Bold text</strong></li>
            <li><em>Italic text</em></li>
            <li><a href="https://www.google.com">Hyperlinks</a></li>
          </ul>
        </div>
      </body>
    </html>
  `;
  
  GmailApp.sendEmail(TEST_CONFIG.recipient, subject, '', {
    htmlBody: htmlBody,
    name: TEST_CONFIG.senderName
  });
}

I included CSS styling to test whether email clients properly render the formatting. The empty string as the third parameter tells Gmail to use only the HTML body.

Test Case 3: File Attachments

Testing attachments required creating different file types programmatically:

function sendEmailWithAttachments() {
  // Create different file types
  const textFile = Utilities.newBlob(
    'This is a test text file.\nLine 2\nLine 3', 
    'text/plain', 
    'test.txt'
  );
  
  const csvFile = Utilities.newBlob(
    'Name,Age,City\nJohn,25,New York\nJane,30,Los Angeles', 
    'text/csv', 
    'test.csv'
  );
  
  const jsonFile = Utilities.newBlob(
    '{"name": "Test", "type": "JSON", "timestamp": "' + new Date().toISOString() + '"}', 
    'application/json', 
    'test.json'
  );

  GmailApp.sendEmail(TEST_CONFIG.recipient, subject, '', {
    htmlBody: htmlBody,
    name: TEST_CONFIG.senderName,
    attachments: [textFile, csvFile, jsonFile]
  });
}

The Utilities.newBlob() method is particularly useful here - it allows me to create files of different MIME types without actually storing them anywhere.

Test Case 4: Large Attachment Testing

I wanted to test Gmail's attachment size limits, so I created a function that generates a large text file:

function sendEmailWithLargeAttachment() {
  // Create a larger text file (around 1MB)
  let largeContent = 'Large file test content.\n';
  for (let i = 0; i < 10000; i++) {
    largeContent += `Line ${i + 1}: Sample content with random number: ${Math.random()}\n`;
  }
  
  const largeFile = Utilities.newBlob(largeContent, 'text/plain', 'large-test-file.txt');
  
  // Send email with large attachment
  GmailApp.sendEmail(TEST_CONFIG.recipient, subject, '', {
    htmlBody: htmlBody,
    attachments: [largeFile]
  });
}

This test helps me understand the practical limits of email attachments and ensures my system can handle larger files.

Test Case 5: Special Characters and International Content

Email encoding can be tricky, especially with international characters and emojis. I created a comprehensive test for this:

function sendEmailWithSpecialCharacters() {
  const subject = '[TEST 7] 🧪 Email with Special Characters & Émojis 测试';
  const htmlBody = `
    <html>
      <body>
        <h2>🧪 Special Characters & Encoding Test</h2>
        <h3>🌍 International Characters:</h3>
        <ul>
          <li><strong>Spanish:</strong> ¡Hola Mundo! ñáéíóú</li>
          <li><strong>Chinese:</strong> 你好世界! 测试中文字符</li>
          <li><strong>Arabic:</strong> مرحبا بالعالم!</li>
          <li><strong>Russian:</strong> Привет мир! тест</li>
        </ul>
        <h3>😀 Emoji Tests:</h3>
        <p>🎉 🚀 💻 📧 ✅ ❌ ⚠️ 🔥 💡 🌟</p>
      </body>
    </html>
  `;
  
  GmailApp.sendEmail(TEST_CONFIG.recipient, subject, '', {
    htmlBody: htmlBody,
    name: TEST_CONFIG.senderName
  });
}

Conclusion

Building this enhanced Gmail testing suite with Google Apps Script proved very convenient when compared to using SMTP connections to external e-mail services to prove the testing, as this testing can be done remotely from any website to obtain the desired results.

Previous Post Next Post

نموذج الاتصال