How can I pull Salesforce objects as users, updating existing accounts when the email address matches?

cn flag

I have a Drupal install that has been live for many years with over 200 thousand users.

We are currently trying to sync our salesforce users with our Drupal users but we only need to do this for certain user roles which would only be about 3000 or so.

I am using Drupal 9, the Salesforce Suit Module v:5.0.0, and I am using the salesforce_pull submodule that is part of that.

My user mapping is working for importing only the new users we want into Drupal; however, Drupal is creating duplicate users even if a user already exists with the same email as what is being pulled over. About half of those 3000 need to be new, the other half will already exist in the Drupal system.

What I am trying to achieve is for Drupal to find a user with that email, and update that record to be connected with salesforce and update new fields as needed.

I have run into many walls with trying to get this to work and any suggestions would be greatly appreciated.

I have also tried setting the upsert key to be the email; however, that key only seems to apply once the Salesforce connection has been made as it doesn't seem to affect the original binding of the Salesforce object with pre-existing entities.

id flag
This is not possible to answer as written as there is no technical description of the coded solution or contributed modules used. We can't suggest what you should be doing differently because we don't know, technically, what you implemented.
Rubix05 avatar
cn flag
Help me understand how I need to be clearer... I have listed what module I am using and the mapping that I created and the version - The implementation was that I created a mapping through that module. I am happy to provide more information. In the time being, I have moved the technical details higher up in my question as it was at the bottom and may have been missed
id flag
This bug report in the Drupal 7 version of the module appears to address the same question:
Kevin avatar
in flag
You are not matching the correct upsert key with existing users to their Salesforce ID. That is why its trying to create new users.
Rubix05 avatar
cn flag
Thank you Kevin, I believe the issue is not with the upsert key. I have tried setting the upsert key to be the email; however, that key only seems to apply once the salesforce connection has been made it doesn't seem to affect when binding the salesforce object with a pre-existing entity with that key.
id flag
@Rubix05 That is more information than is in the question above. When I asked for more information that is the kind of thing that I meant, although you are correct that I overlooked you mentioning the module.
cn flag

The answer was to use an Event Subscriber.

Here is a generic form of my code for anyone else who may have this question. This code is working but there seems to be another event that is in the process of creating a new user which is never completed. I was getting a simple notice log that the user was not able to be created (Which is what I want); however, I would ideally be able to abort this process in the event somehow instead of letting it fail gracefully elsewhere.

Critiques and improvements are welcome!


namespace Drupal\my_module\EventSubscriber;

use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\salesforce\Event\SalesforceEvents;
use Drupal\salesforce_mapping\Event\SalesforcePullEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

 * Class MyNewSubscriber.
class MyNewSubscriber implements EventSubscriberInterface {

  use StringTranslationTrait;

  public function pullPrepull(SalesforcePullEvent $event) {

    /** @var \Drupal\user\Entity\User $account */
    $account = $event->getEntity();
    $mapping = $event->getMapping();
    $salesforceObj = $event->getMappedObject();

    // check if the mapping matches the one I want to revise
    switch ($mapping->id()) {
      case 'my_salesforce_mapping':
        if($account->isNew()) {
          // Be mindful that your salesforce fields may be different. Mine are "Email" and "Name"
          $sf_email = $event->getMappedObject()->getSalesforceRecord()->field('Email');
          if(empty($sf_email)) {
            $event->disallowPull(); // We will reject any salesforce records that don't have an email associated with it. You may want to do something different here

          $drupal_user = user_load_by_mail($sf_email);

          // Find if a user with that email exists
          if($drupal_user != false) {
            \Drupal::logger('salesforce')->debug("Update the user with email {$sf_email} instead of creating a duplicate");
          } else {
            \Drupal::logger('salesforce')->debug("There was an issue when updating the user - Unknown email for {$event->getMappedObject()->getSalesforceRecord()->field('Name')}");
        } else {
          // I don't need to do anything because the entities are already mapped

   * {@inheritdoc}
  public static function getSubscribedEvents() {
    $events = [
      SalesforceEvents::PULL_PREPULL => 'pullPrepull',
    return $events;

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.