I believe I am still running into problems with the email on/off checkbox settings in commons3.3, despite the various fixed bug reports on the same topic.
Specifically, I believe the issue raised by the OP by @jide in #1828184: Message Subscribe sends emails regardless of context and elaborated on in https://drupal.org/comment/6681468#comment-6681468 has not been addressed.

Emails are sent out when a user has any email_* related flag set, regardless of whether the flag matches the particular context/node in question.

The fixes and tests done to this point in the previous issues look like they are fixed because the tested only having one email_* flag set at at time, in which case a user is able to successfully toggle the flag on/off as expected.
But once more than one email_* flag is in play, and one of them is set to ON, none of the flags set to OFF are respected. So if a user has one email_* flag set to ON, they will get emails for everything they follow, regardless of the individual email_* flag settings.

To reproduce:
- user1 and user2 have "Send email notifications by default." checked
- user1 create GroupA.
- user2 follow GroupA.
- user2 create a post PostB on GroupA
- user2 goes to their notification-settings page and sets GroupA to "do not send email"

So at this point:
- user1 will now follow and receive emails for all groupA content
- user2 should only receive emails for comments on PostB

Now:
- user1 create PostC on GroupA

Result:
- both user1 and user2 will receive emails.

In the code

<?php
 function message_subscribe_get_subscribers(){
//... 
//at this point Array ( [8] => Array ( [notifiers] => Array ( ) [flags] => Array ( [0] => commons_follow_node ) ) 
//notifiers is an empty array as expected

 _message_subscribe_add_default_notifiers($uids);

//at this point Array ( [8] => Array ( [notifiers] => Array ( ) [flags] => Array ( [0] => commons_follow_node ) ) 
//notifiers is an empty array as expected, so the problem is not the default_notifiers

drupal_alter('message_subscribe_get_subscribers', $uids, $values);

//now we have Array ( [8] => Array ( [notifiers] => Array ( [email] => email ) [flags] => Array ( [0] => commons_follow_node ) ) 
//so the Email notifier has been added by drupal_alter
//...
}

?>

So then looking at drupal_alter, as pointed out by @jide in the original issue

<?php
 function message_subscribe_email_message_subscribe_get_subscribers_alter(&$uids, $values) {
//...
// at no point does this function check to make sure it is matching against the relevant flag for this particular node/context
//any match for user with an email_* flag will cause emails to be sent
$result = $query->fields('f', array('uid'))
  ->condition('fid', $flag_ids, 'IN')
  ->condition('uid', array_keys($uids), 'IN')
  ->groupBy('uid')
  ->execute()
  ->fetchAll();

foreach ($result as $row) {
  // Add 'email' to the list of notifiers.
  $uids[$row->uid]['notifiers']['email'] = 'email';
}
//...
}

?>

At no point does this function check to make sure it is matching against the relevant flag for this particular node/context. Any match for user with an email_* flag will cause emails to be sent. So if a user has emails turned on for one context, emails will get sent in all contexts.

I have been pulling my hair out trying to figure out why sometimes it seems like i can turn emails on and off, and then the next moment they are always on. initially my test users have just one content they followed and all is well. as my test users do more and subscribe to more content, they start having more than one email_* flag, and then all heck breaks loose.

Comments

BarisW’s picture

Project: Drupal Commons » Message subscribe
Version: 7.x-3.3 »
Component: Email Notifications » Code

Shouldn't this be placed in the Message subscribe module queue?

BarisW’s picture

Project: Message subscribe » Message Subscribe
Version: » 7.x-1.x-dev

Wrong module

BarisW’s picture

Status: Active » Needs review
StatusFileSize
new614 bytes

And here's the fix.

amitaibu’s picture

Shouldn't the flags IDs passed to fid already filter the non-user flags?

BarisW’s picture

Not sure. This is my issue, and the patch fixes it.

What happens is that when a node is created in a group with say 2 members and 100 nodes, not only the 2 members get an e-mail, but also all users with the same UID as there are NID's in this group. So suppose there is a node with NID 5 in this group, the user with UID 5 gets an e-mail, while he is NOT part of this group.

Commons 3.4 (and before) is sending thousands of e-mails to users that are not part of the group, just because these users happen to have the same UID as the NID of the group where the node it is posted in.

amitaibu’s picture

I think a better solution would be to change in message_subscribe_email_message_subscribe_get_subscribers_alter()

$flags = message_subscribe_email_flag_get_flags();

to

$flags = message_subscribe_email_flag_get_flags('user');

Can you please check that?

BarisW’s picture

Status: Active » Needs review
StatusFileSize
new569 bytes

Yes, that is indeed better. I've tested your proposal and that works as well.
Patch attached.

Status: Needs review » Needs work

The last submitted patch, 7: 2126689-7-fix-email-notifications.patch, failed testing.

WebSinPat’s picture

@BarisW, maybe we are having different problems... The patch in #7 does not address my issue at all and does not strike me as correct. With the change in #7 the only flag in the $flags array is 'email_user', but i am also interested in email_group, email_node, and email_term depending on the context. So with the change in #7 I don't get any notifications for nodes or groups that I am subscribed to.

Here is what I've come up with that DOES seem to be working for me. it adds context into the setting of the email notifier. basically i copied the code from function message_subscribe_message_subscribe_get_subscribers()

