Skip to content

Commit 9e08ba2

Browse files
committed
replaced: form-data with form-data-node package for proper ESM support and edge worker support
fix: sending attachments >3MB via Buffer or Readable streams added: new examples showing how to send attachments
1 parent fd72d9d commit 9e08ba2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+5264
-481
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Changed
11+
- Upgraded node-fetch from v2 to v3 for better ESM support and compatibility with edge environments
12+
13+
### Fixed
14+
- Fixed test expectations for file attachment sizes and content types to match actual implementation behavior
15+
- Updated Jest configuration to properly handle ESM modules from node-fetch v3
16+
- Removed incompatible AbortSignal import from node-fetch externals (now uses native Node.js AbortSignal)
17+
818
## [7.11.0] - 2025-06-23
919

1020
### Added
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Dependencies
2+
node_modules/
3+
4+
# Wrangler output
5+
dist/
6+
.wrangler/
7+
8+
# Environment variables (keep .dev.vars.example but not .dev.vars)
9+
.dev.vars
10+
11+
# Logs
12+
*.log
13+
npm-debug.log*
14+
15+
# Runtime data
16+
pids
17+
*.pid
18+
*.seed
19+
*.pid.lock
20+
21+
# Coverage directory used by tools like istanbul
22+
coverage/
23+
24+
# nyc test coverage
25+
.nyc_output
26+
27+
# Dependency directories
28+
jspm_packages/
29+
30+
# Optional npm cache directory
31+
.npm
32+
33+
# Optional REPL history
34+
.node_repl_history
35+
36+
# Output of 'npm pack'
37+
*.tgz
38+
39+
# macOS
40+
.DS_Store
41+
42+
# Windows
43+
Thumbs.db
44+
ehthumbs.db
45+
46+
# IDE
47+
.vscode/
48+
.idea/
49+
*.swp
50+
*.swo
51+
52+
# vars
53+
.*.vars
Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
# Nylas Cloudflare Worker - Email Attachments Example
2+
3+
This example demonstrates how to use the Nylas SDK in a Cloudflare Worker to send email attachments. It provides a simple web interface for uploading files and sending them as email attachments.
4+
5+
## 🚀 Features
6+
7+
- **Simple Web UI**: Drag & drop or click to upload files
8+
- **File Validation**: Automatic file size and type validation (10MB max)
9+
- **Real-time Feedback**: Loading states and success/error messages
10+
- **Email Sending**: Uses the Nylas SDK to send emails with attachments
11+
- **Edge Computing**: Runs on Cloudflare's global edge network
12+
- **Node.js Compatibility**: Uses `nodejs_compat` flag for seamless Node.js module support
13+
14+
## 📋 Prerequisites
15+
16+
Before getting started, you'll need:
17+
18+
1. **Nylas Account**: [Sign up for free](https://dashboard.nylas.com/register)
19+
2. **Cloudflare Account**: [Sign up for free](https://dash.cloudflare.com/sign-up)
20+
3. **Node.js**: Version 16 or higher
21+
4. **Nylas Application**: Created in your Nylas Dashboard
22+
5. **Connected Email Account**: At least one email account connected to your Nylas application
23+
24+
## 🛠️ Setup
25+
26+
### 1. Install Dependencies
27+
28+
```bash
29+
# Navigate to the edge-environment directory
30+
cd examples/edge-environment
31+
32+
# Install dependencies
33+
npm install
34+
```
35+
36+
### 2. Configure Environment Variables
37+
38+
Copy the `.dev.vars` file and update it with your Nylas credentials:
39+
40+
```bash
41+
# Update .dev.vars with your actual values
42+
NYLAS_API_KEY=your_nylas_api_key_here
43+
NYLAS_API_URI=https://api.us.nylas.com
44+
NYLAS_GRANT_ID=your_grant_id_here
45+
TEST_EMAIL=test@example.com
46+
```
47+
48+
**How to get these values:**
49+
50+
- **NYLAS_API_KEY**: Found in your [Nylas Dashboard](https://dashboard.nylas.com/applications) under your application settings
51+
- **NYLAS_GRANT_ID**: The ID of a connected email account (found in Dashboard > Grants)
52+
- **NYLAS_API_URI**: Use `https://api.us.nylas.com` for US region, or your specific region's API URL
53+
54+
### 3. Update Wrangler Configuration
55+
56+
Edit `wrangler.toml` and update the name and environment variables as needed:
57+
58+
```toml
59+
name = "your-worker-name" # Choose a unique name for your worker
60+
61+
[env.development.vars]
62+
NYLAS_API_KEY = "your_api_key"
63+
NYLAS_GRANT_ID = "your_grant_id"
64+
# ... other variables
65+
```
66+
67+
## 🏗️ Development
68+
69+
### Start Local Development Server
70+
71+
```bash
72+
npm run dev
73+
```
74+
75+
This will:
76+
- Start the Wrangler development server
77+
- Make your worker available at `http://localhost:8787`
78+
- Enable hot-reloading for code changes
79+
- Load environment variables from `.dev.vars`
80+
81+
### Test the Application
82+
83+
1. Open `http://localhost:8787` in your browser
84+
2. Fill in the email form:
85+
- **Recipient Email**: Enter a valid email address
86+
- **Subject**: Enter an email subject
87+
- **Message**: Enter your message content
88+
- **Attachment**: Upload a file (max 10MB)
89+
3. Click "Send Email with Attachment"
90+
4. Check the recipient's inbox for the email
91+
92+
### Development Tips
93+
94+
- **File Size Limit**: The worker is configured with a 10MB file size limit
95+
- **Supported Files**: All file types are supported (PDFs, images, documents, etc.)
96+
- **Error Handling**: Check the browser console and worker logs for debugging
97+
- **Hot Reloading**: Code changes will automatically reload the worker
98+
99+
## 🚀 Deployment
100+
101+
### Option 1: Deploy to Cloudflare Workers (Recommended)
102+
103+
#### 1. Set Production Secrets
104+
105+
For security, use Wrangler secrets instead of environment variables in production:
106+
107+
```bash
108+
# Set your API key as a secret
109+
wrangler secret put NYLAS_API_KEY
110+
# Enter your API key when prompted
111+
112+
# Set your Grant ID as a secret
113+
wrangler secret put NYLAS_GRANT_ID
114+
# Enter your Grant ID when prompted
115+
116+
# Set default recipient email (optional)
117+
wrangler secret put TEST_EMAIL
118+
# Enter default email when prompted
119+
```
120+
121+
#### 2. Deploy to Production
122+
123+
```bash
124+
npm run deploy
125+
```
126+
127+
This will:
128+
- Build and upload your worker to Cloudflare
129+
- Make it available at `https://your-worker-name.your-subdomain.workers.dev`
130+
- Use the production environment configuration
131+
132+
#### 3. Test Production Deployment
133+
134+
Visit your worker's URL and test the file upload functionality.
135+
136+
### Option 2: Deploy with Custom Domain
137+
138+
If you have a custom domain managed by Cloudflare:
139+
140+
1. **Add a route in `wrangler.toml`:**
141+
```toml
142+
[[routes]]
143+
pattern = "attachments.yourdomain.com/*"
144+
zone_name = "yourdomain.com"
145+
```
146+
147+
2. **Deploy with the route:**
148+
```bash
149+
wrangler deploy
150+
```
151+
152+
## 📚 How It Works
153+
154+
### Architecture
155+
156+
```
157+
User Browser → Cloudflare Worker → Nylas API → Email Provider
158+
```
159+
160+
1. **File Upload**: User uploads a file through the web interface
161+
2. **Form Processing**: Worker receives multipart form data
162+
3. **File Processing**: File is converted to Buffer for efficient binary transfer
163+
4. **Email Sending**: Nylas SDK processes and sends the email with attachment
164+
5. **Response**: User receives confirmation or error message
165+
166+
### Key Files
167+
168+
- **`src/worker.ts`**: Main worker logic and request handling
169+
- **`wrangler.toml`**: Cloudflare Worker configuration with Node.js compatibility
170+
- **`package.json`**: Dependencies and scripts
171+
- **`.dev.vars`**: Development environment variables
172+
173+
### Technical Implementation
174+
175+
This worker uses the **Nylas SDK** with optimizations for Cloudflare Workers:
176+
177+
- **SDK Integration**: Uses the official Nylas Node.js SDK
178+
- **Buffer Attachments**: Uses native Buffer objects for efficient binary data handling
179+
- **Direct Binary Transfer**: No base64 encoding overhead (33% smaller than base64)
180+
- **Edge Optimized**: Designed specifically for Cloudflare Workers runtime
181+
182+
### Node.js Compatibility
183+
184+
This worker uses:
185+
- **`compatibility_date = "2024-09-23"`**: Enables automatic Node.js built-in module support
186+
- **`nodejs_compat` compatibility flag**: Additional Node.js compatibility features
187+
188+
These settings enable Node.js built-in modules like `crypto`, `path`, `fs`, and `stream` that are required by the Nylas SDK. The Buffer attachment approach ensures optimal performance and compatibility with the Cloudflare Workers edge environment.
189+
190+
### API Endpoints
191+
192+
- **`GET /`**: Serves the HTML upload interface
193+
- **`POST /send-attachment`**: Handles file upload and email sending
194+
- **`OPTIONS /*`**: Handles CORS preflight requests
195+
196+
## 🔧 Customization
197+
198+
### Modify File Size Limits
199+
200+
Update the file size limit in `src/worker.ts`:
201+
202+
```typescript
203+
// Check file size (10MB limit)
204+
const maxSize = 10 * 1024 * 1024; // Change this value
205+
```
206+
207+
### Use ReadableStream for Very Large Files
208+
209+
For extremely large files (>25MB), you can use ReadableStream instead of Buffer:
210+
211+
```typescript
212+
// Alternative: Use ReadableStream for very large files
213+
const stream = file.stream();
214+
const sendRequest: SendMessageRequest = {
215+
// ... other fields
216+
attachments: [{
217+
filename: file.name,
218+
contentType: getContentType(file.name),
219+
content: stream, // Use stream instead of buffer
220+
size: file.size,
221+
}],
222+
};
223+
```
224+
225+
### Customize Email Template
226+
227+
Modify the email HTML template in `src/worker.ts`:
228+
229+
```typescript
230+
body: `
231+
<div style="font-family: Arial, sans-serif;">
232+
<h2>Your Custom Email Template</h2>
233+
<p>${message}</p>
234+
<!-- Add your custom styling and content -->
235+
</div>
236+
`,
237+
```
238+
239+
### Add File Type Restrictions
240+
241+
Add file type validation in the worker:
242+
243+
```typescript
244+
// Validate file type
245+
const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
246+
if (!allowedTypes.includes(getContentType(file.name))) {
247+
return new Response(
248+
JSON.stringify({ error: 'File type not allowed' }),
249+
{ status: 400, headers: { 'Content-Type': 'application/json' } }
250+
);
251+
}
252+
```
253+
254+
## 🐛 Troubleshooting
255+
256+
### Common Issues
257+
258+
**Error: "Missing required environment variables"**
259+
- Ensure all environment variables are set in `.dev.vars` (development) or as secrets (production)
260+
- Check variable names match exactly
261+
262+
**Error: "Could not resolve [module]" (crypto, path, fs, stream)**
263+
- Ensure `compatibility_date = "2024-09-23"` or later is set in `wrangler.toml`
264+
- Ensure `compatibility_flags = ["nodejs_compat"]` is also set
265+
- These settings enable Node.js built-in modules required by the Nylas SDK
266+
- The worker uses Buffer objects for efficient binary attachment handling
267+
268+
**Error: "File size exceeds 10MB limit"**
269+
- Reduce file size or increase the limit in the worker code
270+
- Note: Cloudflare Workers have memory and CPU time limits
271+
272+
**Error: "Invalid file upload"**
273+
- Ensure you're uploading a valid file
274+
- Check that the form is submitting properly
275+
276+
**Error: "optionParams.form.getHeaders is not a function"**
277+
- This was an old SDK compatibility issue, now resolved
278+
- The worker uses Buffer attachments instead of problematic form-data
279+
- This error should not occur with the current implementation
280+
281+
**Email not received**
282+
- Verify the recipient email address
283+
- Check spam/junk folders
284+
- Verify your Nylas grant has send permissions
285+
- Check Nylas Dashboard for any API errors
286+
287+
### Debug Mode
288+
289+
Add logging to the worker for debugging:
290+
291+
```typescript
292+
console.log('File details:', {
293+
name: file.name,
294+
size: file.size,
295+
type: file.type
296+
});
297+
```
298+
299+
View logs with:
300+
```bash
301+
wrangler tail
302+
```
303+
304+
## 📖 Related Examples
305+
306+
- **Local Attachment Examples**: See `../messages/examples/` for Node.js examples
307+
- **Nylas SDK Documentation**: [https://developer.nylas.com](https://developer.nylas.com)
308+
- **Cloudflare Workers Docs**: [https://developers.cloudflare.com/workers/](https://developers.cloudflare.com/workers/)
309+
310+
## 🤝 Contributing
311+
312+
Found an issue or want to improve this example? Please:
313+
314+
1. Check existing issues in the [Nylas Node.js SDK repository](https://github.com/nylas/nylas-nodejs)
315+
2. Create a new issue or pull request
316+
3. Follow the contributing guidelines
317+
318+
## 📄 License
319+
320+
This example is part of the Nylas Node.js SDK and is licensed under the MIT License.

0 commit comments

Comments
 (0)