A high-performance AWS Lambda service for processing DOCX mail merge operations with field extraction, validation, and document merging capabilities.
Flash Mail Merge is a serverless solution that extracts merge fields from DOCX documents, validates merge data, and performs complete mail merge operations. It's designed to be fast, scalable, and cost-effective for processing large volumes of documents with comprehensive logging and error handling.
- DOCX Processing: Extracts and processes Microsoft Word documents with full ZIP archive handling
- DOCX Validation: Validates DOCX file signature and structure integrity
- Merge Field Detection: Automatically detects merge fields in documents with support for complex field types
- Data Validation: Validates merge data against field requirements with detailed error reporting
- Mail Merge Execution: Performs complete mail merge operations with field replacement
- Duplicate Key Detection: Detects and handles duplicate keys in merge data with first-win logic
- Comprehensive Logging: Structured logging with configurable log levels
- Serverless Architecture: Runs on AWS Lambda with API Gateway and S3 integration
- Type Safety: Full type checking for merge field data with Go's strong typing
The project is structured as follows:
flash-mail-merge/
├── main.go # Main Lambda handler (current entry point)
├── cmd/handler/ # Alternative handler (template)
│ └── main.go # Basic Lambda handler template
├── internal/
│ ├── docx/ # DOCX file processing
│ │ ├── unzip.go # ZIP archive handling and extraction
│ │ ├── zip.go # ZIP archive creation
│ │ └── *_test.go # Unit tests
│ ├── fields/ # Merge field operations
│ │ ├── extract.go # Field extraction logic
│ │ ├── models.go # Data models and validation
│ │ ├── parse.go # Field parsing utilities
│ │ └── *_test.go # Unit tests
│ ├── merge/ # Mail merge operations
│ │ ├── merge.go # Core merge functionality
│ │ └── merge_test.go # Unit tests
│ └── logging/ # Logging utilities
│ └── log.go # Structured logging
├── tests/ # Unit tests and sample files
├── tests_manual/ # Manual testing files and events
└── deploy/ # SAM/CloudFormation templates
└── template.yaml # AWS SAM template
- Install Go 1.21 or later (project uses Go 1.24.5)
- Clone the repository
- Run tests:
go test ./...
- Build:
go build -o main main.go
- Test locally:
make local
(starts SAM local API)
The service is deployed using AWS SAM (Serverless Application Model) with a Makefile workflow:
-
Configure AWS credentials
aws configure
-
Create S3 deployment bucket (if needed)
make create-bucket
-
Build and deploy
make build && make package && make deploy
Or use the simplified workflow:
make deploy-all
-
Available Make targets:
make build
- Build the Go binary for Lambda (createsbootstrap
)make test
- Run testsmake package
- Package the SAM applicationmake deploy
- Deploy the SAM applicationmake deploy-all
- Build, package, and deploy in one commandmake validate
- Validate the SAM templatemake local
- Start local API for testingmake create-bucket
- Create S3 bucket for deploymentmake clean
- Clean build artifactsmake delete
- Delete the CloudFormation stack
-
Configuration:
- Runtime:
go1.x
- Handler:
bootstrap
- Memory: 256 MB
- Timeout: 30 seconds
- API Gateway: POST
/merge
and POST/detect
- Binary media types enabled for DOCX files
- S3 buckets for document storage and results
- API Key authentication with usage plans
- Runtime:
The service provides two main endpoints for different use cases:
Performs field extraction, data validation, and optional mail merge operations.
{
"docx": "base64-encoded DOCX content", // Required
"data": { // Optional
"FieldName1": "value1",
"FieldName2": "value2"
}
}
{
"validation": {
"valid": true,
"errors": [],
"warnings": []
},
"mergedDocument": "base64-encoded-result-docx", // Only when data provided
"skippedFields": [] // Only when data provided
}
curl -X POST https://your-api-gateway-url/merge \
-H "Content-Type: application/json" \
-H "x-api-key: your-api-key" \
-d '{
"docx": "UEsDBAoAAAAAAJZQV1cAAAAAAAAAAAAAAAAJAAAAZG9jUHJvcHMv...",
"data": {
"FirstName": "John",
"LastName": "Doe",
"Email": "john.doe@example.com"
}
}'
- 400 Bad Request: Invalid JSON, missing 'docx' field, invalid base64, or validation errors
- 500 Internal Server Error: Document processing failure or merge operation error
Extracts merge fields from DOCX documents without performing validation or merge operations.
{
"docx": "base64-encoded DOCX content" // Required
}
{
"data": {
"FieldName1": "",
"FieldName2": "",
"FieldName3": ""
}
}
curl -X POST https://your-api-gateway-url/detect \
-H "Content-Type: application/json" \
-H "x-api-key: your-api-key" \
-d '{
"docx": "UEsDBAoAAAAAAJZQV1cAAAAAAAAAAAAAAAAJAAAAZG9jUHJvcHMv..."
}'
{
"data": {
"FirstName": "",
"LastName": "",
"Email": "",
"CompanyName": "",
"Address": ""
}
}
- 400 Bad Request: Invalid JSON, missing 'docx' field, or invalid base64
- 500 Internal Server Error: Document processing failure or field extraction error
All endpoints return errors in the following format:
{
"error": "Error message description"
}
Both endpoints require API Key authentication:
- Include
x-api-key
header with your API key - API keys are managed through AWS API Gateway
- Rate limiting: 100 requests/second, 200 burst
- Daily quota: 10,000 requests
- Field Extraction: Automatically detects merge fields in DOCX documents
- Data Validation: Validates provided merge data against field requirements (merge endpoint)
- Duplicate Detection: Handles duplicate keys with first-win logic (merge endpoint)
- Mail Merge: Performs complete merge operation when data is provided (merge endpoint)
- Error Handling: Comprehensive error reporting and validation feedback
import (
"com/lifenture/flash-mail-merge/internal/docx"
)
// Extract DOCX file from bytes with validation
docxFile, err := docx.UnzipDocx(docxBytes)
if err != nil {
// Handle error (invalid DOCX, missing signature, etc.)
}
// Access document XML
documentXML := docxFile.DocumentXML
fmt.Printf("Document XML: %s\n", documentXML)
import (
"com/lifenture/flash-mail-merge/internal/docx"
"com/lifenture/flash-mail-merge/internal/fields"
)
// Load DOCX file
doc, err := docx.UnzipDocx(docxData)
if err != nil {
// Handle error
}
// Extract merge fields
fieldSet, err := fields.ExtractFields(doc)
if err != nil {
// Handle error
}
// Use extracted fields
for _, field := range fieldSet.Fields {
fmt.Printf("Field: %s, Type: %s, Required: %t\n", field.Name, field.Type, field.Required)
}
// Prepare merge data
mergeData := fields.MergeData{
"FirstName": "John",
"LastName": "Doe",
"Email": "john.doe@example.com",
}
// Validate against field set
result := fieldSet.Validate(mergeData)
if !result.Valid {
for _, error := range result.Errors {
fmt.Printf("Validation error: %s\n", error)
}
}
// Check for warnings (e.g., duplicate keys)
for _, warning := range result.Warnings {
fmt.Printf("Warning: %s\n", warning)
}
import (
"com/lifenture/flash-mail-merge/internal/merge"
)
// Perform mail merge operation
mergedBytes, skippedFields, err := merge.PerformMerge(docxFile, mergeData)
if err != nil {
// Handle error
}
// Save or process the merged document
fmt.Printf("Merge completed. Skipped fields: %v\n", skippedFields)
# Run all tests
go test ./...
# Run tests with make
make test
# Build for local development
go build -o main main.go
# Build for Lambda deployment
make build
# Run standard Go tools
go fmt ./...
go vet ./...
# If you have golint installed
golint ./...
# Run all tests
go test ./...
# Run tests with verbose output
go test -v ./...
# Run tests with coverage
go test -cover ./...
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
For detailed API reference including request/response schemas, error codes, and SDK examples, see API.md.
For issues and questions, please create an issue in the GitHub repository.