Skip to content

Commit bff1394

Browse files
[ADVAPP-2687]: Add an email auto‑responder that replies to outbound demo emails (#2587)
* Add demo mode replies for emails, tests * Update code formatting and copyright headers * Address feedback * Update code formatting and copyright headers --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 4fbb207 commit bff1394

7 files changed

Lines changed: 206 additions & 0 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
title: Add Email Demo Mode Auto Reply Feature
3+
created: 2026-06-03
4+
---
5+
6+
## Feature Flags
7+
8+
- App\Features\AddEmailDemoModeAutoReplyFeature
9+
10+
## Temporary Migrations
11+
12+
## Additional Cleanup

app-modules/engagement/src/Notifications/EngagementNotification.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
use AdvisingApp\Engagement\Models\EngagementBatch;
4343
use AdvisingApp\Engagement\Models\EngagementResponse;
4444
use AdvisingApp\Engagement\Settings\EngagementSettings;
45+
use AdvisingApp\IntegrationAwsSesEventHandling\Settings\SesSettings;
4546
use AdvisingApp\IntegrationTwilio\Settings\TwilioSettings;
4647
use AdvisingApp\Notification\DataTransferObjects\NotificationResultData;
4748
use AdvisingApp\Notification\Enums\EmailType;
@@ -53,6 +54,7 @@
5354
use AdvisingApp\Notification\Notifications\Contracts\HasEmailType;
5455
use AdvisingApp\Notification\Notifications\Messages\MailMessage;
5556
use AdvisingApp\Notification\Notifications\Messages\TwilioMessage;
57+
use App\Models\Tenant;
5658
use Illuminate\Bus\Queueable;
5759
use Illuminate\Contracts\Queue\ShouldQueue;
5860
use Illuminate\Database\Eloquent\Model;
@@ -164,6 +166,25 @@ public function afterSend(AnonymousNotifiable|CanBeNotified $notifiable, Message
164166
]);
165167
}
166168

169+
$sesSettings = app(SesSettings::class);
170+
171+
if (
172+
$this->engagement->channel === NotificationChannel::Email
173+
&& Tenant::current()->config->mail->isDemoModeEnabled
174+
&& $sesSettings->is_demo_auto_reply_mode_enabled
175+
&& $this->engagement->recipient instanceof Model
176+
) {
177+
EngagementResponse::create([
178+
'type' => EngagementResponseType::Email,
179+
'subject' => 'Re: ' . $this->engagement->getSubject(),
180+
'sender_id' => $this->engagement->recipient->getKey(),
181+
'sender_type' => $this->engagement->recipient->getMorphClass(),
182+
'content' => 'Thank you for your message. Will get back to you shortly.',
183+
'sent_at' => now()->addSeconds(2),
184+
'status' => EngagementResponseStatus::New,
185+
]);
186+
}
187+
167188
if (! $this->engagement->engagementBatch) {
168189
return;
169190
}

app-modules/engagement/tests/Tenant/Feature/Notifications/EngagementNotificationTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,14 @@
3535
*/
3636

3737
use AdvisingApp\Engagement\Models\Engagement;
38+
use AdvisingApp\Engagement\Models\EngagementResponse;
3839
use AdvisingApp\Engagement\Notifications\EngagementNotification;
40+
use AdvisingApp\IntegrationAwsSesEventHandling\Settings\SesSettings;
41+
use AdvisingApp\IntegrationTwilio\Settings\TwilioSettings;
3942
use AdvisingApp\Notification\Enums\EmailType;
4043
use AdvisingApp\Notification\Models\EmailMessage;
4144
use AdvisingApp\Prospect\Models\Prospect;
45+
use App\Models\Tenant;
4246

