Details
Description
A mailing is sent out to a parent group with the
{action.unsubscribeUrl}token included.
Clicking the unsubscribe link leads to the expected page e.g. /civicrm/mailing/unsubscribe?reset=1&jid=1898&qid=239080&h=f2574b32a30be04f but the unsubscribe success notice is immediately displayed:
"Email: user@example.com has been successfully unsubscribed from this Mailing List/Group."
However, no records in the database are changed and the contact remains added to the parent and child groups.
Tracing through the code, the unsubscribe process fails for a parent group in a query in function unsub_from_mailing in file /civicrm/CRM/Mailing/Event/BAO/Unsubscribe.php, line 237 for 4.6.x (line 235 for 4.7.15)
{{ SELECT $group.id as group_id,
$group.title as title,
$group.description as description
FROM $group
LEFT JOIN $gc
ON $gc.group_id = $group.id
WHERE $group.is_hidden = 0
$groupIdClause
AND ($group.saved_search_id is not null
OR ($gc.contact_id = $contact_id
AND $gc.status = 'Added')
$baseGroupClause
)}}
The query's comment states:
Now we have a complete list of recipient groups. Filter out all those except smart groups, those that the contact belongs to and base groups from search based mailings.
However, a parent group is filtered out by the above query as it has no saved_search_id in the civicrm_group table or have a record of contacts stored in the civicrm_group_contact table.
An empty $groups array is therefore returned to the unsub_from_mailing call in /civicrm/CRM/Mailing/Form/Unsubscribe.php, line 65. This then triggers the following "if (!$groupExist)" which displays the "successfully unsubscribed" message quoted above.
To have a parent group returned by the query above including the following clause would appear to work:
OR $group.children is not null
Testing this results in the unsubscribe verification form being displayed for the parent group. Removal from the parent group then takes place as expected.
Is this the expected functionality? i.e. unsubscribing from a mailing sent to a parent group removes the contact from the parent group but not any of the child groups.
If so, does the addition of this clause seem the right way to fix this?
This probably affects version 4.7.x as well as the unsubscribe code all looks the same. I've currently only got an installation of 4.6 though to test on.