Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CATL-1614: Do not create contacts when filing email #44

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions CRM/Admin/Form/MailSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
}

/**
Expand Down Expand Up @@ -146,13 +148,15 @@ public function postProcess() {
'is_ssl',
'is_default',
'activity_status',
'is_contact_creation_disabled_if_no_match',
];

$params = [];
foreach ($fields as $f) {
if (in_array($f, [
'is_default',
'is_ssl',
'is_contact_creation_disabled_if_no_match',
])) {
$params[$f] = CRM_Utils_Array::value($f, $formValues, FALSE);
}
Expand Down
4 changes: 4 additions & 0 deletions CRM/Upgrade/Incremental/sql/5.30.0.mysql.tpl
Original file line number Diff line number Diff line change
@@ -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';
27 changes: 16 additions & 11 deletions CRM/Utils/Mail/EmailProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 . '<p>';
$message .= ts('Error message: ');
$message .= '<pre>' . $e->getMessage() . '</pre><p>';
Expand Down Expand Up @@ -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();
Expand All @@ -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";
}
}
}

Expand Down
20 changes: 12 additions & 8 deletions CRM/Utils/Mail/Incoming.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
}
Expand Down
77 changes: 43 additions & 34 deletions templates/CRM/Admin/Form/MailSettings.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,62 +9,71 @@
*}
{* this template is used for adding/editing email settings. *}
<div class="crm-block crm-form-block crm-mail-settings-form-block">
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
{if $action eq 8}
<div class="messages status no-popup">
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
{if $action eq 8}
<div class="messages status no-popup">
{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}
</div>
{ts}WARNING: Deleting this option will result in the loss of mail settings data.{/ts} {ts}Do you want to continue?{/ts}
</div>
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
{else}
{else}
<table class="form-layout-compressed">

<tr class="crm-mail-settings-form-block-name"><td class="label">{$form.name.label}</td><td>{$form.name.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Name of this group of settings.{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-name"><td class="label">{$form.name.label}</td><td>{$form.name.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Name of this group of settings.{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-server"><td class="label">{$form.server.label}</td><td>{$form.server.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Name or IP address of mail server machine.{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-server"><td class="label">{$form.server.label}</td><td>{$form.server.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Name or IP address of mail server machine.{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-username"><td class="label">{$form.username.label}</td><td>{$form.username.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Username to use when polling (for IMAP and POP3).{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-username"><td class="label">{$form.username.label}</td><td>{$form.username.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Username to use when polling (for IMAP and POP3).{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-password"><td class="label">{$form.password.label}</td><td>{$form.password.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Password to use when polling (for IMAP and POP3).{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-password"><td class="label">{$form.password.label}</td><td>{$form.password.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Password to use when polling (for IMAP and POP3).{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-localpart"><td class="label">{$form.localpart.label}</td><td>{$form.localpart.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Optional local part (e.g., 'civimail+' for addresses like [email protected]).{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-localpart"><td class="label">{$form.localpart.label}</td><td>{$form.localpart.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Optional local part (e.g., 'civimail+' for addresses like [email protected]).{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-domain"><td class="label">{$form.domain.label}</td><td>{$form.domain.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Email address domain (the part after @).{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-domain"><td class="label">{$form.domain.label}</td><td>{$form.domain.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Email address domain (the part after @).{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-return_path"><td class="label">{$form.return_path.label}</td><td>{$form.return_path.html}</td><tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Contents of the Return-Path header.{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-return_path"><td class="label">{$form.return_path.label}</td><td>{$form.return_path.html}</td><tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Contents of the Return-Path header.{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-protocol"><td class="label">{$form.protocol.label}</td><td>{$form.protocol.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Name of the protocol to use for polling.{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-protocol"><td class="label">{$form.protocol.label}</td><td>{$form.protocol.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Name of the protocol to use for polling.{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-source"><td class="label">{$form.source.label}</td><td>{$form.source.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Folder to poll from when using IMAP (will default to INBOX when empty), path to poll from when using Maildir, etc..{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-source"><td class="label">{$form.source.label}</td><td>{$form.source.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Folder to poll from when using IMAP (will default to INBOX when empty), path to poll from when using Maildir, etc..{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-is_ssl"><td class="label">{$form.is_ssl.label}</td><td>{$form.is_ssl.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Whether to use SSL for IMAP and POP3 or not.{/ts}</td></tr>
<tr class="crm-mail-settings-form-block-is_ssl"><td class="label">{$form.is_ssl.label}</td><td>{$form.is_ssl.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{ts}Whether to use SSL for IMAP and POP3 or not.{/ts}</td></tr>

<tr class="crm-mail-settings-form-block-is_default"><td class="label">{$form.is_default.label}</td><td>{$form.is_default.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{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}</td></tr>
<tr class="crm-mail-settings-form-block-is_default"><td class="label">{$form.is_default.label}</td><td>{$form.is_default.html}</td></tr>
<tr><td class="label">&nbsp;</td><td class="description">{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}</td></tr>

<tr class="crm-mail-settings-form-block-activity_status"><td class="label">{$form.activity_status.label}</td><td>{$form.activity_status.html}</td></tr>
<tr class="crm-mail-settings-form-block-is_contact_creation_disabled_if_no_match"><td class="label">&nbsp;</td><td>{$form.is_contact_creation_disabled_if_no_match.html}{$form.is_contact_creation_disabled_if_no_match.label}</td></tr>

<tr class="crm-mail-settings-form-block-activity_status"><td class="label">&nbsp;</td><td>{$form.activity_status.label}<div>{$form.activity_status.html}</div></td></tr>
</table>
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
{/if}

<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
{/if}
</div>

{literal}
<script type="text/javascript">
CRM.$(function($) {
var $form = $('form.{/literal}{$form.formClass}{literal}');
function showActivityStatus() {
$('.crm-mail-settings-form-block-activity_status', $form).toggle($(this).val() === '0');
function showActivityFields() {
var fields = [
'.crm-mail-settings-form-block-activity_status',
'.crm-mail-settings-form-block-is_contact_creation_disabled_if_no_match',
];

$(fields.join(', '), $form).toggle($(this).val() === '0');
}
$('select[name=is_default]').each(showActivityStatus).change(showActivityStatus);
$('select[name="is_default"]').each(showActivityFields).change(showActivityFields);
});
</script>
{/literal}
33 changes: 33 additions & 0 deletions tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' => "[email protected]",
]);
$this->assertTrue(empty($result['values']));
}

}
11 changes: 11 additions & 0 deletions xml/schema/Core/MailSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,15 @@
<type>Select</type>
</html>
</field>
<field>
<name>is_contact_creation_disabled_if_no_match</name>
<type>boolean</type>
<title>Do not create new contacts when filing emails</title>
<default>0</default>
<html>
<type>CheckBox</type>
</html>
<description>If this option is enabled, CiviCRM will not create new contacts when filing emails.</description>
<add>5.30</add>
</field>
</table>