'Bounce test', 'type' => 'general_newsletter', 'subject' => ['en' => 'Bounce test'], 'status' => 'sent', ]); } public function test_a_second_report_for_the_same_mailing_updates_the_first(): void { $mailing = $this->mailing(); MailingBounce::recordBounce('Bounce.Test@Example.test', 'soft', 'mailbox full', $mailing->id); $bounce = MailingBounce::recordBounce('bounce.test@example.test ', 'hard', 'user unknown', $mailing->id); $rows = MailingBounce::where('email', 'bounce.test@example.test')->get(); $this->assertCount(1, $rows); $this->assertSame($bounce->id, $rows->first()->id); $this->assertSame('hard', $rows->first()->bounce_type); $this->assertSame('user unknown', $rows->first()->bounce_reason); } public function test_bounces_without_a_mailing_still_add_up(): void { MailingBounce::recordBounce('bounce.test@example.test', 'hard', 'user unknown'); MailingBounce::recordBounce('bounce.test@example.test', 'hard', 'user unknown'); $this->assertSame(2, MailingBounce::where('email', 'bounce.test@example.test')->count()); } public function test_other_mailings_get_their_own_row(): void { $first = $this->mailing(); $second = $this->mailing(); MailingBounce::recordBounce('bounce.test@example.test', 'hard', 'user unknown', $first->id); MailingBounce::recordBounce('bounce.test@example.test', 'hard', 'user unknown', $second->id); $this->assertSame(2, MailingBounce::where('email', 'bounce.test@example.test')->count()); } private function thresholds(int $windowDays = 30): void { $key = config('app.timebank_config') . '.mailing.bounce_thresholds'; config([ "{$key}.suppression_threshold" => 1, "{$key}.verification_reset_threshold" => 1, "{$key}.counting_window_days" => $windowDays, ]); } public function test_a_block_against_our_server_does_not_suppress_the_address(): void { $this->thresholds(); $user = User::factory()->create(['email' => 'bounce.test@example.test', 'email_verified_at' => now()]); MailingBounce::recordBounce('bounce.test@example.test', 'hard', "smtp; 550 5.7.1 Unfortunately, messages from [195.190.28.89] weren't sent. Please contact your Internet service provider since part of their network is on our block list (S3150)."); $this->assertFalse(MailingBounce::isSuppressed('bounce.test@example.test')); $this->assertNotNull($user->fresh()->email_verified_at); } public function test_an_unknown_user_still_suppresses_the_address(): void { $this->thresholds(); $user = User::factory()->create(['email' => 'bounce.test@example.test', 'email_verified_at' => now()]); MailingBounce::recordBounce('bounce.test@example.test', 'hard', 'smtp; 550 5.1.1 user unknown'); $this->assertTrue(MailingBounce::isSuppressed('bounce.test@example.test')); $this->assertNull($user->fresh()->email_verified_at); } public function test_a_missing_address_counts_even_with_a_5_7_code(): void { $this->thresholds(); MailingBounce::recordBounce('bounce.test@example.test', 'hard', 'smtp; 550 5.7.1 : Recipient address rejected: Recipient not found'); $this->assertTrue(MailingBounce::isSuppressed('bounce.test@example.test')); } public function test_a_bounce_is_dated_when_it_happened_and_old_ones_do_not_count(): void { $this->thresholds(30); $when = now()->subDays(70)->startOfSecond(); $bounce = MailingBounce::recordBounce('bounce.test@example.test', 'hard', 'smtp; 550 5.1.1 user unknown', null, $when); $this->assertTrue($bounce->fresh()->bounced_at->equalTo($when)); $this->assertFalse(MailingBounce::isSuppressed('bounce.test@example.test')); } }