goodmail 0.3.0 → 0.4.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 +4 -4
- data/.rubocop.yml +199 -0
- data/.simplecov +55 -0
- data/CHANGELOG.md +76 -0
- data/README.md +154 -49
- data/Rakefile +12 -1
- data/context7.json +4 -0
- data/examples/PAY_TESTING_GUIDE.md +497 -0
- data/examples/pay_goodmailer.rb +518 -0
- data/lib/goodmail/action_mailer_integration.rb +286 -0
- data/lib/goodmail/builder.rb +304 -15
- data/lib/goodmail/configuration.rb +40 -2
- data/lib/goodmail/dispatcher.rb +41 -42
- data/lib/goodmail/email.rb +82 -46
- data/lib/goodmail/layout.erb +0 -1
- data/lib/goodmail/layout.rb +1 -1
- data/lib/goodmail/mailer.rb +19 -44
- data/lib/goodmail/plaintext.rb +236 -0
- data/lib/goodmail/version.rb +1 -1
- data/lib/goodmail.rb +8 -4
- metadata +22 -29
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
# Pay + Goodmail Testing Guide
|
|
2
|
+
|
|
3
|
+
Complete guide for testing all Pay gem email notifications with Goodmail.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Setup](#setup)
|
|
8
|
+
- [Viewing Emails in Development](#viewing-emails-in-development)
|
|
9
|
+
- [Testing All Email Types](#testing-all-email-types)
|
|
10
|
+
- [1. Receipt Email](#1-receipt-email)
|
|
11
|
+
- [2. Refund Email](#2-refund-email)
|
|
12
|
+
- [3. Subscription Renewing Email](#3-subscription-renewing-email)
|
|
13
|
+
- [4. Payment Action Required Email](#4-payment-action-required-email)
|
|
14
|
+
- [5. Subscription Trial Will End Email](#5-subscription-trial-will-end-email)
|
|
15
|
+
- [6. Subscription Trial Ended Email](#6-subscription-trial-ended-email)
|
|
16
|
+
- [7. Payment Failed Email](#7-payment-failed-email)
|
|
17
|
+
- [Quick Test Script](#quick-test-script)
|
|
18
|
+
- [Tips & Tricks](#tips--tricks)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
### 1. Install and Configure Goodmail
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
# Gemfile
|
|
28
|
+
gem 'goodmail'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bundle install
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
# config/initializers/goodmail.rb
|
|
37
|
+
Goodmail.configure do |config|
|
|
38
|
+
config.company_name = "Your App Name"
|
|
39
|
+
config.brand_color = "#E62F17"
|
|
40
|
+
config.logo_url = "https://your-cdn.com/logo.png"
|
|
41
|
+
config.company_url = "https://yourapp.com"
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. Copy the PayGoodmailer
|
|
46
|
+
|
|
47
|
+
Copy `examples/pay_goodmailer.rb` to your app:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cp examples/pay_goodmailer.rb app/mailers/pay_goodmailer.rb
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3. Configure Pay to Use the Mailer
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
# config/initializers/pay.rb
|
|
57
|
+
Pay.setup do |config|
|
|
58
|
+
config.parent_mailer = "ApplicationMailer"
|
|
59
|
+
config.mailer = "PayGoodmailer"
|
|
60
|
+
|
|
61
|
+
# Enable all email notifications
|
|
62
|
+
config.send_emails = true
|
|
63
|
+
config.emails.receipt = true
|
|
64
|
+
config.emails.refund = true
|
|
65
|
+
config.emails.subscription_renewing = true
|
|
66
|
+
config.emails.payment_action_required = true
|
|
67
|
+
config.emails.subscription_trial_will_end = true
|
|
68
|
+
config.emails.subscription_trial_ended = true
|
|
69
|
+
config.emails.payment_failed = true
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 4. Customize URL Helpers
|
|
74
|
+
|
|
75
|
+
Edit the URL helper methods at the bottom of `pay_goodmailer.rb`:
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
def billing_url
|
|
79
|
+
# Change this to match your app:
|
|
80
|
+
billing_path # or account_billing_url, etc.
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def dashboard_url
|
|
84
|
+
dashboard_path # or root_url, etc.
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def receipt_url(pay_charge)
|
|
88
|
+
receipt_path(pay_charge) # or charge_url(pay_charge), etc.
|
|
89
|
+
end
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Viewing Emails in Development
|
|
95
|
+
|
|
96
|
+
### Option 1: Letter Opener (Recommended)
|
|
97
|
+
|
|
98
|
+
Opens emails in your browser automatically:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
# Gemfile
|
|
102
|
+
group :development do
|
|
103
|
+
gem 'letter_opener'
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# config/environments/development.rb
|
|
107
|
+
config.action_mailer.delivery_method = :letter_opener
|
|
108
|
+
config.action_mailer.perform_deliveries = true
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Option 2: Mailer Previews
|
|
112
|
+
|
|
113
|
+
Visit `http://localhost:3000/rails/mailers` to see previews (requires creating preview classes).
|
|
114
|
+
|
|
115
|
+
### Option 3: Check Logs
|
|
116
|
+
|
|
117
|
+
Emails are logged in `log/development.log` when using the default `:test` delivery method.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Testing All Email Types
|
|
122
|
+
|
|
123
|
+
Open your Rails console:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
rails console
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Setup Test User and Fake Processor
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
# Get or create a user
|
|
133
|
+
user = User.first || User.create!(
|
|
134
|
+
email: 'test@example.com',
|
|
135
|
+
password: 'password123'
|
|
136
|
+
# ... other required fields
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# Set up the fake processor (for testing without real payments)
|
|
140
|
+
user.set_payment_processor(:fake_processor, allow_fake: true)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
### 1. Receipt Email
|
|
146
|
+
|
|
147
|
+
**Triggered when:** A payment is successfully processed (charge.succeeded webhook)
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
# Create a test charge
|
|
151
|
+
charge = user.payment_processor.charge(2999) # $29.99
|
|
152
|
+
|
|
153
|
+
# Send receipt email
|
|
154
|
+
Pay.mailer.with(
|
|
155
|
+
pay_customer: user.payment_processor,
|
|
156
|
+
pay_charge: charge
|
|
157
|
+
).receipt.deliver_now
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Expected email content:**
|
|
161
|
+
- ✅ Payment confirmation GIF
|
|
162
|
+
- ✅ Amount charged
|
|
163
|
+
- ✅ Payment method details
|
|
164
|
+
- ✅ Transaction date and ID
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
### 2. Refund Email
|
|
169
|
+
|
|
170
|
+
**Triggered when:** A charge is refunded (charge.refunded webhook)
|
|
171
|
+
|
|
172
|
+
```ruby
|
|
173
|
+
# Create a charge first
|
|
174
|
+
charge = user.payment_processor.charge(4999) # $49.99
|
|
175
|
+
|
|
176
|
+
# Simulate a refund (full refund)
|
|
177
|
+
charge.update!(amount_refunded: 4999)
|
|
178
|
+
|
|
179
|
+
# Send refund email
|
|
180
|
+
Pay.mailer.with(
|
|
181
|
+
pay_customer: user.payment_processor,
|
|
182
|
+
pay_charge: charge
|
|
183
|
+
).refund.deliver_now
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**For a partial refund:**
|
|
187
|
+
|
|
188
|
+
```ruby
|
|
189
|
+
charge.update!(amount_refunded: 2000) # $20.00 refund on $49.99 charge
|
|
190
|
+
Pay.mailer.with(
|
|
191
|
+
pay_customer: user.payment_processor,
|
|
192
|
+
pay_charge: charge
|
|
193
|
+
).refund.deliver_now
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Expected email content:**
|
|
197
|
+
- ✅ Refund confirmation GIF
|
|
198
|
+
- ✅ Refund amount
|
|
199
|
+
- ✅ Original charge amount
|
|
200
|
+
- ✅ Processing timeline (5-10 business days)
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### 3. Subscription Renewing Email
|
|
205
|
+
|
|
206
|
+
**Triggered when:** Annual subscription will renew soon (invoice.upcoming webhook)
|
|
207
|
+
|
|
208
|
+
```ruby
|
|
209
|
+
# Create a subscription
|
|
210
|
+
subscription = user.payment_processor.subscribe(
|
|
211
|
+
name: "Pro Plan",
|
|
212
|
+
trial_ends_at: nil
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Send renewal notice (with renewal date)
|
|
216
|
+
Pay.mailer.with(
|
|
217
|
+
pay_customer: user.payment_processor,
|
|
218
|
+
pay_subscription: subscription,
|
|
219
|
+
date: 30.days.from_now
|
|
220
|
+
).subscription_renewing.deliver_now
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Expected email content:**
|
|
224
|
+
- ✅ Renewal reminder
|
|
225
|
+
- ✅ Subscription plan name
|
|
226
|
+
- ✅ Next billing date
|
|
227
|
+
- ✅ Days until renewal
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
### 4. Payment Action Required Email
|
|
232
|
+
|
|
233
|
+
**Triggered when:** Payment needs additional authentication (invoice.payment_action_required webhook)
|
|
234
|
+
|
|
235
|
+
```ruby
|
|
236
|
+
# Create a subscription (or use existing)
|
|
237
|
+
subscription = user.payment_processor.subscriptions.last ||
|
|
238
|
+
user.payment_processor.subscribe(name: "Pro Plan")
|
|
239
|
+
|
|
240
|
+
# Send payment action required email
|
|
241
|
+
Pay.mailer.with(
|
|
242
|
+
pay_subscription: subscription,
|
|
243
|
+
payment_intent_id: "pi_test_123" # Optional
|
|
244
|
+
).payment_action_required.deliver_now
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Expected email content:**
|
|
248
|
+
- ✅ Action needed alert
|
|
249
|
+
- ✅ Security verification explanation
|
|
250
|
+
- ✅ "Complete Payment" button
|
|
251
|
+
- ✅ Urgency message
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
### 5. Subscription Trial Will End Email
|
|
256
|
+
|
|
257
|
+
**Triggered when:** Trial period ending in 3 days (customer.subscription.trial_will_end webhook)
|
|
258
|
+
|
|
259
|
+
```ruby
|
|
260
|
+
# Create a subscription with trial
|
|
261
|
+
subscription = user.payment_processor.subscribe(
|
|
262
|
+
name: "Pro Plan",
|
|
263
|
+
trial_ends_at: 7.days.from_now
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
# Send trial ending email
|
|
267
|
+
Pay.mailer.with(
|
|
268
|
+
pay_subscription: subscription
|
|
269
|
+
).subscription_trial_will_end.deliver_now
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**Expected email content:**
|
|
273
|
+
- ✅ Trial ending reminder
|
|
274
|
+
- ✅ Days remaining
|
|
275
|
+
- ✅ Trial end date
|
|
276
|
+
- ✅ What happens after trial
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### 6. Subscription Trial Ended Email
|
|
281
|
+
|
|
282
|
+
**Triggered when:** Trial period has ended
|
|
283
|
+
|
|
284
|
+
#### Active Subscription (payment successful):
|
|
285
|
+
|
|
286
|
+
```ruby
|
|
287
|
+
# Create active subscription (trial just ended)
|
|
288
|
+
subscription = user.payment_processor.subscribe(
|
|
289
|
+
name: "Pro Plan",
|
|
290
|
+
trial_ends_at: 1.day.ago,
|
|
291
|
+
status: "active"
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
# Send trial ended email
|
|
295
|
+
Pay.mailer.with(
|
|
296
|
+
pay_subscription: subscription
|
|
297
|
+
).subscription_trial_ended.deliver_now
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Expected email content:**
|
|
301
|
+
- ✅ Trial completion notice
|
|
302
|
+
- ✅ Active subscription confirmation
|
|
303
|
+
- ✅ Thank you message
|
|
304
|
+
|
|
305
|
+
#### Inactive Subscription (payment failed):
|
|
306
|
+
|
|
307
|
+
```ruby
|
|
308
|
+
# Create inactive subscription
|
|
309
|
+
subscription = user.payment_processor.subscribe(
|
|
310
|
+
name: "Pro Plan",
|
|
311
|
+
trial_ends_at: 1.day.ago
|
|
312
|
+
)
|
|
313
|
+
subscription.update!(status: "incomplete")
|
|
314
|
+
|
|
315
|
+
# Send trial ended email
|
|
316
|
+
Pay.mailer.with(
|
|
317
|
+
pay_subscription: subscription
|
|
318
|
+
).subscription_trial_ended.deliver_now
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**Expected email content:**
|
|
322
|
+
- ✅ Trial ended notice
|
|
323
|
+
- ✅ Payment failure message
|
|
324
|
+
- ✅ "Update Payment Method" button
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
### 7. Payment Failed Email
|
|
329
|
+
|
|
330
|
+
**Triggered when:** Subscription payment fails (invoice.payment_failed webhook)
|
|
331
|
+
|
|
332
|
+
```ruby
|
|
333
|
+
# Create a subscription
|
|
334
|
+
subscription = user.payment_processor.subscribe(name: "Pro Plan")
|
|
335
|
+
|
|
336
|
+
# Send payment failed email
|
|
337
|
+
Pay.mailer.with(
|
|
338
|
+
pay_subscription: subscription
|
|
339
|
+
).payment_failed.deliver_now
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**Expected email content:**
|
|
343
|
+
- ✅ "Uh-oh!" GIF
|
|
344
|
+
- ✅ Payment failure notice
|
|
345
|
+
- ✅ Common failure reasons
|
|
346
|
+
- ✅ "Update Payment Info" button
|
|
347
|
+
- ✅ Urgency message
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## Quick Test Script
|
|
352
|
+
|
|
353
|
+
Run all email tests at once:
|
|
354
|
+
|
|
355
|
+
```ruby
|
|
356
|
+
# rails console
|
|
357
|
+
|
|
358
|
+
# Setup
|
|
359
|
+
user = User.first
|
|
360
|
+
user.set_payment_processor(:fake_processor, allow_fake: true)
|
|
361
|
+
|
|
362
|
+
# Test all emails
|
|
363
|
+
puts "Testing Receipt..."
|
|
364
|
+
charge = user.payment_processor.charge(2999)
|
|
365
|
+
Pay.mailer.with(pay_customer: user.payment_processor, pay_charge: charge).receipt.deliver_now
|
|
366
|
+
|
|
367
|
+
puts "Testing Refund..."
|
|
368
|
+
charge.update!(amount_refunded: 2999)
|
|
369
|
+
Pay.mailer.with(pay_customer: user.payment_processor, pay_charge: charge).refund.deliver_now
|
|
370
|
+
|
|
371
|
+
puts "Testing Subscription Renewing..."
|
|
372
|
+
subscription = user.payment_processor.subscribe(name: "Pro Plan")
|
|
373
|
+
Pay.mailer.with(pay_subscription: subscription, date: 30.days.from_now).subscription_renewing.deliver_now
|
|
374
|
+
|
|
375
|
+
puts "Testing Payment Action Required..."
|
|
376
|
+
Pay.mailer.with(pay_subscription: subscription).payment_action_required.deliver_now
|
|
377
|
+
|
|
378
|
+
puts "Testing Trial Will End..."
|
|
379
|
+
subscription.update!(trial_ends_at: 7.days.from_now)
|
|
380
|
+
Pay.mailer.with(pay_subscription: subscription).subscription_trial_will_end.deliver_now
|
|
381
|
+
|
|
382
|
+
puts "Testing Trial Ended (Active)..."
|
|
383
|
+
subscription.update!(trial_ends_at: 1.day.ago, status: "active")
|
|
384
|
+
Pay.mailer.with(pay_subscription: subscription).subscription_trial_ended.deliver_now
|
|
385
|
+
|
|
386
|
+
puts "Testing Payment Failed..."
|
|
387
|
+
Pay.mailer.with(pay_subscription: subscription).payment_failed.deliver_now
|
|
388
|
+
|
|
389
|
+
puts "✅ All emails sent! Check your browser (Letter Opener) or logs."
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## Tips & Tricks
|
|
395
|
+
|
|
396
|
+
### Testing with Stripe CLI (Most Realistic)
|
|
397
|
+
|
|
398
|
+
For end-to-end testing with real webhook events:
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
# Install Stripe CLI
|
|
402
|
+
brew install stripe/stripe-cli/stripe
|
|
403
|
+
|
|
404
|
+
# Login
|
|
405
|
+
stripe login
|
|
406
|
+
|
|
407
|
+
# Forward webhooks to local server
|
|
408
|
+
stripe listen --forward-to localhost:3000/pay/webhooks/stripe
|
|
409
|
+
|
|
410
|
+
# In another terminal, trigger events
|
|
411
|
+
stripe trigger payment_intent.succeeded
|
|
412
|
+
stripe trigger charge.refunded
|
|
413
|
+
stripe trigger customer.subscription.updated
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Customizing GIF Images
|
|
417
|
+
|
|
418
|
+
Replace the GIF URLs in `pay_goodmailer.rb`:
|
|
419
|
+
|
|
420
|
+
```ruby
|
|
421
|
+
# Change from:
|
|
422
|
+
image("https://assets.rameerez.com/mailers/ok.gif", "Payment confirmed!", width: 250)
|
|
423
|
+
|
|
424
|
+
# To your own:
|
|
425
|
+
image("https://your-cdn.com/success.gif", "Payment confirmed!", width: 250)
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Adding i18n Translations
|
|
429
|
+
|
|
430
|
+
Create `config/locales/pay.en.yml`:
|
|
431
|
+
|
|
432
|
+
```yaml
|
|
433
|
+
en:
|
|
434
|
+
pay:
|
|
435
|
+
mailer:
|
|
436
|
+
receipt:
|
|
437
|
+
subject: "Your payment receipt from %{application_name}"
|
|
438
|
+
title: "Payment Received!"
|
|
439
|
+
message: "Thanks for your payment!"
|
|
440
|
+
refund:
|
|
441
|
+
subject: "Refund processed"
|
|
442
|
+
title: "Refund Processed"
|
|
443
|
+
# ... etc
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Testing Email Delivery
|
|
447
|
+
|
|
448
|
+
Verify emails are actually being sent:
|
|
449
|
+
|
|
450
|
+
```ruby
|
|
451
|
+
# Check ActionMailer deliveries
|
|
452
|
+
ActionMailer::Base.deliveries.count
|
|
453
|
+
ActionMailer::Base.deliveries.last.subject
|
|
454
|
+
ActionMailer::Base.deliveries.last.to
|
|
455
|
+
|
|
456
|
+
# Clear deliveries
|
|
457
|
+
ActionMailer::Base.deliveries.clear
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Debugging
|
|
461
|
+
|
|
462
|
+
If emails aren't sending:
|
|
463
|
+
|
|
464
|
+
1. Check Pay configuration: `Pay.send_emails` should be `true`
|
|
465
|
+
2. Check individual email settings: `Pay.emails.receipt` etc.
|
|
466
|
+
3. Check mailer is configured: `Pay.mailer` should return `"PayGoodmailer"`
|
|
467
|
+
4. Check logs for errors: `tail -f log/development.log`
|
|
468
|
+
5. Verify Goodmail is configured: `Goodmail.config.company_name`
|
|
469
|
+
|
|
470
|
+
### Production Testing Checklist
|
|
471
|
+
|
|
472
|
+
Before deploying to production:
|
|
473
|
+
|
|
474
|
+
- [ ] Customize all URL helper methods
|
|
475
|
+
- [ ] Replace GIF URLs with your own (or remove them)
|
|
476
|
+
- [ ] Add i18n translations (optional)
|
|
477
|
+
- [ ] Configure Goodmail with your branding
|
|
478
|
+
- [ ] Test with real Stripe test mode webhooks
|
|
479
|
+
- [ ] Verify emails look good in Gmail, Outlook, Apple Mail
|
|
480
|
+
- [ ] Check spam score (use mail-tester.com)
|
|
481
|
+
- [ ] Set up proper SMTP/email delivery service
|
|
482
|
+
- [ ] Configure SPF, DKIM, DMARC records
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## Need Help?
|
|
487
|
+
|
|
488
|
+
- **Goodmail Issues:** https://github.com/rameerez/goodmail/issues
|
|
489
|
+
- **Pay Gem Issues:** https://github.com/pay-rails/pay/issues
|
|
490
|
+
- **Email not sending?** Check that `config.action_mailer.perform_deliveries = true` in your environment
|
|
491
|
+
- **Emails look wrong?** Verify Goodmail configuration in `config/initializers/goodmail.rb`
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
**Happy testing!** 🎉
|
|
496
|
+
|
|
497
|
+
If you find this guide helpful, please star the [Goodmail repository](https://github.com/rameerez/goodmail)!
|