diff --git a/.arclint b/.arclint
--- a/.arclint
+++ b/.arclint
@@ -65,7 +65,7 @@
     "text": {
       "type": "text",
       "exclude": [
-        "(^src/(.*/)?__tests__/[^/]+/.*\\.(txt|json|expect))"
+        "(^src/(.*/)?__tests__/[^/]+/.*\\.(txt|json|expect|ics))"
       ]
     },
     "text-without-length": {
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -311,6 +311,7 @@
     'BulkSelectParameterType' => 'applications/transactions/bulk/type/BulkSelectParameterType.php',
     'BulkStringParameterType' => 'applications/transactions/bulk/type/BulkStringParameterType.php',
     'BulkTokenizerParameterType' => 'applications/transactions/bulk/type/BulkTokenizerParameterType.php',
+    'CalendarImportTestCase' => 'applications/calendar/import/__tests__/CalendarImportTestCase.php',
     'CalendarTimeUtil' => 'applications/calendar/util/CalendarTimeUtil.php',
     'CalendarTimeUtilTestCase' => 'applications/calendar/__tests__/CalendarTimeUtilTestCase.php',
     'CelerityAPI' => 'applications/celerity/CelerityAPI.php',
@@ -6317,6 +6318,7 @@
     'BulkSelectParameterType' => 'BulkParameterType',
     'BulkStringParameterType' => 'BulkParameterType',
     'BulkTokenizerParameterType' => 'BulkParameterType',
+    'CalendarImportTestCase' => 'PhabricatorTestCase',
     'CalendarTimeUtil' => 'Phobject',
     'CalendarTimeUtilTestCase' => 'PhabricatorTestCase',
     'CelerityAPI' => 'Phobject',
diff --git a/src/applications/calendar/import/__tests__/CalendarImportTestCase.php b/src/applications/calendar/import/__tests__/CalendarImportTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/import/__tests__/CalendarImportTestCase.php
@@ -0,0 +1,231 @@
+<?php
+
+final class CalendarImportTestCase extends PhabricatorTestCase {
+
+  protected function getPhabricatorTestCaseConfiguration() {
+    return array(
+      self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES => true,
+    );
+  }
+
+  // Indexes of the "expectedInviteesTests" test.
+  const INVITEED_USER = 0;
+  const INVITEED_EXPECTED = 1;
+  const INVITEED_RESULT = 2;
+
+  public function testIcsFileImportWithGuestThatIsHost() {
+    $alice_unverified =
+      $this->generateTestUserWithVerifiedMail(
+        'alice@example.com',
+        0);
+    $lincoln_verified =
+      $this->generateTestUserWithVerifiedMail(
+        'a.lincoln@example.com',
+        1);
+    $alien_unverified =
+      $this->generateTestUserWithVerifiedMail(
+        'alien.unferified@example.com',
+        0);
+    $alien_verified =
+      $this->generateTestUserWithVerifiedMail(
+        'alien.verified@example.com',
+        1);
+
+    // Tests are event-based. Each event has their expected invitees.
+    $tests = array(
+      // Test zero. Alice imports an event with A.Lincoln.
+      array(
+        'test' => pht('alice invites a.lincoln via verified email'),
+        'file' => 'simple-event-alincoln-guest.ics',
+        'fileAuthor' => $alice_unverified,
+        'expectedInvitees' => 3,
+        'expectedInviteesTests' => array(
+          // Documentation:
+          //   Array 0 (INVITEED_USER):     User object
+          //   Array 1 (INVITEED_EXPECTED): Presence (bool)
+          array($lincoln_verified, false),
+          array($alice_unverified, false),
+          array($alien_unverified, false),
+          array($alien_verified, false),
+        ),
+      ),
+      // Test one. A.Lincoln imports an event with A.Lincoln.
+      array(
+        'test' => pht('a.lincoln self-invite via verified email'),
+        'file' => 'simple-event-alincoln-guest.ics',
+        'fileAuthor' => $lincoln_verified,
+        'expectedInvitees' => 3,
+        'expectedInviteesTests' => array(
+//        array($lincoln_verified, true), // Self-invitation. T15564
+          array($alice_unverified, false),
+          array($alien_unverified, false),
+          array($alien_verified, false),
+        ),
+      ),
+    );
+
+    foreach ($tests as $test) {
+      $this->runIcsFileImportTestWithExpectedResults(
+        $test['test'],
+        $test['file'],
+        $test['fileAuthor'],
+        $test['expectedInvitees'],
+        $test['expectedInviteesTests']);
+    }
+  }
+
+  private function runIcsFileImportTestWithExpectedResults(
+    $test, $file, $importer_author, $expecteds, $invitees_tests) {
+
+    $ics_path = __DIR__.'/events/'.$file;
+
+    // Prepare a calendar import.
+    $import_type = new PhabricatorCalendarICSFileImportEngine();
+    $calendar_import = PhabricatorCalendarImport::initializeNewCalendarImport(
+      $importer_author,
+      clone $import_type);
+
+    // Create the File containing the ICS example.
+    $file_data = Filesystem::readFile($ics_path);
+    $file_test_engine = new PhabricatorTestStorageEngine();
+    $file_params = array(
+      'name' => $file,
+      'viewPolicy' => PhabricatorPolicies::POLICY_USER,
+      'authorPHID' => $importer_author->getPHID(),
+      'storageEngines' => array($file_test_engine),
+    );
+    $file_up = PhabricatorFile::newFromFileData($file_data, $file_params);
+
+    // Create a calendar import with our ICS file.
+    $import_xactions = array();
+    $import_xactions[] = id(new PhabricatorCalendarImportTransaction())
+      ->setTransactionType(
+        PhabricatorCalendarImportICSFileTransaction::TRANSACTIONTYPE)
+      ->setNewValue($file_up->getPHID());
+
+    // Persist the calendar import and get it.
+    id(new PhabricatorCalendarImportEditor())
+      ->setActor($importer_author)
+      ->setContentSource($this->newContentSource())
+      ->applyTransactions($calendar_import, $import_xactions);
+
+    $import_type->importEventsFromSource(
+      $importer_author,
+      $calendar_import,
+      false);
+
+    // Find imported events from the perspective of the importer author itself.
+    // So we check if we gained some extra people email visibility by mistake.
+    // The backend does not support attachInvitees() and it's done by default.
+    $events = (new PhabricatorCalendarEventQuery())
+      ->setViewer($importer_author)
+      ->withImportSourcePHIDs(array($calendar_import->getPHID()))
+      ->execute();
+
+    // At the moment test cases are hardcoded with one event.
+    $this->assertEqual(
+      1,
+      count($events),
+      pht('Unexpected events in file "%s" on test "%s"',
+        $file,
+        $test));
+
+    // Take the first event.
+    $event = head($events);
+
+    // How many people we invited in this event.
+    $this->assertEqual(
+      $expecteds,
+      count($event->getInvitees()),
+      pht('Unexpected invitees in file "%s" on test "%s"', $file, $test));
+
+    foreach ($invitees_tests as $invitees_test) {
+      $this->assertMatchingInvitees($test, $file, $event, $invitees_tests);
+    }
+
+    $event->delete();
+  }
+
+  /**
+   * Check if the invitees matches.
+   */
+  private function assertMatchingInvitees($test, $file, $event, $expecteds) {
+
+    // Index what we expect, by user PHID.
+    $expected_users_by_phid = [];
+    foreach ($expecteds as $expected_invited_data) {
+        $user_phid = $expected_invited_data[self::INVITEED_USER]
+          ->getPHID();
+        $expected_users_by_phid[$user_phid]
+          = $expected_invited_data;
+    }
+
+    // Get current invitees (mixed between "PHID-CXNV" and "PHID-USER").
+    $actuals_phids_mixed = mpull($event->getInvitees(), 'getInviteePHID');
+
+    // Get just actual users.
+    $actual_users = (new PhabricatorUser())->loadAllWhere(
+      'phid IN (%Ls)',
+      $actuals_phids_mixed);
+    $actual_users = mpull($actual_users, null, 'getPHID');
+
+    // Map actual users with the expected ones.
+    foreach ($actual_users as $actual_user) {
+        $user_phid = $actual_user->getPHID();
+        $found = isset($expected_users_by_phid[$user_phid]);
+        if (!$found) {
+            $expected_users_by_phid[$user_phid] = array();
+        }
+        $expected_users_by_phid[$user_phid][self::INVITEED_RESULT]
+          = $found;
+    }
+
+//   In the future it may be useful to also check external users
+//   by their email. In case, start from here!
+//   but note that the 'getURI()' returns 'mailto:' stuff.
+//  $actual_externals = (new PhabricatorCalendarExternalInvitee())
+//      ->loadAllWhere(
+//      'phid IN (%Ls)',
+//      $actuals_phids_mixed);
+//  $actual_externals = mpull($actual_externals, null, 'getURI');
+
+    // Check results (matched or not).
+    foreach ($expected_users_by_phid as $phid => $expecteds_data) {
+      $expected = idx($expecteds_data, self::INVITEED_EXPECTED, null);
+      $result = idx($expecteds_data, self::INVITEED_RESULT, false);
+      $user = idx($expecteds_data, self::INVITEED_USER, null);
+      if ($expected !== null) {
+        $this->assertEqual(
+          $expected,
+          $result,
+          pht('Unexpected presence of user "%s" in file "%s" on test "%s"',
+            $user == null ? '(unknown)' : $user->loadPrimaryEmailAddress(),
+            $file,
+            $test));
+      }
+    }
+  }
+
+  /**
+   * Generate a test user with a specific verified (or not) email.
+   * @param string $mail Email address
+   * @param int    $is_verified 0: unverified, 1: verified
+   * @return PhabricatorUser
+   */
+  private function generateTestUserWithVerifiedMail($mail, $is_verified) {
+    $user = $this->generateNewTestUser();
+
+    // Set our primary address as verified or not.
+    $email = id(new PhabricatorUserEmail())->loadOneWhere(
+      'userPHID = %s',
+      $user->getPHID());
+
+    $email->setAddress($mail);
+    $email->setIsVerified($is_verified);
+    $email->setIsPrimary(true);
+    $email->save();
+
+    return $user;
+  }
+
+}
diff --git a/src/applications/calendar/import/__tests__/events/simple-event-alincoln-guest.ics b/src/applications/calendar/import/__tests__/events/simple-event-alincoln-guest.ics
new file mode 100644
--- /dev/null
+++ b/src/applications/calendar/import/__tests__/events/simple-event-alincoln-guest.ics
@@ -0,0 +1,23 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Phacility//Phabricator//EN
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20240205
+DTEND;VALUE=DATE:20240206
+DTSTAMP:20240411T230207Z
+ORGANIZER;CN=asd@group.calendar.google.com:mailto:lol@group.calendar.google.com
+UID:blabla@google.com
+ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=
+ foo@example.com;X-NUM-GUESTS=0:mailto:foo@example.com
+ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=a.
+ lincoln@example.com;X-NUM-GUESTS=0:mailto:a.lincoln@example.com
+ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=
+ alien@example.com;X-NUM-GUESTS=0:mailto:alien@example.com
+CREATED:20240123T154250Z
+LAST-MODIFIED:20240123T162620Z
+SEQUENCE:0
+STATUS:CONFIRMED
+SUMMARY:A Lincoln, Foo and Alien to FOSDEM 2024
+TRANSP:TRANSPARENT
+END:VEVENT
+END:VCALENDAR