diff --git a/CRM/Admin/Form/MailSettings.php b/CRM/Admin/Form/MailSettings.php index 4de49fe41356..3ec4e11d0a52 100644 --- a/CRM/Admin/Form/MailSettings.php +++ b/CRM/Admin/Form/MailSettings.php @@ -70,6 +70,8 @@ public function buildQuickForm() { ]; $this->add('select', 'is_default', ts('Used For?'), $usedfor); $this->addField('activity_status', ['placeholder' => FALSE]); + + $this->add('checkbox', 'is_contact_creation_disabled_if_no_match', ts('Do not create new contacts when filing emails')); } /** @@ -146,6 +148,7 @@ public function postProcess() { 'is_ssl', 'is_default', 'activity_status', + 'is_contact_creation_disabled_if_no_match', ]; $params = []; @@ -153,6 +156,7 @@ public function postProcess() { if (in_array($f, [ 'is_default', 'is_ssl', + 'is_contact_creation_disabled_if_no_match', ])) { $params[$f] = CRM_Utils_Array::value($f, $formValues, FALSE); } diff --git a/CRM/Upgrade/Incremental/sql/5.30.0.mysql.tpl b/CRM/Upgrade/Incremental/sql/5.30.0.mysql.tpl new file mode 100644 index 000000000000..1f4bdf572111 --- /dev/null +++ b/CRM/Upgrade/Incremental/sql/5.30.0.mysql.tpl @@ -0,0 +1,4 @@ +{* file to handle db changes in 5.30.0 during upgrade *} + +ALTER TABLE civicrm_mail_settings +ADD is_contact_creation_disabled_if_no_match TINYINT default 0 not null comment 'If this option is enabled, CiviCRM will not create new contacts when filing emails'; diff --git a/CRM/Utils/Mail/EmailProcessor.php b/CRM/Utils/Mail/EmailProcessor.php index 9d68310b9dfe..8721c943fdce 100644 --- a/CRM/Utils/Mail/EmailProcessor.php +++ b/CRM/Utils/Mail/EmailProcessor.php @@ -157,7 +157,7 @@ public static function _process($civiMail, $dao, $is_create_activities) { try { $store = CRM_Mailing_MailStore::getStore($dao->name); } - catch (Exception$e) { + catch (Exception $e) { $message = ts('Could not connect to MailStore for ') . $dao->username . '@' . $dao->server . '

'; $message .= ts('Error message: '); $message .= '

' . $e->getMessage() . '

'; @@ -226,7 +226,8 @@ public static function _process($civiMail, $dao, $is_create_activities) { if ($usedfor == 0 || $is_create_activities) { // if its the activities that needs to be processed .. try { - $mailParams = CRM_Utils_Mail_Incoming::parseMailingObject($mail); + $createContact = !($dao->is_contact_creation_disabled_if_no_match ?? FALSE); + $mailParams = CRM_Utils_Mail_Incoming::parseMailingObject($mail, $createContact, FALSE); } catch (Exception $e) { echo $e->getMessage(); @@ -241,16 +242,20 @@ public static function _process($civiMail, $dao, $is_create_activities) { if (!empty($dao->activity_status)) { $params['status_id'] = $dao->activity_status; } - $result = civicrm_api('activity', 'create', $params); - if ($result['is_error']) { - $matches = FALSE; - echo "Failed Processing: {$mail->subject}. Reason: {$result['error_message']}\n"; - } - else { - $matches = TRUE; - CRM_Utils_Hook::emailProcessor('activity', $params, $mail, $result); - echo "Processed as Activity: {$mail->subject}\n"; + // Create activity if its not empty. + if (!empty($params['subject']) || !empty($params['target_contact_id'])) { + $result = civicrm_api('activity', 'create', $params); + + if ($result['is_error']) { + $matches = FALSE; + echo "Failed Processing: {$mail->subject}. Reason: {$result['error_message']}\n"; + } + else { + $matches = TRUE; + CRM_Utils_Hook::emailProcessor('activity', $params, $mail, $result); + echo "Processed as Activity: {$mail->subject}\n"; + } } } diff --git a/CRM/Utils/Mail/Incoming.php b/CRM/Utils/Mail/Incoming.php index 1e2da042236b..a11961081250 100644 --- a/CRM/Utils/Mail/Incoming.php +++ b/CRM/Utils/Mail/Incoming.php @@ -322,10 +322,12 @@ public function &parse(&$file) { /** * @param $mail + * @param $createContact + * @param $requireContact * * @return array */ - public static function parseMailingObject(&$mail) { + public static function parseMailingObject(&$mail, $createContact = TRUE, $requireContact = TRUE) { $config = CRM_Core_Config::singleton(); @@ -342,18 +344,18 @@ public static function parseMailingObject(&$mail) { } $params['from'] = []; - self::parseAddress($mail->from, $field, $params['from'], $mail); + self::parseAddress($mail->from, $field, $params['from'], $mail, $createContact); // we definitely need a contact id for the from address // if we dont have one, skip this email - if (empty($params['from']['id'])) { + if ($requireContact && empty($params['from']['id'])) { return NULL; } $emailFields = ['to', 'cc', 'bcc']; foreach ($emailFields as $field) { $value = $mail->$field; - self::parseAddresses($value, $field, $params, $mail); + self::parseAddresses($value, $field, $params, $mail, $createContact); } // define other parameters @@ -396,8 +398,9 @@ public static function parseMailingObject(&$mail) { * @param array $params * @param $subParam * @param $mail + * @param $createContact */ - public static function parseAddress(&$address, &$params, &$subParam, &$mail) { + public static function parseAddress(&$address, &$params, &$subParam, &$mail, $createContact = TRUE) { // CRM-9484 if (empty($address->email)) { return; @@ -408,7 +411,7 @@ public static function parseAddress(&$address, &$params, &$subParam, &$mail) { $contactID = self::getContactID($subParam['email'], $subParam['name'], - TRUE, + $createContact, $mail ); $subParam['id'] = $contactID ? $contactID : NULL; @@ -419,13 +422,14 @@ public static function parseAddress(&$address, &$params, &$subParam, &$mail) { * @param $token * @param array $params * @param $mail + * @param $createContact */ - public static function parseAddresses(&$addresses, $token, &$params, &$mail) { + public static function parseAddresses(&$addresses, $token, &$params, &$mail, $createContact = TRUE) { $params[$token] = []; foreach ($addresses as $address) { $subParam = []; - self::parseAddress($address, $params, $subParam, $mail); + self::parseAddress($address, $params, $subParam, $mail, $createContact); $params[$token][] = $subParam; } } diff --git a/templates/CRM/Admin/Form/MailSettings.tpl b/templates/CRM/Admin/Form/MailSettings.tpl index 361ffe09e187..9185c54a18a9 100644 --- a/templates/CRM/Admin/Form/MailSettings.tpl +++ b/templates/CRM/Admin/Form/MailSettings.tpl @@ -9,62 +9,71 @@ *} {* this template is used for adding/editing email settings. *}

-
{include file="CRM/common/formButtons.tpl" location="top"}
-{if $action eq 8} -
+
{include file="CRM/common/formButtons.tpl" location="top"}
+ {if $action eq 8} +
{icon icon="fa-info-circle"}{/icon} - {ts}WARNING: Deleting this option will result in the loss of mail settings data.{/ts} {ts}Do you want to continue?{/ts} -
+ {ts}WARNING: Deleting this option will result in the loss of mail settings data.{/ts} {ts}Do you want to continue?{/ts} +
{include file="CRM/common/formButtons.tpl" location="top"}
-{else} + {else} - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + + +
{$form.name.label}{$form.name.html}
 {ts}Name of this group of settings.{/ts}
{$form.name.label}{$form.name.html}
 {ts}Name of this group of settings.{/ts}
{$form.server.label}{$form.server.html}
 {ts}Name or IP address of mail server machine.{/ts}
{$form.server.label}{$form.server.html}
 {ts}Name or IP address of mail server machine.{/ts}
{$form.username.label}{$form.username.html}
 {ts}Username to use when polling (for IMAP and POP3).{/ts}
{$form.username.label}{$form.username.html}
 {ts}Username to use when polling (for IMAP and POP3).{/ts}
{$form.password.label}{$form.password.html}
 {ts}Password to use when polling (for IMAP and POP3).{/ts}
{$form.password.label}{$form.password.html}
 {ts}Password to use when polling (for IMAP and POP3).{/ts}
{$form.localpart.label}{$form.localpart.html}
 {ts}Optional local part (e.g., 'civimail+' for addresses like civimail+s.1.2@example.com).{/ts}
{$form.localpart.label}{$form.localpart.html}
 {ts}Optional local part (e.g., 'civimail+' for addresses like civimail+s.1.2@example.com).{/ts}
{$form.domain.label}{$form.domain.html}
 {ts}Email address domain (the part after @).{/ts}
{$form.domain.label}{$form.domain.html}
 {ts}Email address domain (the part after @).{/ts}
{$form.return_path.label}{$form.return_path.html}
 {ts}Contents of the Return-Path header.{/ts}
{$form.return_path.label}{$form.return_path.html}
 {ts}Contents of the Return-Path header.{/ts}
{$form.protocol.label}{$form.protocol.html}
 {ts}Name of the protocol to use for polling.{/ts}
{$form.protocol.label}{$form.protocol.html}
 {ts}Name of the protocol to use for polling.{/ts}
{$form.source.label}{$form.source.html}
 {ts}Folder to poll from when using IMAP (will default to INBOX when empty), path to poll from when using Maildir, etc..{/ts}
{$form.source.label}{$form.source.html}
 {ts}Folder to poll from when using IMAP (will default to INBOX when empty), path to poll from when using Maildir, etc..{/ts}
{$form.is_ssl.label}{$form.is_ssl.html}
 {ts}Whether to use SSL for IMAP and POP3 or not.{/ts}
{$form.is_ssl.label}{$form.is_ssl.html}
 {ts}Whether to use SSL for IMAP and POP3 or not.{/ts}
{$form.is_default.label}{$form.is_default.html}
 {ts}How this mail account will be used. Only one box may be used for bounce processing. It will also be used as the envelope email when sending mass mailings.{/ts}
{$form.is_default.label}{$form.is_default.html}
 {ts}How this mail account will be used. Only one box may be used for bounce processing. It will also be used as the envelope email when sending mass mailings.{/ts}
{$form.activity_status.label}{$form.activity_status.html}
 {$form.is_contact_creation_disabled_if_no_match.html}{$form.is_contact_creation_disabled_if_no_match.label}
 {$form.activity_status.label}
{$form.activity_status.html}
-
{include file="CRM/common/formButtons.tpl" location="bottom"}
-{/if} + +
{include file="CRM/common/formButtons.tpl" location="bottom"}
+ {/if}
+ {literal} {/literal} diff --git a/tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php b/tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php index 89354b9783ce..3e10c72f2cd5 100644 --- a/tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php +++ b/tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php @@ -169,4 +169,37 @@ public function setUpMailing() { $this->eventQueue = $this->callAPISuccess('MailingEventQueue', 'get', ['api.MailingEventQueue.create' => ['hash' => 'aaaaaaaaaaaaaaaa']]); } + /** + * Set up mail account with 'Do not create new contacts when filing emails' + * option enabled. + */ + public function setUpDoNotCreateContact() { + $this->callAPISuccess('MailSettings', 'get', [ + 'api.MailSettings.create' => [ + 'name' => 'mailbox', + 'protocol' => 'Localdir', + 'source' => __DIR__ . '/data/mail', + 'domain' => 'example.com', + 'is_default' => '0', + 'is_contact_creation_disabled_if_no_match' => TRUE, + ], + ]); + } + + /** + * Test case email processing when is_non_case_email_skipped is enabled. + */ + public function testInboundProcessingDoNotCreateContact() { + $this->setUpDoNotCreateContact(); + $mail = 'test_non_cases_email.eml'; + + copy(__DIR__ . '/data/inbound/' . $mail, __DIR__ . '/data/mail/' . $mail); + $this->callAPISuccess('job', 'fetch_activities', []); + $result = civicrm_api3('Contact', 'get', [ + 'sequential' => 1, + 'email' => "from@test.test", + ]); + $this->assertTrue(empty($result['values'])); + } + } diff --git a/xml/schema/Core/MailSettings.xml b/xml/schema/Core/MailSettings.xml index 0dea26c13b2a..bad887e5c779 100644 --- a/xml/schema/Core/MailSettings.xml +++ b/xml/schema/Core/MailSettings.xml @@ -150,4 +150,15 @@ Select + + is_contact_creation_disabled_if_no_match + boolean + Do not create new contacts when filing emails + 0 + + CheckBox + + If this option is enabled, CiviCRM will not create new contacts when filing emails. + 5.30 +