poodle-ruby 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +1 -0
- data/.rubocop.yml +65 -0
- data/.yardopts +12 -0
- data/CODE_OF_CONDUCT.md +78 -0
- data/CONTRIBUTING.md +151 -0
- data/LICENSE +21 -0
- data/README.md +442 -0
- data/Rakefile +4 -0
- data/examples/advanced_usage.rb +255 -0
- data/examples/basic_usage.rb +64 -0
- data/lib/poodle/client.rb +222 -0
- data/lib/poodle/configuration.rb +145 -0
- data/lib/poodle/email.rb +190 -0
- data/lib/poodle/email_response.rb +101 -0
- data/lib/poodle/errors/authentication_error.rb +54 -0
- data/lib/poodle/errors/base_error.rb +49 -0
- data/lib/poodle/errors/forbidden_error.rb +56 -0
- data/lib/poodle/errors/network_error.rb +104 -0
- data/lib/poodle/errors/payment_error.rb +73 -0
- data/lib/poodle/errors/rate_limit_error.rb +146 -0
- data/lib/poodle/errors/server_error.rb +57 -0
- data/lib/poodle/errors/validation_error.rb +93 -0
- data/lib/poodle/http_client.rb +327 -0
- data/lib/poodle/rails/railtie.rb +50 -0
- data/lib/poodle/rails/tasks.rake +113 -0
- data/lib/poodle/rails.rb +158 -0
- data/lib/poodle/test_helpers.rb +244 -0
- data/lib/poodle/version.rb +6 -0
- data/lib/poodle.rb +80 -0
- data/sig/poodle.rbs +4 -0
- metadata +107 -0
data/README.md
ADDED
@@ -0,0 +1,442 @@
|
|
1
|
+
# Poodle Ruby SDK
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/poodle-ruby)
|
4
|
+
[](https://github.com/usepoodle/poodle-ruby/actions)
|
5
|
+
[](./LICENSE)
|
6
|
+
|
7
|
+
Ruby SDK for the Poodle's email sending API.
|
8
|
+
|
9
|
+
## Table of Contents
|
10
|
+
|
11
|
+
- [Features](#features)
|
12
|
+
- [Installation](#installation)
|
13
|
+
- [Quick Start](#quick-start)
|
14
|
+
- [Configuration](#configuration)
|
15
|
+
- [Usage Examples](#usage-examples)
|
16
|
+
- [API Reference](#api-reference)
|
17
|
+
- [Error Types](#error-types)
|
18
|
+
- [Development](#development)
|
19
|
+
- [Contributing](#contributing)
|
20
|
+
- [License](#license)
|
21
|
+
- [Support](#support)
|
22
|
+
|
23
|
+
## Features
|
24
|
+
|
25
|
+
- ๐ **Simple API** - Send emails with just a few lines of code
|
26
|
+
- ๐ **Type Safe** - Comprehensive validation and error handling
|
27
|
+
- ๐ **Environment Support** - Easy configuration via environment variables
|
28
|
+
- ๐ **Rich Content** - Support for HTML, plain text, and multipart emails
|
29
|
+
- ๐ **Retry Logic** - Built-in support for handling rate limits and network issues
|
30
|
+
- ๐งช **Test Support** - Comprehensive testing utilities and mocks
|
31
|
+
- ๐ **Well Documented** - Comprehensive documentation and examples
|
32
|
+
- ๐ฏ **Ruby 3.0+** - Modern Ruby support with keyword arguments
|
33
|
+
|
34
|
+
## Installation
|
35
|
+
|
36
|
+
Add this line to your application's Gemfile:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
gem 'poodle-ruby'
|
40
|
+
```
|
41
|
+
|
42
|
+
And then execute:
|
43
|
+
|
44
|
+
```bash
|
45
|
+
bundle install
|
46
|
+
```
|
47
|
+
|
48
|
+
Or install it yourself as:
|
49
|
+
|
50
|
+
```bash
|
51
|
+
gem install poodle-ruby
|
52
|
+
```
|
53
|
+
|
54
|
+
## Quick Start
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
require 'poodle'
|
58
|
+
|
59
|
+
# Initialize the client
|
60
|
+
client = Poodle::Client.new(api_key: 'your_api_key')
|
61
|
+
|
62
|
+
# Send an email
|
63
|
+
response = client.send(
|
64
|
+
from: 'sender@example.com',
|
65
|
+
to: 'recipient@example.com',
|
66
|
+
subject: 'Hello from Poodle!',
|
67
|
+
html: '<h1>Hello World!</h1><p>This email was sent using Poodle.</p>'
|
68
|
+
)
|
69
|
+
|
70
|
+
if response.success?
|
71
|
+
puts "Email sent successfully!"
|
72
|
+
else
|
73
|
+
puts "Failed to send email: #{response.message}"
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
## Configuration
|
78
|
+
|
79
|
+
### API Key
|
80
|
+
|
81
|
+
Set your API key in one of these ways:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
# 1. Pass directly to client
|
85
|
+
client = Poodle::Client.new(api_key: 'your_api_key')
|
86
|
+
|
87
|
+
# 2. Use environment variable
|
88
|
+
ENV['POODLE_API_KEY'] = 'your_api_key'
|
89
|
+
client = Poodle::Client.new
|
90
|
+
|
91
|
+
# 3. Use configuration object
|
92
|
+
config = Poodle::Configuration.new(
|
93
|
+
api_key: 'your_api_key',
|
94
|
+
timeout: 30,
|
95
|
+
debug: true
|
96
|
+
)
|
97
|
+
client = Poodle::Client.new(config)
|
98
|
+
```
|
99
|
+
|
100
|
+
### Environment Variables
|
101
|
+
|
102
|
+
| Variable | Description | Default |
|
103
|
+
| ------------------------ | ----------------------------- | --------------------------- |
|
104
|
+
| `POODLE_API_KEY` | Your Poodle API key | Required |
|
105
|
+
| `POODLE_BASE_URL` | API base URL | `https://api.usepoodle.com` |
|
106
|
+
| `POODLE_TIMEOUT` | Request timeout in seconds | `30` |
|
107
|
+
| `POODLE_CONNECT_TIMEOUT` | Connection timeout in seconds | `10` |
|
108
|
+
| `POODLE_DEBUG` | Enable debug logging | `false` |
|
109
|
+
|
110
|
+
## Usage Examples
|
111
|
+
|
112
|
+
### Basic Email Sending
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
# HTML email
|
116
|
+
response = client.send_html(
|
117
|
+
from: 'newsletter@example.com',
|
118
|
+
to: 'subscriber@example.com',
|
119
|
+
subject: 'Weekly Newsletter',
|
120
|
+
html: '<h1>Newsletter</h1><p>Your weekly update...</p>'
|
121
|
+
)
|
122
|
+
|
123
|
+
# Plain text email
|
124
|
+
response = client.send_text(
|
125
|
+
from: 'notifications@example.com',
|
126
|
+
to: 'user@example.com',
|
127
|
+
subject: 'Account Update',
|
128
|
+
text: 'Your account has been updated successfully.'
|
129
|
+
)
|
130
|
+
|
131
|
+
# Multipart email (HTML + Text)
|
132
|
+
response = client.send(
|
133
|
+
from: 'support@example.com',
|
134
|
+
to: 'customer@example.com',
|
135
|
+
subject: 'Welcome!',
|
136
|
+
html: '<h1>Welcome!</h1><p>Thanks for joining us.</p>',
|
137
|
+
text: 'Welcome! Thanks for joining us.'
|
138
|
+
)
|
139
|
+
```
|
140
|
+
|
141
|
+
### Using Email Objects
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
# Create an Email object for reusability and validation
|
145
|
+
email = Poodle::Email.new(
|
146
|
+
from: 'sender@example.com',
|
147
|
+
to: 'recipient@example.com',
|
148
|
+
subject: 'Important Update',
|
149
|
+
html: '<h1>Update</h1><p>Please read this important update.</p>',
|
150
|
+
text: 'Update: Please read this important update.'
|
151
|
+
)
|
152
|
+
|
153
|
+
# Check email properties
|
154
|
+
puts "Multipart email: #{email.multipart?}"
|
155
|
+
puts "Content size: #{email.content_size} bytes"
|
156
|
+
|
157
|
+
# Send the email
|
158
|
+
response = client.send_email(email)
|
159
|
+
```
|
160
|
+
|
161
|
+
### Multipart Emails (HTML + Text)
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
# Send emails with both HTML and text content for maximum compatibility
|
165
|
+
response = client.send(
|
166
|
+
from: 'newsletter@example.com',
|
167
|
+
to: 'subscriber@example.com',
|
168
|
+
subject: 'Weekly Newsletter',
|
169
|
+
html: '<h1>Newsletter</h1><p>This week\'s updates...</p>',
|
170
|
+
text: 'Newsletter\n\nThis week\'s updates...'
|
171
|
+
)
|
172
|
+
```
|
173
|
+
|
174
|
+
### Rails Integration
|
175
|
+
|
176
|
+
The Poodle SDK provides seamless Rails integration with automatic configuration and helpful rake tasks.
|
177
|
+
|
178
|
+
#### Installation
|
179
|
+
|
180
|
+
Add to your Rails application's Gemfile:
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
gem 'poodle-ruby'
|
184
|
+
```
|
185
|
+
|
186
|
+
#### Configuration
|
187
|
+
|
188
|
+
Create an initializer or let Poodle auto-configure:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
# config/initializers/poodle.rb
|
192
|
+
Poodle::Rails.configure do |config|
|
193
|
+
config.api_key = Rails.application.credentials.poodle_api_key
|
194
|
+
config.debug = Rails.env.development?
|
195
|
+
end
|
196
|
+
```
|
197
|
+
|
198
|
+
Or use environment variables:
|
199
|
+
|
200
|
+
```bash
|
201
|
+
# .env or environment
|
202
|
+
POODLE_API_KEY=your_api_key_here
|
203
|
+
```
|
204
|
+
|
205
|
+
#### Usage in Controllers
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
class NotificationController < ApplicationController
|
209
|
+
def send_welcome_email
|
210
|
+
response = Poodle::Rails.client.send(
|
211
|
+
from: "welcome@example.com",
|
212
|
+
to: params[:email],
|
213
|
+
subject: "Welcome!",
|
214
|
+
html: render_to_string("welcome_email")
|
215
|
+
)
|
216
|
+
|
217
|
+
if response.success?
|
218
|
+
render json: { status: "sent" }
|
219
|
+
else
|
220
|
+
render json: { error: response.message }, status: :unprocessable_entity
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
```
|
225
|
+
|
226
|
+
#### Rake Tasks
|
227
|
+
|
228
|
+
```bash
|
229
|
+
# Check configuration
|
230
|
+
rake poodle:config
|
231
|
+
|
232
|
+
# Test connection
|
233
|
+
rake poodle:test
|
234
|
+
|
235
|
+
# Send test email
|
236
|
+
rake poodle:send_test[recipient@example.com]
|
237
|
+
|
238
|
+
# Generate initializer
|
239
|
+
rake poodle:install
|
240
|
+
```
|
241
|
+
|
242
|
+
### Testing
|
243
|
+
|
244
|
+
The SDK includes comprehensive testing utilities for easy testing in your applications.
|
245
|
+
|
246
|
+
#### RSpec Integration
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
# spec/spec_helper.rb or spec/rails_helper.rb
|
250
|
+
require 'poodle'
|
251
|
+
|
252
|
+
RSpec.configure do |config|
|
253
|
+
config.include Poodle::TestHelpers
|
254
|
+
|
255
|
+
config.before(:each) do
|
256
|
+
Poodle.test_mode!
|
257
|
+
end
|
258
|
+
|
259
|
+
config.after(:each) do
|
260
|
+
Poodle.clear_deliveries
|
261
|
+
end
|
262
|
+
end
|
263
|
+
```
|
264
|
+
|
265
|
+
#### Testing Email Sending
|
266
|
+
|
267
|
+
```ruby
|
268
|
+
it "sends welcome email" do
|
269
|
+
expect {
|
270
|
+
UserMailer.send_welcome(user)
|
271
|
+
}.to change { Poodle.deliveries.count }.by(1)
|
272
|
+
|
273
|
+
email = Poodle.last_delivery
|
274
|
+
expect(email[:to]).to eq(user.email)
|
275
|
+
expect(email[:subject]).to include("Welcome")
|
276
|
+
expect(email[:html]).to include(user.name)
|
277
|
+
end
|
278
|
+
|
279
|
+
it "sends notification emails" do
|
280
|
+
service.send_notifications
|
281
|
+
|
282
|
+
assert_email_sent(3)
|
283
|
+
assert_email_sent_to("admin@example.com")
|
284
|
+
assert_email_sent_with_subject("Alert")
|
285
|
+
end
|
286
|
+
```
|
287
|
+
|
288
|
+
### Error Handling
|
289
|
+
|
290
|
+
```ruby
|
291
|
+
begin
|
292
|
+
response = client.send(email_data)
|
293
|
+
puts "Email sent!" if response.success?
|
294
|
+
rescue Poodle::ValidationError => e
|
295
|
+
puts "Validation failed: #{e.message}"
|
296
|
+
e.errors.each do |field, messages|
|
297
|
+
puts "#{field}: #{messages.join(', ')}"
|
298
|
+
end
|
299
|
+
rescue Poodle::AuthenticationError => e
|
300
|
+
puts "Authentication failed: #{e.message}"
|
301
|
+
rescue Poodle::RateLimitError => e
|
302
|
+
puts "Rate limited. Retry after: #{e.retry_after} seconds"
|
303
|
+
rescue Poodle::PaymentError => e
|
304
|
+
puts "Payment required: #{e.message}"
|
305
|
+
puts "Upgrade at: #{e.upgrade_url}"
|
306
|
+
rescue Poodle::ForbiddenError => e
|
307
|
+
puts "Access forbidden: #{e.message}"
|
308
|
+
rescue Poodle::NetworkError => e
|
309
|
+
puts "Network error: #{e.message}"
|
310
|
+
rescue Poodle::ServerError => e
|
311
|
+
puts "Server error: #{e.message}"
|
312
|
+
rescue Poodle::Error => e
|
313
|
+
puts "Poodle error: #{e.message}"
|
314
|
+
end
|
315
|
+
```
|
316
|
+
|
317
|
+
### Retry Logic
|
318
|
+
|
319
|
+
```ruby
|
320
|
+
def send_with_retry(client, email_data, max_retries: 3)
|
321
|
+
retries = 0
|
322
|
+
|
323
|
+
begin
|
324
|
+
client.send(email_data)
|
325
|
+
rescue Poodle::RateLimitError => e
|
326
|
+
if retries < max_retries && e.retry_after
|
327
|
+
retries += 1
|
328
|
+
sleep(e.retry_after)
|
329
|
+
retry
|
330
|
+
else
|
331
|
+
raise
|
332
|
+
end
|
333
|
+
rescue Poodle::NetworkError, Poodle::ServerError => e
|
334
|
+
if retries < max_retries
|
335
|
+
retries += 1
|
336
|
+
sleep(2 ** retries) # Exponential backoff
|
337
|
+
retry
|
338
|
+
else
|
339
|
+
raise
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
343
|
+
```
|
344
|
+
|
345
|
+
## API Reference
|
346
|
+
|
347
|
+
### Client
|
348
|
+
|
349
|
+
#### `Poodle::Client.new(config_or_api_key, **options)`
|
350
|
+
|
351
|
+
Creates a new Poodle client.
|
352
|
+
|
353
|
+
**Parameters:**
|
354
|
+
|
355
|
+
- `config_or_api_key` - Configuration object, API key string, or nil
|
356
|
+
- `**options` - Additional options (base_url, timeout, debug, etc.)
|
357
|
+
|
358
|
+
#### `client.send(from:, to:, subject:, html: nil, text: nil)`
|
359
|
+
|
360
|
+
Sends an email with the specified parameters.
|
361
|
+
|
362
|
+
#### `client.send_email(email)`
|
363
|
+
|
364
|
+
Sends an Email object.
|
365
|
+
|
366
|
+
#### `client.send_html(from:, to:, subject:, html:)`
|
367
|
+
|
368
|
+
Sends an HTML-only email.
|
369
|
+
|
370
|
+
#### `client.send_text(from:, to:, subject:, text:)`
|
371
|
+
|
372
|
+
Sends a text-only email.
|
373
|
+
|
374
|
+
### Email
|
375
|
+
|
376
|
+
#### `Poodle::Email.new(from:, to:, subject:, html: nil, text: nil)`
|
377
|
+
|
378
|
+
Creates a new Email object with validation.
|
379
|
+
|
380
|
+
**Methods:**
|
381
|
+
|
382
|
+
- `#html?` - Returns true if HTML content is present
|
383
|
+
- `#text?` - Returns true if text content is present
|
384
|
+
- `#multipart?` - Returns true if both HTML and text are present
|
385
|
+
- `#content_size` - Returns total content size in bytes
|
386
|
+
- `#to_h` - Converts to hash for API requests
|
387
|
+
|
388
|
+
### EmailResponse
|
389
|
+
|
390
|
+
#### Properties
|
391
|
+
|
392
|
+
- `#success?` - Returns true if email was successfully queued
|
393
|
+
- `#failed?` - Returns true if email sending failed
|
394
|
+
- `#message` - Response message from API
|
395
|
+
- `#data` - Additional response data
|
396
|
+
|
397
|
+
### Configuration
|
398
|
+
|
399
|
+
#### `Poodle::Configuration.new(**options)`
|
400
|
+
|
401
|
+
Creates a new configuration object.
|
402
|
+
|
403
|
+
**Options:**
|
404
|
+
|
405
|
+
- `api_key` - Your Poodle API key
|
406
|
+
- `base_url` - API base URL
|
407
|
+
- `timeout` - Request timeout in seconds
|
408
|
+
- `connect_timeout` - Connection timeout in seconds
|
409
|
+
- `debug` - Enable debug logging
|
410
|
+
- `http_options` - Additional HTTP client options
|
411
|
+
|
412
|
+
## Error Types
|
413
|
+
|
414
|
+
| Error Class | Description | HTTP Status |
|
415
|
+
| ----------------------------- | ------------------------ | ----------- |
|
416
|
+
| `Poodle::ValidationError` | Invalid request data | 400, 422 |
|
417
|
+
| `Poodle::AuthenticationError` | Invalid API key | 401 |
|
418
|
+
| `Poodle::PaymentError` | Payment required | 402 |
|
419
|
+
| `Poodle::ForbiddenError` | Access forbidden | 403 |
|
420
|
+
| `Poodle::RateLimitError` | Rate limit exceeded | 429 |
|
421
|
+
| `Poodle::ServerError` | Server error | 5xx |
|
422
|
+
| `Poodle::NetworkError` | Network/connection error | Various |
|
423
|
+
|
424
|
+
All errors inherit from `Poodle::Error` which provides:
|
425
|
+
|
426
|
+
- `#message` - Error message
|
427
|
+
- `#context` - Additional error context
|
428
|
+
- `#status_code` - HTTP status code (if applicable)
|
429
|
+
|
430
|
+
## Development
|
431
|
+
|
432
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
433
|
+
|
434
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
435
|
+
|
436
|
+
## Contributing
|
437
|
+
|
438
|
+
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on the process for submitting pull requests and our [Code of Conduct](CODE_OF_CONDUCT.md).
|
439
|
+
|
440
|
+
## License
|
441
|
+
|
442
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,255 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "poodle"
|
6
|
+
|
7
|
+
# Advanced usage example for the Poodle Ruby SDK
|
8
|
+
|
9
|
+
# Example 1: Using configuration object
|
10
|
+
puts "=== Example 1: Configuration Object ==="
|
11
|
+
|
12
|
+
config = Poodle::Configuration.new(
|
13
|
+
api_key: "your_api_key_here",
|
14
|
+
base_url: "https://api.usepoodle.com",
|
15
|
+
timeout: 60,
|
16
|
+
debug: true
|
17
|
+
)
|
18
|
+
|
19
|
+
client = Poodle::Client.new(config)
|
20
|
+
puts "Client initialized with custom configuration"
|
21
|
+
puts "User-Agent: #{config.user_agent}"
|
22
|
+
puts "Base URL: #{config.base_url}"
|
23
|
+
|
24
|
+
# Example 2: Using Email objects
|
25
|
+
puts "\n=== Example 2: Email Objects ==="
|
26
|
+
|
27
|
+
begin
|
28
|
+
# Create an Email object
|
29
|
+
email = Poodle::Email.new(
|
30
|
+
from: "newsletter@example.com",
|
31
|
+
to: "subscriber@example.com",
|
32
|
+
subject: "Weekly Newsletter - #{Date.today}",
|
33
|
+
html: <<~HTML,
|
34
|
+
<html>
|
35
|
+
<body>
|
36
|
+
<h1>Weekly Newsletter</h1>
|
37
|
+
<p>Welcome to our weekly newsletter!</p>
|
38
|
+
<ul>
|
39
|
+
<li>Feature 1: New dashboard</li>
|
40
|
+
<li>Feature 2: Improved performance</li>
|
41
|
+
<li>Feature 3: Bug fixes</li>
|
42
|
+
</ul>
|
43
|
+
<p>Best regards,<br>The Team</p>
|
44
|
+
</body>
|
45
|
+
</html>
|
46
|
+
HTML
|
47
|
+
text: <<~TEXT
|
48
|
+
Weekly Newsletter - #{Date.today}
|
49
|
+
|
50
|
+
Welcome to our weekly newsletter!
|
51
|
+
|
52
|
+
- Feature 1: New dashboard
|
53
|
+
- Feature 2: Improved performance
|
54
|
+
- Feature 3: Bug fixes
|
55
|
+
|
56
|
+
Best regards,
|
57
|
+
The Team
|
58
|
+
TEXT
|
59
|
+
)
|
60
|
+
|
61
|
+
puts "Email object created:"
|
62
|
+
puts "- From: #{email.from}"
|
63
|
+
puts "- To: #{email.to}"
|
64
|
+
puts "- Subject: #{email.subject}"
|
65
|
+
puts "- Has HTML: #{email.html?}"
|
66
|
+
puts "- Has Text: #{email.text?}"
|
67
|
+
puts "- Is Multipart: #{email.multipart?}"
|
68
|
+
puts "- Content Size: #{email.content_size} bytes"
|
69
|
+
|
70
|
+
# Send the email object
|
71
|
+
response = client.send_email(email)
|
72
|
+
puts "Email sent: #{response.success?}"
|
73
|
+
rescue Poodle::ValidationError => e
|
74
|
+
puts "Validation failed: #{e.message}"
|
75
|
+
e.errors.each do |field, messages|
|
76
|
+
puts " #{field}: #{messages.join(', ')}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Example 3: Environment variables
|
81
|
+
puts "\n=== Example 3: Environment Variables ==="
|
82
|
+
|
83
|
+
# Set environment variables
|
84
|
+
ENV["POODLE_API_KEY"] = "your_api_key_here"
|
85
|
+
ENV["POODLE_DEBUG"] = "true"
|
86
|
+
ENV["POODLE_TIMEOUT"] = "45"
|
87
|
+
|
88
|
+
# Create client using environment variables
|
89
|
+
env_client = Poodle::Client.new
|
90
|
+
puts "Client created using environment variables"
|
91
|
+
puts "Debug mode: #{env_client.config.debug?}"
|
92
|
+
puts "Timeout: #{env_client.config.timeout} seconds"
|
93
|
+
|
94
|
+
# Example 4: Multiple content types
|
95
|
+
puts "\n=== Example 4: Multiple Content Types ==="
|
96
|
+
|
97
|
+
begin
|
98
|
+
# Send email with both HTML and text content
|
99
|
+
multipart_response = client.send(
|
100
|
+
from: "newsletter@example.com",
|
101
|
+
to: "subscriber@example.com",
|
102
|
+
subject: "Weekly Newsletter",
|
103
|
+
html: "<h1>Newsletter</h1><p>This week's updates...</p>",
|
104
|
+
text: "Newsletter\n\nThis week's updates..."
|
105
|
+
)
|
106
|
+
|
107
|
+
puts "Multipart email sent: #{multipart_response.success?}"
|
108
|
+
rescue Poodle::Error => e
|
109
|
+
puts "Multipart email error: #{e.message}"
|
110
|
+
end
|
111
|
+
|
112
|
+
# Example 5: Comprehensive error handling
|
113
|
+
puts "\n=== Example 5: Error Handling ==="
|
114
|
+
|
115
|
+
def send_email_with_retry(client, email_data, max_retries: 3)
|
116
|
+
retries = 0
|
117
|
+
|
118
|
+
begin
|
119
|
+
response = client.send(email_data)
|
120
|
+
puts "Email sent successfully: #{response.message}"
|
121
|
+
response
|
122
|
+
rescue Poodle::RateLimitError => e
|
123
|
+
handle_rate_limit_error(e, retries, max_retries)
|
124
|
+
retries += 1
|
125
|
+
retry
|
126
|
+
rescue Poodle::NetworkError => e
|
127
|
+
handle_network_error(e, retries, max_retries)
|
128
|
+
retries += 1
|
129
|
+
retry
|
130
|
+
rescue Poodle::ServerError => e
|
131
|
+
handle_server_error(e, retries, max_retries)
|
132
|
+
retries += 1
|
133
|
+
retry
|
134
|
+
rescue Poodle::ValidationError => e
|
135
|
+
handle_validation_error(e)
|
136
|
+
rescue Poodle::AuthenticationError => e
|
137
|
+
handle_authentication_error(e)
|
138
|
+
rescue Poodle::PaymentError => e
|
139
|
+
handle_payment_error(e)
|
140
|
+
rescue Poodle::ForbiddenError => e
|
141
|
+
handle_forbidden_error(e)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def handle_rate_limit_error(error, retries, max_retries)
|
146
|
+
if retries < max_retries && error.retry_after
|
147
|
+
puts "Rate limited. Retrying in #{error.retry_after} seconds... (attempt #{retries + 1}/#{max_retries})"
|
148
|
+
sleep(error.retry_after)
|
149
|
+
else
|
150
|
+
puts "Rate limit exceeded. Max retries reached."
|
151
|
+
raise error
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def handle_network_error(error, retries, max_retries)
|
156
|
+
if retries < max_retries
|
157
|
+
puts "Network error. Retrying... (attempt #{retries + 1}/#{max_retries})"
|
158
|
+
sleep(2**(retries + 1)) # Exponential backoff
|
159
|
+
else
|
160
|
+
puts "Network error. Max retries reached."
|
161
|
+
raise error
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def handle_server_error(error, retries, max_retries)
|
166
|
+
if retries < max_retries
|
167
|
+
puts "Server error. Retrying... (attempt #{retries + 1}/#{max_retries})"
|
168
|
+
sleep(2**(retries + 1))
|
169
|
+
else
|
170
|
+
puts "Server error. Max retries reached."
|
171
|
+
raise error
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def handle_validation_error(error)
|
176
|
+
puts "Validation error (not retryable): #{error.message}"
|
177
|
+
puts "Errors: #{error.errors}"
|
178
|
+
raise error
|
179
|
+
end
|
180
|
+
|
181
|
+
def handle_authentication_error(error)
|
182
|
+
puts "Authentication error (not retryable): #{error.message}"
|
183
|
+
raise error
|
184
|
+
end
|
185
|
+
|
186
|
+
def handle_payment_error(error)
|
187
|
+
puts "Payment required: #{error.message}"
|
188
|
+
puts "Upgrade URL: #{error.upgrade_url}" if error.upgrade_url
|
189
|
+
raise error
|
190
|
+
end
|
191
|
+
|
192
|
+
def handle_forbidden_error(error)
|
193
|
+
puts "Access forbidden: #{error.message}"
|
194
|
+
puts "Reason: #{error.reason}" if error.reason
|
195
|
+
raise error
|
196
|
+
end
|
197
|
+
|
198
|
+
# Test the retry mechanism
|
199
|
+
email_data = {
|
200
|
+
from: "retry@example.com",
|
201
|
+
to: "test@example.com",
|
202
|
+
subject: "Retry Test",
|
203
|
+
html: "<p>Testing retry mechanism</p>"
|
204
|
+
}
|
205
|
+
|
206
|
+
begin
|
207
|
+
send_email_with_retry(client, email_data)
|
208
|
+
rescue Poodle::Error => e
|
209
|
+
puts "Final error: #{e.message}"
|
210
|
+
end
|
211
|
+
|
212
|
+
# Example 6: Batch sending (conceptual)
|
213
|
+
puts "\n=== Example 6: Batch Sending ==="
|
214
|
+
|
215
|
+
recipients = [
|
216
|
+
"user1@example.com",
|
217
|
+
"user2@example.com",
|
218
|
+
"user3@example.com"
|
219
|
+
]
|
220
|
+
|
221
|
+
successful_sends = 0
|
222
|
+
failed_sends = 0
|
223
|
+
|
224
|
+
recipients.each_with_index do |recipient, index|
|
225
|
+
response = client.send(
|
226
|
+
from: "batch@example.com",
|
227
|
+
to: recipient,
|
228
|
+
subject: "Batch Email #{index + 1}",
|
229
|
+
html: "<p>Hello #{recipient}! This is batch email ##{index + 1}</p>"
|
230
|
+
)
|
231
|
+
|
232
|
+
if response.success?
|
233
|
+
successful_sends += 1
|
234
|
+
puts "โ
Sent to #{recipient}"
|
235
|
+
else
|
236
|
+
failed_sends += 1
|
237
|
+
puts "โ Failed to send to #{recipient}: #{response.message}"
|
238
|
+
end
|
239
|
+
|
240
|
+
# Rate limiting: wait between sends
|
241
|
+
sleep(0.1)
|
242
|
+
rescue Poodle::Error => e
|
243
|
+
failed_sends += 1
|
244
|
+
puts "โ Error sending to #{recipient}: #{e.message}"
|
245
|
+
end
|
246
|
+
|
247
|
+
puts "\nBatch sending complete:"
|
248
|
+
puts "Successful: #{successful_sends}"
|
249
|
+
puts "Failed: #{failed_sends}"
|
250
|
+
puts "Total: #{recipients.length}"
|
251
|
+
|
252
|
+
# Clean up environment variables
|
253
|
+
ENV.delete("POODLE_API_KEY")
|
254
|
+
ENV.delete("POODLE_DEBUG")
|
255
|
+
ENV.delete("POODLE_TIMEOUT")
|