4347
it('getEmailType returns the engagement email_type value', function () {
4448
$engagement = Engagement::factory()
@@ -101,3 +105,50 @@
101105
expect($emailMessage)->not->toBeNull()
102106
->and($emailMessage->email_type)->toBe(EmailType::Transactional);
103107
});
108+
109+
it('creates a proper Engagement Response for emails when demo mode is turned on', function () {
110+
$tenantConfig = Tenant::current()->config;
111+
$tenantConfig->mail->isDemoModeEnabled = true;
112+
Tenant::current()->update([
113+
'config' => $tenantConfig,
114+
]);
115+
116+
$settings = app(SesSettings::class);
117+
$settings->is_demo_auto_reply_mode_enabled = true;
118+
$settings->save();
119+
120+
$prospect = Prospect::factory()->create();
121+
122+
$engagement = Engagement::factory()
123+
->forProspect()
124+
->email()
125+
->create();
126+
127+
$notification = new EngagementNotification($engagement);
128+
129+
$prospect->notify($notification);
130+
131+
expect(EngagementResponse::count())->toBe(1);
132+
expect(EngagementResponse::first()->content)->toBe('Thank you for your message. Will get back to you shortly.');
133+
});
134+
135+
it('creates a proper Engagement Response for SMS when demo mode is turned on', function () {
136+
$settings = app(TwilioSettings::class);
137+
$settings->is_demo_mode_enabled = true;
138+
$settings->is_demo_auto_reply_mode_enabled = true;
139+
$settings->save();
140+
141+
$prospect = Prospect::factory()->create();
142+
143+
$engagement = Engagement::factory()
144+
->forProspect()
145+
->sms()
146+
->create();
147+
148+
$notification = new EngagementNotification($engagement);
149+
150+
$prospect->notify($notification);
151+
152+
expect(EngagementResponse::count())->toBe(1);
153+
expect(EngagementResponse::first()->content)->toBe('Thank you for your message. Will get back to you shortly.');
154+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
/*
4+
<COPYRIGHT>
5+
6+
Copyright © 2016-2026, Canyon GBS Inc. All rights reserved.
7+
8+
Advising App® is licensed under the Elastic License 2.0. For more details,
9+
see https://github.com/canyongbs/advisingapp/blob/main/LICENSE.
10+
11+
Notice:
12+
13+
- You may not provide the software to third parties as a hosted or managed
14+
service, where the service provides users with access to any substantial set of
15+
the features or functionality of the software.
16+
- You may not move, change, disable, or circumvent the license key functionality
17+
in the software, and you may not remove or obscure any functionality in the
18+
software that is protected by the license key.
19+
- You may not alter, remove, or obscure any licensing, copyright, or other notices
20+
of the licensor in the software. Any use of the licensor’s trademarks is subject
21+
to applicable law.
22+
- Canyon GBS Inc. respects the intellectual property rights of others and expects the
23+
same in return. Canyon GBS® and Advising App® are registered trademarks of
24+
Canyon GBS Inc., and we are committed to enforcing and protecting our trademarks
25+
vigorously.
26+
- The software solution, including services, infrastructure, and code, is offered as a
27+
Software as a Service (SaaS) by Canyon GBS Inc.
28+
- Use of this software implies agreement to the license terms and conditions as stated
29+
in the Elastic License 2.0.
30+
31+
For more information or inquiries please visit our website at
32+
https://www.canyongbs.com or contact us via email at legal@canyongbs.com.
33+
34+
</COPYRIGHT>
35+
*/
36+
37+
use App\Features\AddEmailDemoModeAutoReplyFeature;
38+
use Illuminate\Support\Facades\DB;
39+
use Spatie\LaravelSettings\Exceptions\SettingAlreadyExists;
40+
use Spatie\LaravelSettings\Migrations\SettingsBlueprint;
41+
use Spatie\LaravelSettings\Migrations\SettingsMigration;
42+
43+
return new class () extends SettingsMigration {
44+
public function up(): void
45+
{
46+
DB::transaction(function () {
47+
try {
48+
$this->migrator->inGroup('ses', function (SettingsBlueprint $blueprint): void {
49+
$blueprint->add('is_demo_auto_reply_mode_enabled', false);
50+
});
51+
} catch (SettingAlreadyExists) {
52+
}
53+
54+
AddEmailDemoModeAutoReplyFeature::activate();
55+
});
56+
}
57+
58+
public function down(): void
59+
{
60+
DB::transaction(function () {
61+
AddEmailDemoModeAutoReplyFeature::deactivate();
62+
63+
$this->migrator->inGroup('ses', function (SettingsBlueprint $blueprint): void {
64+
$blueprint->delete('is_demo_auto_reply_mode_enabled');
65+
});
66+
});
67+
}
68+
};

app-modules/integration-aws-ses-event-handling/src/Filament/Pages/ManageAmazonSesSettings.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
use AdvisingApp\Engagement\Settings\EngagementSettings;
4040
use AdvisingApp\IntegrationAwsSesEventHandling\Settings\SesSettings;
41+
use App\Features\AddEmailDemoModeAutoReplyFeature;
4142
use App\Filament\Clusters\ProductIntegrations;
4243
use App\Models\Tenant;
4344
use App\Models\User;
@@ -87,6 +88,10 @@ public function form(Schema $schema): Schema
8788
Toggle::make('isDemoModeEnabled')
8889
->label('Demo Mode')
8990
->live(),
91+
Toggle::make('is_demo_auto_reply_mode_enabled')
92+
->visible(AddEmailDemoModeAutoReplyFeature::active())
93+
->label('Demo Autoreply')
94+
->helperText('When enabled, email messages will receive an automatic reply.'),
9095
Checkbox::make('isExcludingSystemNotificationsFromDemoMode')
9196
->label('Exclude authentication related messages')
9297
->visible(fn (Get $get): bool => (bool) $get('isDemoModeEnabled')),

app-modules/integration-aws-ses-event-handling/src/Settings/SesSettings.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class SesSettings extends Settings
4242
{
4343
public ?string $configuration_set = null;
4444

45+
public bool $is_demo_auto_reply_mode_enabled = false;
46+
4547
public static function group(): string
4648
{
4749
return 'ses';
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/*
4+
<COPYRIGHT>
5+
6+
Copyright © 2016-2026, Canyon GBS Inc. All rights reserved.
7+
8+
Advising App® is licensed under the Elastic License 2.0. For more details,
9+
see https://github.com/canyongbs/advisingapp/blob/main/LICENSE.
10+
11+
Notice:
12+
13+
- You may not provide the software to third parties as a hosted or managed
14+
service, where the service provides users with access to any substantial set of
15+
the features or functionality of the software.
16+
- You may not move, change, disable, or circumvent the license key functionality
17+
in the software, and you may not remove or obscure any functionality in the
18+
software that is protected by the license key.
19+
- You may not alter, remove, or obscure any licensing, copyright, or other notices
20+
of the licensor in the software. Any use of the licensor’s trademarks is subject
21+
to applicable law.
22+
- Canyon GBS Inc. respects the intellectual property rights of others and expects the
23+
same in return. Canyon GBS® and Advising App® are registered trademarks of
24+
Canyon GBS Inc., and we are committed to enforcing and protecting our trademarks
25+
vigorously.
26+
- The software solution, including services, infrastructure, and code, is offered as a
27+
Software as a Service (SaaS) by Canyon GBS Inc.
28+
- Use of this software implies agreement to the license terms and conditions as stated
29+
in the Elastic License 2.0.
30+
31+
For more information or inquiries please visit our website at
32+
https://www.canyongbs.com or contact us via email at legal@canyongbs.com.
33+
34+
</COPYRIGHT>
35+
*/
36+
37+
namespace App\Features;
38+
39+
use App\Support\AbstractFeatureFlag;
40+
41+
class AddEmailDemoModeAutoReplyFeature extends AbstractFeatureFlag
42+
{
43+
public function resolve(mixed $scope): mixed
44+
{
45+
return false;
46+
}
47+
}

0 commit comments

Comments
 (0)