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
- Navigate to script.google.com in your browser
- Make sure you're logged into your dedicated testing Google account
- Click "New Project" to create a fresh script
Step 2: Add the Testing Code
- Delete the default
myFunction()
code that appears - 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
- In the function dropdown at the top, select "runAllEmailTests"
- Click the "Run" button (▶️ play icon)
- The first time, you'll need to authorize the script to access Gmail
- 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.