diff --git a/src/core/models/schedules.py b/src/core/models/schedules.py
index 658c56ce1df319fa699e8fcad854cafbf7309513..85ff87e28236ce0e23633e3eb1bb42f49b1fb055 100644
--- a/src/core/models/schedules.py
+++ b/src/core/models/schedules.py
@@ -127,20 +127,21 @@ class ScheduleSource(models.Model):
         if not name:
             raise ValueError('You need to provide a name for the speaker.')
 
-        if mail_guid is None and addresses is None:
-            raise ValueError('You need to provide at least mail_guid or addresses (better: both).')
-
         if mail_guid and not isinstance(mail_guid, UUID):
             mail_guid = UUID(mail_guid)
 
-        speaker_username = '_speaker_' + str(mail_guid or sha1('\n'.join(sorted(addresses))))
+        if mail_guid:
+            speaker_username = '_speaker_' + str(mail_guid)
+        elif addresses:
+            speaker_username = '_speaker_' + sha1('\n'.join(sorted(addresses)).encode('utf-8')).hexdigest()
+        else:
+            speaker_username = '_speaker_' + sha1(name.encode('utf-8')).hexdigest()
 
         # try to find by the username
         if candidate := PlatformUser.objects.filter(username=speaker_username, user_type=PlatformUser.Type.SPEAKER).first():
             return candidate, False
 
-        # basically, this is a hail-mary-type attempt: we try to find a PlatformUser who
-        # has a verified email matching the given mail_guid or any of the supplied addresses
+        # we try to find a PlatformUser who has a verified email matching the given mail_guid or any of the supplied addresses
         candidates = []  # type: List[PlatformUser]
         for cm in self.conference.users.select_related('user').filter(user__user_type__in=PlatformUser.PERSON_TYPES).iterator():  # type: ConferenceMember
             for addr in cm.user.get_verified_mail_addresses():
@@ -159,6 +160,11 @@ class ScheduleSource(models.Model):
         if len(candidates) > 1:
             raise ValueError('Multiple candidate speakers found: ' + '; '.join(x.pk for x in candidates))
 
+        # hail mary attempt: see if we have an imported speaker with the same name
+        candidates = self.conference.users.select_related('user').filter(user__user_type=PlatformUser.Type.SPEAKER, user__display_name=name).all()
+        if len(candidates) == 1:
+            return candidates[0], False
+
         # the expected case: nothing found, create a new one
         name_split = name.split(' ')
         user_kwargs = {
@@ -260,7 +266,7 @@ class ScheduleSource(models.Model):
             hints['room_name'] = item.get('room')
             hints['speaker_lookup'] = from_dict_args.get('speaker_lookup')
         elif item_type == 'speaker':
-            hints['name'] = item.get('public_name') or item.get('name')
+            hints['name'] = item.get('full_public_name') or item.get('public_name') or item.get('name')
             hints['addresses'] = item.get('addresses')
 
         mapping, new_mapping = self.get_or_create_mapping(
@@ -456,11 +462,13 @@ class ScheduleSource(models.Model):
             ```
             """
 
+            # for the source id use the provided id, uuid or guid field (in order)
+            speaker_id = speaker_info.get('id') or speaker_info.get('uuid') or speaker_info.get('guid')
+
             # sanity check: verify that required attributes are present
-            if any(x not in speaker_info for x in ['id', 'public_name']):
-                raise ValueError('Missing required attribute in speaker_info.')
+            if not speaker_info:
+                raise ValueError('Missing required attribute in speaker_info: id/uuid/guid')
 
-            speaker_id = speaker_info.get('id')
             try:
                 action = self._load_dataitem(
                     activity=activity,