ebb_ews_update_cache_for_expression (EBookBackendEws *bbews,
				     const gchar *expr,
				     GCancellable *cancellable,
				     GError **error)
{
	EBookMetaBackend *meta_backend;
	CamelEwsSettings *ews_settings;
	gboolean success = TRUE;

	g_return_val_if_fail (E_IS_BOOK_BACKEND_EWS (bbews), FALSE);

	/* Resolve names in GAL only for GAL */
	if (!bbews->priv->is_gal)
		return TRUE;

	ews_settings = ebb_ews_get_collection_settings (bbews);

	if (camel_ews_settings_get_oab_offline (ews_settings))
		return TRUE;

	meta_backend = E_BOOK_META_BACKEND (bbews);

	g_rec_mutex_lock (&bbews->priv->cnc_lock);

	/* Search only if not searching for everything */
	if (expr && *expr && g_ascii_strcasecmp (expr, "(contains \"x-evolution-any-field\" \"\")") != 0) {
		gchar *restriction_expr = NULL;
		GSList *mailboxes = NULL, *contacts = NULL, *found_infos = NULL;
		gboolean includes_last_item = TRUE;

		success = ebb_ews_build_restriction (expr, &restriction_expr) &&
			e_book_meta_backend_ensure_connected_sync (meta_backend, cancellable, error) &&
			e_ews_connection_resolve_names_sync (bbews->priv->cnc, EWS_PRIORITY_MEDIUM, restriction_expr,
				EWS_SEARCH_AD, NULL, TRUE, &mailboxes, &contacts, &includes_last_item, cancellable, error);

		if (success) {
			EBookCache *book_cache;
			ESourceEwsFolder *ews_folder;
			gboolean use_primary_address;
			GSList *mlink, *clink;

			ews_folder = e_source_get_extension (e_backend_get_source (E_BACKEND (bbews)), E_SOURCE_EXTENSION_EWS_FOLDER);
			use_primary_address = e_source_ews_folder_get_use_primary_address (ews_folder);
			book_cache = e_book_meta_backend_ref_cache (meta_backend);

			for (mlink = mailboxes, clink = contacts; mlink; mlink = g_slist_next (mlink), clink = g_slist_next (clink)) {
				EwsMailbox *mb = mlink->data;
				EEwsItem *contact_item = clink ? clink->data : NULL;
				EBookMetaBackendInfo *nfo;
				EContact *contact = NULL, *old_contact = NULL;
				gboolean is_public_dl = FALSE, mailbox_address_set = FALSE;
				const gchar *str;

				if (g_strcmp0 (mb->mailbox_type, "PublicDL") == 0) {
					contact = e_contact_new ();

					if (!ebb_ews_get_dl_info_gal (bbews, contact, mb, cancellable, NULL)) {
						g_clear_object (&contact);
					} else {
						is_public_dl = TRUE;
					}
				}

				if (!contact && contact_item && e_ews_item_get_item_type (contact_item) == E_EWS_ITEM_TYPE_CONTACT)
					contact = ebb_ews_item_to_contact (bbews, contact_item, use_primary_address && !is_public_dl, cancellable, NULL);

				if (!contact)
					contact = e_contact_new ();

				/* We do not get an id from the server, so just using email_id as uid for now */
				e_contact_set (contact, E_CONTACT_UID, mb->email);

				/* There is no ChangeKey provided either, thus make up some revision,
				   to have the contact always updated in the local cache. */
				ebews_populate_rev (contact, NULL);

				if (use_primary_address && !is_public_dl && mb->email &&
				    (!mb->routing_type || g_ascii_strcasecmp (mb->routing_type, "SMTP") == 0)) {
					e_contact_set (contact, E_CONTACT_EMAIL_1, mb->email);
					mailbox_address_set = TRUE;
				}

				str = e_contact_get_const (contact, E_CONTACT_FULL_NAME);
				if (!str || !*str)
					e_contact_set (contact, E_CONTACT_FULL_NAME, mb->name);

				str = e_contact_get_const (contact, E_CONTACT_EMAIL_1);
				if (!str || !*str || (!is_public_dl && contact_item && !mailbox_address_set &&
				    e_ews_item_get_item_type (contact_item) == E_EWS_ITEM_TYPE_CONTACT)) {
					/* Cleanup first, then re-add only SMTP addresses */
					e_contact_set (contact, E_CONTACT_EMAIL_1, NULL);
					e_contact_set (contact, E_CONTACT_EMAIL_2, NULL);
					e_contact_set (contact, E_CONTACT_EMAIL_3, NULL);
					e_contact_set (contact, E_CONTACT_EMAIL_4, NULL);
					e_contact_set (contact, E_CONTACT_EMAIL, NULL);

					ebews_populate_emails_ex (bbews, contact, contact_item, TRUE, use_primary_address && !is_public_dl);
				}

				str = e_contact_get_const (contact, E_CONTACT_EMAIL_1);
				if (!str || !*str) {
					e_contact_set (contact, E_CONTACT_EMAIL_1, mb->email);
				} else if (!is_public_dl && !mailbox_address_set && mb->email &&
					   (!mb->routing_type || g_ascii_strcasecmp (mb->routing_type, "SMTP") == 0)) {
					EContactField fields[3] = { E_CONTACT_EMAIL_2, E_CONTACT_EMAIL_3, E_CONTACT_EMAIL_4 };
					gchar *emails[3];
					gint ii, ff = 0;

					emails[0] = e_contact_get (contact, E_CONTACT_EMAIL_1);
					emails[1] = e_contact_get (contact, E_CONTACT_EMAIL_2);
					emails[2] = e_contact_get (contact, E_CONTACT_EMAIL_3);

					/* Make the mailbox email the primary email and skip duplicates */
					e_contact_set (contact, E_CONTACT_EMAIL_1, NULL);
					e_contact_set (contact, E_CONTACT_EMAIL_2, NULL);
					e_contact_set (contact, E_CONTACT_EMAIL_3, NULL);
					e_contact_set (contact, E_CONTACT_EMAIL_4, NULL);
					e_contact_set (contact, E_CONTACT_EMAIL, NULL);

					e_contact_set (contact, E_CONTACT_EMAIL_1, mb->email);

					for (ii = 0; ii < 3; ii++) {
						if (emails[ii] && g_ascii_strcasecmp (emails[ii], mb->email) != 0) {
							e_contact_set (contact, fields[ff], emails[ii]);
							ff++;
						}

						g_free (emails[ii]);
					}
				}

				/* Copy photo information, if any there */
				if (e_book_cache_get_contact (book_cache, mb->email, FALSE, &old_contact, cancellable, NULL) && old_contact) {
					EContactPhoto *photo;

					photo = e_contact_get (old_contact, E_CONTACT_PHOTO);
					if (photo) {
						e_contact_set (contact, E_CONTACT_PHOTO, photo);
						e_contact_photo_free (photo);
					} else {
						const gchar *photo_check_date;

						photo_check_date = ebb_ews_get_photo_check_date (old_contact);
						if (photo_check_date)
							ebb_ews_store_photo_check_date (contact, photo_check_date);
					}

					g_clear_object (&old_contact);
				}

				ebb_ews_store_original_vcard (contact);

				nfo = e_book_meta_backend_info_new (e_contact_get_const (contact, E_CONTACT_UID),
					e_contact_get_const (contact, E_CONTACT_REV), NULL, NULL);
				nfo->object = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);

				found_infos = g_slist_prepend (found_infos, nfo);

				g_object_unref (contact);
			}

			g_clear_object (&book_cache);
		}

		g_slist_free_full (mailboxes, (GDestroyNotify) e_ews_mailbox_free);
		e_util_free_nullable_object_slist (contacts);

		if (success) {
			GSList *created_objects = NULL, *modified_objects = NULL;

			success = e_book_meta_backend_split_changes_sync (meta_backend, found_infos, &created_objects,
				&modified_objects, NULL, cancellable, error);
			if (success)
				success = e_book_meta_backend_process_changes_sync (meta_backend, created_objects,
					modified_objects, NULL, cancellable, error);

			g_slist_free_full (created_objects, e_book_meta_backend_info_free);
			g_slist_free_full (modified_objects, e_book_meta_backend_info_free);
		}

		g_slist_free_full (found_infos, e_book_meta_backend_info_free);
		g_free (restriction_expr);
	}

	g_rec_mutex_unlock (&bbews->priv->cnc_lock);

	ebb_ews_convert_error_to_edb_error (error);
	ebb_ews_maybe_disconnect_sync (bbews, error, cancellable);

	return success;
}