Use bounce activity type, if exists
authorEileen McNaughton <emcnaughton@wikimedia.org>
Mon, 11 Sep 2023 20:33:33 +0000 (08:33 +1200)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Mon, 11 Sep 2023 21:43:57 +0000 (09:43 +1200)
We can look at adding in upgrade script in later version after bedding in

CRM/Utils/Mail/EmailProcessor.php
CRM/Utils/Mail/IncomingMail.php
tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php

index 8904a440b0d7f45e7e927ab468ff81a65af2ae87..c1e511df8740bdb8952fa1a547d81c241383a2c8 100644 (file)
@@ -16,6 +16,8 @@
  */
 
 // we should consider moving this to the settings table
+use Civi\Api4\Activity;
+
 define('MAIL_BATCH_SIZE', 50);
 
 /**
@@ -84,6 +86,16 @@ class CRM_Utils_Mail_EmailProcessor {
     // create an array of all of to, from, cc, bcc that are in use for this Mail Account, so we don't create contacts for emails we aren't adding to the activity.
     $emailFields = array_merge($targetFields, $assigneeFields, $sourceFields);
     $createContact = !($dao->is_contact_creation_disabled_if_no_match);
+    $bounceActivityTypeID = $activityTypeID = (int) $dao->activity_type_id;
+    $activityTypes = Activity::getFields(TRUE)
+      ->setLoadOptions(['id', 'name'])
+      ->addWhere('name', '=', 'activity_type_id')
+      ->execute()->first()['options'];
+    foreach ($activityTypes as $activityType) {
+      if ($activityType['name'] === 'Bounce') {
+        $bounceActivityTypeID = (int) $activityType['id'];
+      }
+    }
 
     // retrieve the emails
     try {
@@ -118,9 +130,12 @@ class CRM_Utils_Mail_EmailProcessor {
 
           // if its the activities that needs to be processed ..
           try {
+            if ($incomingMail->isBounce()) {
+              $activityTypeID = $bounceActivityTypeID;
+            }
             $mailParams = CRM_Utils_Mail_Incoming::parseMailingObject($mail, $incomingMail->getAttachments(), $createContact, $emailFields, [$incomingMail->getFrom()]);
             $activityParams = [
-              'activity_type_id' => (int) $dao->activity_type_id,
+              'activity_type_id' => $activityTypeID,
               'campaign_id' => $dao->campaign_id ? (int) $dao->campaign_id : NULL,
               'status_id' => $dao->activity_status,
               'subject' => $incomingMail->getSubject(),
index c11273a5fa0a6ce4b8f22edfef45caf2c8436c3f..04eeb841b9e13bd5825e1291520e26ed1f509cad 100644 (file)
@@ -124,6 +124,17 @@ class CRM_Utils_Mail_IncomingMail {
     return (bool) $this->action;
   }
 
+  /**
+   * Is this a bounce email.
+   *
+   * At the moment we are only able to detect verp bounces but maybe in the future...
+   *
+   * @return bool
+   */
+  public function isBounce() : bool {
+    return $this->getAction() === 'b';
+  }
+
   /**
    * @param \ezcMail $mail
    * @param string $emailDomain
index e89393999853c6a4b93d0109579b946c002d7e03..1d1d0e5b607681745bcfc08b56d452a3efd25591 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Civi\Api4\OptionValue;
+
 /**
  * Class CRM_Utils_Mail_EmailProcessorTest
  * @group headless
@@ -40,6 +42,7 @@ class CRM_Utils_Mail_EmailProcessorTest extends CiviUnitTestCase {
         'activity_assignees' => 'from',
       ],
     ]);
+    $this->createTestEntity('OptionValue', ['option_group_id:name' => 'activity_type', 'name' => 'Bounce', 'label' => "Bounce"]);
   }
 
   /**
@@ -48,6 +51,7 @@ class CRM_Utils_Mail_EmailProcessorTest extends CiviUnitTestCase {
   public function tearDown(): void {
     CRM_Utils_File::cleanDir(__DIR__ . '/data/mail');
     parent::tearDown();
+    OptionValue::delete(FALSE)->addWhere('name', '=', 'Bounce')->execute();
     $this->quickCleanup([
       'civicrm_group',
       'civicrm_group_contact',
@@ -116,7 +120,7 @@ class CRM_Utils_Mail_EmailProcessorTest extends CiviUnitTestCase {
     $this->callAPISuccess('job', 'fetch_bounces', ['is_create_activities' => TRUE]);
     $this->assertFileDoesNotExist(__DIR__ . '/data/mail/' . $mail);
     $this->checkMailingBounces(1);
-    $this->callAPISuccessGetSingle('Activity', ['source_contact_id' => $this->contactID, 'activity_type_id' => 'Inbound Email']);
+    $this->callAPISuccessGetSingle('Activity', ['source_contact_id' => $this->contactID, 'activity_type_id' => 'Bounce']);
   }
 
   /**