<?php
function message_subscribe_email_message_subscribe_get_subscribers_alter(&$uids, $values) {
  if (empty($uids)) {
    // Nobody is subscribed to the content.
    return;
  }

  $context = $values['context'];
  // Find the users that subscribed to each context.
  foreach ($context as $entity_type => $entity_ids) {

    if (!$entity_ids) {
      continue;
    }

    // Get all flags on given entity type.
    if (!$flags = message_subscribe_email_flag_get_flags($entity_type)) {
      continue;
    }

    $fids = array();
    foreach ($flags as $flag) {
      $fids[$flag->fid] = $flag->name;
    }

    // Query all the entity IDs inside the given flags. We don't use
    // flag_get_content_flags() as we want to get all the flaggings of an
    // entity-type in a single query.
    if (FLAG_API_VERSION == 2) {
      $query = db_select('flag_content', 'fc')
        ->condition('content_type', $entity_type)
        ->condition('content_id', $entity_ids, 'IN');
    }
    else {
      $query = db_select('flagging', 'fc')
        ->condition('entity_type', $entity_type)
        ->condition('entity_id', $entity_ids, 'IN');
    }

    $result = $query->fields('fc')
      ->condition('fid', array_keys($fids), 'IN')
      ->condition('uid', array_keys($uids), 'IN')
       ->groupBy('uid')
       ->execute()
       ->fetchAll();

     foreach ($result as $row) {

     // Add 'email' to the list of notifiers.
     $uids[$row->uid]['notifiers']['email'] = 'email';
     }
   }
 }
?>
WebSinPat’s picture

StatusFileSize
new2.49 KB

an attempt at a patch. my first such, hope it's not too far off the mark.

BarisW’s picture

Hi WebSinPat,

I didn't think of that, and I assume you are correct, but it's up to Amitai to make sure.
Anyhow, I tried your code and my problem is still solved, so maybe your solution would be better.

I couldn't apply the patch though. This is how do it:

- Make a git clone of the latest code (https://drupal.org/project/message_subscribe/git-instructions)
- Paste in your code
- Do "git diff > name-of-my-patch.patch"

If you want to make a patch from a codebase that's already in git (eg; as part of a distro), you could use "git diff --relative > name-of-my-patch.patch"

BarisW’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 10: 2126689-email_notification_context.patch, failed testing.

WebSinPat’s picture

new attempt at patch, per the instructions above, against 7.x-1.x HEAD.
thanks @BarisW

WebSinPat’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 14: email-notification-context-2126689-14.patch, failed testing.

WebSinPat’s picture

Status: Needs work » Needs review
StatusFileSize
new2.39 KB

re-rolled patch and removed whitespace errors. hopefully now it will at least apply....

dalinian’s picture

Hi WebSinPat,

I got patch from #17 to apply, but it still did not solve the problem for me. I think there is one minor problem with your patch. Since the get_subscribers_alter hook passes in the uids by reference, your patch leaves all of the prior uids unchecked, which is not what we want, since we know that they will always send emails. I have re-rolled your patch with a minor modification to unset the notifiers of all uids at the beginning of the alter function, so that went we set them at the end of the function, they will only apply to the uids we want to send email to.

I have done some minimal testing with this, and it seems to produce the behavior that we're looking for.

Status: Needs review » Needs work

The last submitted patch, 18: email-notification-context-fix-2126689-18.patch, failed testing.

dalinian’s picture

Let's try this again. Instead of unsetting notifiers I just make them = array(). This passed testing locally.

amitaibu’s picture

Status: Needs work » Needs review

Setting to correct status for test bot.
Haven't reviewed the code yet, but noticed there are some tabs (@dalinian you can use Dreditor to see those tabs)

WebSinPat’s picture

@dalinian, thanks! seems like a good catch. I'll give your patch a whirl later on and report back.

dalinian’s picture

Okay, I guess I should re-roll without tabs.

amitaibu’s picture

@dalinian, thanks -- can you add a simpleTest please to prevent regression.

roysegall’s picture

Assigned: Unassigned » roysegall
roysegall’s picture

I made a minor re-roll. @amitaibu - where do you want to write the tests? i'm a little confuse. Does message subscribe email module is the proper place to add the test?

amitaibu’s picture

> Does message subscribe email module is the proper place to add the test?

Yes.

BarisW’s picture

Any updates here?

roysegall’s picture

Yeah, i'm trying to get to this one.

candelas’s picture

Any updates? :)
Thanks for your work.

roysegall’s picture

This was a published a long time ago so I need some more info. I tried to set this one up but the only i was able to send messages when creating a group content is to alter message_notify_example:

function message_notify_example_node_insert($node) {
  if ($node->type != 'group_content') {
    return;
  }

  $node_wrapper = entity_metadata_wrapper('node', $node);

  $message = message_create('example_og_post_in_group', array('uid' => $node->uid));
  $wrapper = entity_metadata_wrapper('message', $message);
  $wrapper->field_node_ref->set($node);
  $wrapper->field_node_groups_ref->set($node_wrapper->{OG_AUDIENCE_FIELD}->value(array('identifier' => TRUE)));
  message_subscribe_send_message('node', $node, $message);
}

If i'm wrong so far let me know but but except that the patch isn't worked for me. After disabling the emails for the group for demo(user2) he is the only one which receive emails. I'll try to see what going on here.

roysegall’s picture

nwom’s picture

Status: Needs review » Needs work

Sadly this patch expects two flags to exist and does not work otherwise. If a site is using Message Subscribe Email Frequency then only one flag is actually necessary.

bluegeek9’s picture

Status: Needs work » Closed (outdated)