diff -urpN salesforce/salesforce_api/salesforce_api.module salesforce/salesforce_api/salesforce_api.module
--- salesforce/salesforce_api/salesforce_api.module	2010-03-01 09:31:08.000000000 -0500
+++ salesforce/salesforce_api/salesforce_api.module	2010-03-17 14:24:31.000000000 -0400
@@ -45,6 +45,17 @@ define('SALESFORCE_LOG_NONE', 0);
 define('SALESFORCE_LOG_SOME', 5);
 define('SALESFORCE_LOG_ALL', 10);
 
+if (!function_exists('is_sfid')) {
+  // Without a roundtrip to salesforce.com, checking the string length is the
+  // best we can do to verify a SalesForce ID.
+  function is_sfid($sfid) {
+    if (strlen($sfid) == 15 || strlen($sfid) == 18) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+}
+
 
 /**
  * Implementation of hook_menu().
diff -urpN salesforce/sf_node/sf_node.module salesforce/sf_node/sf_node.module
--- salesforce/sf_node/sf_node.module	2010-03-01 09:38:28.000000000 -0500
+++ salesforce/sf_node/sf_node.module	2010-03-17 14:24:31.000000000 -0400
@@ -597,8 +597,8 @@ function sf_node_export($node, $fieldmap
 /**
  * Imports data from Salesforce into a node.
  *
- * @param $sfid
- *   The Salesforce ID of the object from which you want to import.
+ * @param $sf_data
+ *   The Salesforce Object OR The Salesforce ID of the object to be imported.
  * @param $fieldmap
  *   The index of the fieldmap to use to create the export object.
  * @param $nid
@@ -606,7 +606,7 @@ function sf_node_export($node, $fieldmap
  * @return
  *   The nid of the imported node or FALSE on failure.
  */
-function sf_node_import($sfid, $fieldmap, $nid = NULL) {
+function sf_node_import($sf_data, $fieldmap, $nid = NULL) {
   // Retrieve the object from Salesforce.
   $sf = salesforce_api_connect();
   if (!$sf) {
@@ -614,8 +614,17 @@ function sf_node_import($sfid, $fieldmap
     return FALSE;
   }
 
-  $sf_data = $sf->retrieve(array($sfid), $fieldmap);
+  if (is_sfid($sf_data)) {
+    $sf_data = $sf->retrieve(array($sf_data), $fieldmap);
+  }
+  elseif (is_array($sf_data)) {
+    $sf_data = (object) $sf_data;
+  }
 
+  if (empty($sf_data)) {
+    return FALSE;
+  }
+  $sfid = $sf_data->Id;
   // Load the fieldmap data.
   $map = salesforce_api_fieldmap_load($fieldmap);
   
@@ -637,6 +646,7 @@ function sf_node_import($sfid, $fieldmap
       'uid' => 1,
     );
   }
+
   // Loop through the fields on the fieldmap.
   foreach ($map['fields'] as $sf_fieldname => $drupal_fieldname) {
     // If a handler is specified for importing a value from Salesforce....
@@ -655,6 +665,10 @@ function sf_node_import($sfid, $fieldmap
   }
   $node->sf_node_skip_export = TRUE;
   node_save($node);
+  if ($map['automatic'] && !empty($node->nid)) {
+    // Store the Salesforce ID for the node and return TRUE.
+    salesforce_api_id_save('node', $node->nid, $sfid, $fieldmap);
+  }
   unset($node->sf_node_skip_export);
 
   return $node->nid;
diff -urpN salesforce/sf_notifications/sf_notifications.admin.inc salesforce/sf_notifications/sf_notifications.admin.inc
--- salesforce/sf_notifications/sf_notifications.admin.inc	1969-12-31 19:00:00.000000000 -0500
+++ salesforce/sf_notifications/sf_notifications.admin.inc	2010-03-17 14:24:31.000000000 -0400
@@ -0,0 +1,17 @@
+<?php 
+
+// @todo add tracking and reporting of messages received from SalesForce
+
+/**
+ * SF Notifications settings
+ *
+ * @todo Notifications settings per mapping
+ * @todo Notifications settings for create, update, & delete per mapping
+ * @todo Response handling: under what conditions should we return a successful response?
+ */
+function sf_notifications_settings_form(&$form_state) {
+  return array('placeholder' => array(
+      '#type' => 'markup', '#value' => 'Placeholder for more SalesForce Notifications settings'
+    ));
+}
+
diff -urpN salesforce/sf_notifications/sf_notifications.info salesforce/sf_notifications/sf_notifications.info
--- salesforce/sf_notifications/sf_notifications.info	1969-12-31 19:00:00.000000000 -0500
+++ salesforce/sf_notifications/sf_notifications.info	2010-03-17 14:24:31.000000000 -0400
@@ -0,0 +1,6 @@
+; $Id$
+name = Salesforce Notifications
+description = Responds to SOAP Outbound Messages from SalesForce.
+dependencies[] = salesforce_api
+package = Salesforce
+core = 6.x
diff -urpN salesforce/sf_notifications/sf_notifications.install salesforce/sf_notifications/sf_notifications.install
--- salesforce/sf_notifications/sf_notifications.install	1969-12-31 19:00:00.000000000 -0500
+++ salesforce/sf_notifications/sf_notifications.install	2010-03-17 14:24:31.000000000 -0400
@@ -0,0 +1,24 @@
+<?php 
+
+function sf_notifications_enable() {
+  global $base_url;
+  $sfuser = variable_get('salesforce_api_username', 'user@example.com');
+  $formula = '<code>NOT($User.Username = \'' . $sfuser . '\')</code>';
+  $args = array(
+    '!messages' => 'https://na1.salesforce.com/04k', 
+    '!workflow' => 'https://na1.salesforce.com/01Q', 
+    '!base_url' => $base_url,
+    '!formula' => $formula);
+  drupal_set_message(t('You have successfully enabled SalesForce Notifications. To make use
+    of this module, you will probably want to head over to salesforce.com and 
+    <a href="!message">set up some outbound messages</a> and <a href="!workflow">
+    associate them with workflow rules</a>. Point the outbound message(s) to 
+    !base_url and set up the workflow rules to fire when the user is NOT your 
+    SFDC API user. Use the following formula if you are unsure: !formula.', $args));
+}
+
+function sf_notifications_disable() {
+  drupal_set_message(t('You have successfully disabled SalesForce Notifications. You may
+    want to <a href="!workflow">deactivate any workflow rules</a> associated 
+    with this site.', array('!workflow' => 'https://na1.salesforce.com/01Q')));
+}
\ No newline at end of file
diff -urpN salesforce/sf_notifications/sf_notifications.module salesforce/sf_notifications/sf_notifications.module
--- salesforce/sf_notifications/sf_notifications.module	1969-12-31 19:00:00.000000000 -0500
+++ salesforce/sf_notifications/sf_notifications.module	2010-03-17 15:04:27.000000000 -0400
@@ -0,0 +1,262 @@
+<?php 
+
+define('SALESFORCE_PATH_NOTIFICATIONS_ADMIN', SALESFORCE_PATH_ADMIN . '/notifications');
+define('SALESFORCE_PATH_NOTIFICATIONS_ENDPOINT', 'sf_notifications/endpoint');
+
+/**
+ * hook_menu implementation
+ */
+function sf_notifications_menu() {
+  return array(
+    SALESFORCE_PATH_NOTIFICATIONS_ADMIN => array(
+      'title' => 'Notifications',
+      'description' => 'Placeholder for more SalesForce Notifications settings',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('sf_notifications_settings_form'),
+      'access arguments' => array('administer salesforce'),
+      'type' => MENU_LOCAL_TASK,
+      'file' => 'sf_notifications.admin.inc',
+      ),
+    SALESFORCE_PATH_NOTIFICATIONS_ENDPOINT => array(
+      'title' => FALSE,
+      'page callback' => 'sf_notifications_endpoint',
+      'access arguments' => array('access content'),
+      'type' => MENU_CALLBACK
+      ),
+    );
+}
+
+/**
+ * Menu callback for SalesForce notifications endpoint
+ * @todo Add authentication. see "Downloading the Salesforce.com Client Certificate" at
+ * http://www.salesforce.com/us/developer/docs/ajax/Content/sforce_api_ajax_queryresultiterator.htm
+ */
+function sf_notifications_endpoint() {
+  // SF Toolkit only gets included on salesforce_api_connect, which we've no reason to call.
+  require_once(drupal_get_path('module', 'salesforce_api') .'/salesforce.class.inc');
+
+  // Needed for the reference to SObject in parse_message, otherwise it just seems to die 
+  // when it tries to call new SObject()
+  require_once(drupal_get_path('module', 'salesforce_api') .'/toolkit/soapclient/SforcePartnerClient.php');
+
+  $content = file_get_contents('php://input');
+  if (empty($content)) {
+    DrupalSalesforce::watchdog(SALESFORCE_LOG_SOME, 'SalesForce Notifications: Empty request.');
+    exit;
+  }
+	$dom = new DOMDocument();
+	$dom->loadXML($content);
+	if (empty($dom) || !$dom->hasChildNodes()) {
+    DrupalSalesforce::watchdog(SALESFORCE_LOG_NONE, 
+      'SalesForce Notifications: Failed to parse into DOM Document. 
+      <pre>' . print_r($content) . '</pre>');
+		_sf_notifications_soap_respond('false');
+    exit;
+	}
+	$resultArray = _sf_notifications_parse_message($dom);
+	$ret = _sf_notifications_handle_message($resultArray);
+
+	// Sends SOAP response to SFDC
+	if ($ret) { 
+		_sf_notifications_soap_respond('true');
+	}
+	else { 
+		_sf_notifications_soap_respond('false');
+	}
+	exit;
+}
+
+/**
+ * Loop through an array of SObjects from SalesForce and save them according to 
+ * any existing sf fieldmaps and data.
+ *
+ * @param array $objects 
+ *  A numerically indexed array of SObjects (as returned by _sf_notifications_parse_message)
+ * @return (boolean) FALSE if there were errors. TRUE otherwise.
+ */
+function _sf_notifications_handle_message($objects) {
+  $success = TRUE;
+  // Assume all the records are new, and delete them while we loop otherwise.
+  $new_records = $objects['salesforce'];
+	foreach ($objects['drupal'] as $object_record) {
+	  $sfid = $object_record['sfid'];
+    $obj = $objects['salesforce'][$sfid];
+    $fieldmap = salesforce_api_fieldmap_load($object_record['fieldmap']);
+    unset($new_records[$sfid]);
+	  // Booleans from SalesForce are strings "true" and "false".
+		if ($obj->fields->IsDeleted == 'true') {
+      // Try to delete the local record. Since the record is no more, in this 
+      // case we're agnostic to the drupal_type ("node" or "user").
+      if ($object_record['drupal_type'] == 'user') {
+        user_delete(array(), $object_record['oid']);
+        DrupalSalesforce::watchdog(SALESFORCE_LOG_ALL, 
+          'SalesForce Notificaitions deleted user ' 
+          . $object_record['oid'] . ' sfid ' . $sfid);
+      } 
+      elseif ($object_record['drupal_type'] == 'node') {
+        node_delete($object_record['oid']);
+        DrupalSalesforce::watchdog(SALESFORCE_LOG_ALL, 
+          'SalesForce Notificaitions deleted node ' 
+          . $object_record['oid'] . ' sfid ' . $sfid);
+      } 
+      elseif (function_exists($object_record['drupal_type'] . '_delete')) {
+        $function = $object_record['drupal_type'] . '_delete';
+        $function($object_record['oid']);
+        DrupalSalesforce::watchdog(SALESFORCE_LOG_ALL, 
+          'SalesForce Notificaitions deleted ' 
+          . $object_record['drupal_type'] . ' ' . $object_record['oid'] 
+          . ' sfid ' . $sfid);
+      }
+      else {
+        DrupalSalesforce::watchdog(SALESFORCE_LOG_SOME, 
+          ' SalesForce Notifications: Could not find delete handler for deleted 
+          SalesForce record <pre>' . $obj . '</pre>');
+        $success = FALSE;
+      }
+			continue;
+		}
+		
+    $function = 'sf_' . $object_record['drupal_type'] . '_import';
+    if (function_exists($function)) {
+	    $drupal_id = $function($obj->fields, $object_record['fieldmap'], $object_record['oid']);
+      if ($drupal_id) {
+        DrupalSalesforce::watchdog(SALESFORCE_LOG_ALL, 
+          'SalesForce Notificaitions updated ' 
+          . $object_record['drupal_type'] . ' ' . $drupal_id);
+      }
+      else {
+        DrupalSalesforce::watchdog(SALESFORCE_LOG_NONE, 
+          'SalesForce Notificaitions failed to update ' 
+          . $object_record['drupal_type'] . ' from record. 
+          <pre>' . print_r($obj, 1) . '</pre>');
+        $success = FALSE;
+      }
+    } 
+    else {
+      DrupalSalesforce::watchdog(SALESFORCE_LOG_SOME, 
+          'SalesForce Notifications: Import handler ' . $function . ' undefined.
+          Drupal ' . $fieldmap['drupal'] . ' with id ' 
+          . $object_record['oid'] . ' was not updated.');
+      $success = FALSE;
+    }
+	}
+
+	foreach ($new_records as $sfid => $obj) {
+	  $result = db_query('SELECT fieldmap FROM {salesforce_field_map} WHERE salesforce = "%s"', $obj->type);
+    // If there are multiple fieldmaps for a single SalesForce type, there is 
+    // no way to know which one to use for an import. Execute import for all.
+    // @see todos
+    $fieldmap_id = db_result($result);
+    if (!$fieldmap_id) {
+      DrupalSalesforce::watchdog(SALESFORCE_LOG_SOME, 
+            'SalesForce Notifications: No fieldmap found.
+            <pre>' . print_r($obj, 1) . '</pre>');
+      $success = FALSE;
+      continue;
+    }
+	  do {
+	    $fieldmap = salesforce_api_fieldmap_load($fieldmap_id);
+      $fieldmap_type = $fieldmap['drupal'];
+	    if (strpos($fieldmap['drupal'], 'node_') === 0) {
+	      $fieldmap_type = 'node';
+	    }
+      $function = 'sf_' . $fieldmap_type . '_import';
+      if (function_exists($function)) {
+  	    $drupal_id = $function($obj->fields, $fieldmap_id, NULL);
+        if ($drupal_id) {
+          DrupalSalesforce::watchdog(SALESFORCE_LOG_ALL, 
+            'SalesForce Notificaitions created ' 
+            . $fieldmap['drupal'] . ' ' . $drupal_id);
+        } 
+        else {
+          DrupalSalesforce::watchdog(SALESFORCE_LOG_NONE, 
+              'SalesForce Notificaitions failed to create ' 
+              . $fieldmap['drupal'] . ' from SF record. 
+              <pre>' . print_r($obj, 1) . '</pre>');
+          $success = FALSE;
+        }
+      }
+      else {
+        DrupalSalesforce::watchdog(SALESFORCE_LOG_SOME, 
+            'SalesForce Notifications: No import handler defined for ' 
+            . $fieldmap['drupal'] . '. No record created. 
+            <pre>' . print_r($obj, 1) . '</pre>');
+          $success = FALSE;
+      } 
+    } while ($fieldmap_id = db_result($result));
+	}
+	
+	return $success;
+}
+
+
+/**
+ * Parse SOAP message into its component args.
+ *
+ * @param (object) $domDoc 
+ *  A DOMDocument representation of the outbound SOAP message from SalesForce.
+ * @return (array) $result
+ *  An array with two sub-arrays, keyed as:
+ *  'drupal':
+ *    A sequential array containing relevant salesforce_ids records.
+ *    We don't index on drupal_id because there could be overlap.
+ *  'salesforce':
+ *    An indexed array mapping sfids to SObject records from SalesForce.
+ */
+function _sf_notifications_parse_message($domDoc) {
+  $result = array('salesforce' => array(), 'drupal' => array());
+  $sfids = array();
+  // Create sObject array and fill fields provided in notification
+  $objects = $domDoc->getElementsByTagName('sObject');
+  foreach ($objects as $sObjectNode) {
+    $sObjType = $sObjectNode->getAttribute('xsi:type');
+    if (substr_count($sObjType,'sf:')) {
+      $sObjType = substr($sObjType,3);
+  	}
+    $obj = new SObject();
+    $obj->type = $sObjType;
+    $elements = $sObjectNode->getElementsByTagNameNS('urn:sobject.enterprise.soap.sforce.com','*');
+    $obj->fieldnames = array();
+    foreach ($elements as $node) {
+      if ($node->localName == 'Id') { 
+        // "Id" is a property of the SObject as well as SObject->fields
+        $sfids[] = $obj->Id = $node->textContent;
+      }
+      $fieldname = $node->localName;
+      $obj->fields->$fieldname = $node->nodeValue;
+      array_push($obj->fieldnames,$fieldname);
+    }
+  	$result['salesforce'][$obj->Id] = $obj;
+  }
+  
+  $dbresult = db_query(
+    'SELECT oid, sfid, fieldmap, drupal_type FROM salesforce_object_map 
+      WHERE sfid IN (' . db_placeholders($sfids, 'varchar') . ')', $sfids);
+  while($row = db_fetch_array($dbresult)) {
+    $result['drupal'][] = $row;
+  }
+  
+  return $result;
+}
+
+/**
+ * Format and send a SOAP response message.
+ *
+ * @param boolean $tf 
+ * @return void
+**/
+function _sf_notifications_soap_respond($tf = 'true') {
+print '<?xml version = "1.0" encoding = "utf-8"?>
+<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
+  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+		<soapenv:Body>
+			<notifications xmlns="http://soap.sforce.com/2005/09/outbound">
+				<Ack>'.$tf.'</Ack>
+			</notifications>
+		</soapenv:Body>
+</soapenv:Envelope>
+';
+}
+
+
diff -urpN salesforce/sf_user/sf_user.module salesforce/sf_user/sf_user.module
--- salesforce/sf_user/sf_user.module	2010-02-25 14:18:46.000000000 -0500
+++ salesforce/sf_user/sf_user.module	2010-03-17 14:24:31.000000000 -0400
@@ -406,8 +406,8 @@ function sf_user_export($uid, $fieldmap,
 /**
  * Imports data from Salesforce into a user.
  *
- * @param $sfid
- *   The Salesforce ID of the object from which you want to import.
+ * @param $sf_data
+ *   The Salesforce Object OR The Salesforce ID of the object to be imported.
  * @param $fieldmap
  *   The index of the fieldmap to use to create the export object.
  * @param $uid
@@ -415,7 +415,7 @@ function sf_user_export($uid, $fieldmap,
  * @return
  *   The uid of the imported user or FALSE on failure.
  */
-function sf_user_import($sfid, $fieldmap, $uid = NULL) {
+function sf_user_import($sf_data, $fieldmap, $uid = NULL) {
   // Retrieve the object from Salesforce.
   $sf = salesforce_api_connect();
   if (!$sf) {
@@ -423,13 +423,17 @@ function sf_user_import($sfid, $fieldmap
     return FALSE;
   }
 
-  $sf_data = $sf->retrieve(array($sfid), $fieldmap);
+  if (is_sfid($sf_data)) {
+    $sf_data = $sf->retrieve(array($sf_data), $fieldmap);
+  }
+  elseif (is_array($sf_data)) {
+    $sf_data = (object) $sf_data;
+  }
 
-  // Return FALSE if the object data was not found at Salesforce.
   if (empty($sf_data)) {
     return FALSE;
   }
-
+  $sfid = $sf_data->Id;
   // Load the fieldmap data.
   $map = salesforce_api_fieldmap_load($fieldmap);
 
@@ -476,6 +480,10 @@ function sf_user_import($sfid, $fieldmap
     $account->sf_user_skip_export = TRUE;
     $changes['sf_user_skip_export'] = TRUE;
     $account = user_save($account, $changes);
+    if ($map['automatic'] && !empty($account->uid)) {
+      // Store the Salesforce ID for the node and return TRUE.
+      salesforce_api_id_save('user', $account->uid, $sfid, $fieldmap);
+    }
     unset($account->sf_user_skip_export);
   }
 
