Aggiunge IMAP bounce e flag email non valide nel CRM.
CI / scan_ruby (push) Failing after 13m27s
CI / scan_js (push) Successful in 11m45s
CI / lint (push) Failing after 12m4s

Permette di leggere i bounce dalla stessa MailIdentity SMTP, aggiornare le email in anagrafica e saltare gli indirizzi invalidi nei mailing.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-08 19:46:04 +02:00
co-authored by Cursor
parent 353ace4d99
commit 36b3ffe507
26 changed files with 922 additions and 12 deletions
+20
View File
@@ -110,6 +110,26 @@ class Api::V1::ApiTest < ActionDispatch::IntegrationTest
assert_equal "demo_trial", @opportunity.pipeline_stage
end
test "updates organization email after bounce" do
patch "/api/v1/p/matchlivetv/organizations/#{@org.id}/email",
params: {
organization_id: @org.id,
bounced_email: "vecchia@example.com",
email: "nuova@example.com",
email_invalid: false,
bounce_reason: "User unknown",
activity_subject: "Email aggiornata dopo bounce"
},
headers: bearer(@admin_token.plaintext),
as: :json
assert_response :success
@org.reload
assert_equal "nuova@example.com", @org.email
assert_equal "vecchia@example.com", @org.bounced_email
assert_not @org.email_invalid?
assert json_body["activity"].present?
end
test "rejects lost stage without reason" do
patch "/api/v1/p/matchlivetv/opportunities/#{@opportunity.id}/stage",
params: { pipeline_stage: "lost" },
+1
View File
@@ -27,6 +27,7 @@ class McpControllerTest < ActionDispatch::IntegrationTest
assert_includes listed, "list_projects"
assert_includes listed, "today"
assert_includes listed, "create_activity"
assert_includes listed, "check_mail_bounces"
assert names || listed.any?
end
+25
View File
@@ -51,4 +51,29 @@ class MailIdentityTest < ActiveSupport::TestCase
assert_not identity.valid?
assert_includes identity.errors[:smtp_port], "con SSL/TLS va usata la porta 465 (es. smtps.aruba.it)"
end
test "infers aruba imap host from smtp" do
identity = MailIdentity.new(
name: "Aruba",
from_name: "Info",
from_email: "info@example.com",
smtp_host: "smtps.aruba.it",
smtp_port: 465,
encryption: "tls",
smtp_authentication: "plain",
smtp_username: "info@example.com",
smtp_password: "secret",
active: true
)
assert identity.valid?
assert_equal "imaps.aruba.it", identity.effective_imap_host
assert_equal 993, identity.effective_imap_port
assert identity.imap_ready?
settings = identity.imap_settings
assert_equal "imaps.aruba.it", settings[:address]
assert_equal 993, settings[:port]
assert settings[:ssl]
assert_equal "info@example.com", settings[:user_name]
assert_equal "secret", settings[:password]
end
end
@@ -0,0 +1,40 @@
require "test_helper"
class Mailings::ImapBounceReaderTest < ActiveSupport::TestCase
test "parses aruba-style delivery failure from raw rfc822" do
identity = create_mail_identity(
from_email: "info@matchlivetv.it",
smtp_username: "info@matchlivetv.it",
smtp_host: "smtps.aruba.it",
smtp_port: 465,
encryption: "tls"
)
raw = <<~EML
From: mail-daemon@example.com
To: info@matchlivetv.it
Subject: Recapito fallito
Date: Mon, 07 Sep 2026 08:14:05 +0200
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Delivery to the following recipients failed permanently:
* broken@club.it
Reason: 550 5.1.1 User unknown
Final-Recipient: rfc822; broken@club.it
Diagnostic-Code: smtp; 550 5.1.1 User unknown
Subject: Più visibilità per ASD Test Club
EML
reader = Mailings::ImapBounceReader.new(identity)
parsed = reader.send(:parse_message, raw, uid: 42)
assert_not_nil parsed
assert_includes parsed[:failed_emails], "broken@club.it"
assert_equal "ASD Test Club", parsed[:club_hint]
assert_match(/550|User unknown/i, parsed[:reason].to_s)
end
end