Jak dodać dużą ilość kontaktów do Microsoft 365 (hurtowo z CSV + PowerShell)

Jak dodać dużą ilość kontaktów do Microsoft 365 (hurtowo z CSV + PowerShell)

Dodawanie setek lub tysięcy kontaktów zewnętrznych do Microsoft 365 ręcznie to droga przez mękę. Poniżej pokazuję sprawdzony sposób na hurtowe wgrywanie kontaktów (Mail Contacts) z pliku CSV z pełną walidacją oraz bez duplikatów — wszystko jednym skryptem PowerShell.

Co zyskasz?

  • Oszczędność czasu – import całych list w minutach.
  • Idempotencja – skrypt nie doda duplikatów (sprawdza DisplayName i ExternalEmailAddress).
  • Czytelne komunikaty – wiesz, co się udało, co już istniało i co poszło nie tak.

Wymagania wstępne

  1. Uprawnienia z rolą wystarczającą do tworzenia Mail Contacts (np. Exchange Admin).
  2. PowerShell 5.1+ (Windows) lub 7.x (Core).
  3. Moduł: ExchangeOnlineManagement.

Instalacja modułu i logowanie:

Install-Module ExchangeOnlineManagement -Scope CurrentUser -Force
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline

Przygotowanie CSV

Plik CSV musi mieć nagłówki dokładnie w tej postaci (bez polskich znaków i spacji, jak niżej):

FirstName,LastName,DisplayName,Alias,ExternalEmailAddress
Jan,Kowalski,Jan Kowalski,j.kowalski,[email protected]
Anna,Nowak,Anna Nowak,a.nowak,[email protected]

Wskazówki:

  • Kodowanie pliku: UTF-8 (z BOM), separator: przecinek (,).
  • Alias powinien być unikalny (bez spacji i znaków specjalnych).
  • ExternalEmailAddress – pełny, poprawny e-mail (np. [email protected]).

Skrypt PowerShell (wklej i uruchom)

Poniżej skrypt, który:

  • importuje CSV,
  • dla każdego wiersza sprawdza, czy kontakt już istnieje (po DisplayName lub ExternalEmailAddress),
  • tworzy kontakt tylko gdy go nie ma,
  • wypisuje przejrzyste komunikaty.
Kod powershell do wczytania wielu kontaktów
$csvFilePath = "export-csc.csv"

try {
    $Contacts = Import-Csv $csvFilePath

    foreach ($Contact in $Contacts) {
        try {
            if (Get-MailContact -Filter "DisplayName -eq '$($Contact.DisplayName)' -or ExternalEmailAddress -eq '$($Contact.ExternalEmailAddress)'" -ErrorAction SilentlyContinue) {
                Write-Host "Contact $($Contact.ExternalEmailAddress) already exists" -ForegroundColor Yellow
            }
            else {
                $contactParams = @{
                    Name                 = $Contact.DisplayName
                    FirstName            = $Contact.FirstName
                    LastName             = $Contact.LastName
                    DisplayName          = $Contact.DisplayName
                    Alias                = $Contact.Alias
                    ExternalEmailAddress = $Contact.ExternalEmailAddress
                    # WhatIf              = $true   # <- odkomentuj do testów (dry-run)
                }

                $null = New-MailContact @contactParams
                Write-Host "Contact $($Contact.ExternalEmailAddress) added successfully" -ForegroundColor Green
            }
        }
        catch {
            Write-Host "Failed to add contact $($Contact.ExternalEmailAddress). Error: $_" -ForegroundColor Red
        }
    }
}
catch {
    Write-Host "Failed to import CSV file. Error: $_" -ForegroundColor Red
}

One-liner (wskażesz tylko plik)

Po zalogowaniu Connect-ExchangeOnline możesz użyć wersji jednowierszowej (przeklej w jedną linię, zmień ścieżkę):

$csv="C:\ścieżka\export-csc.csv"; Import-Csv $csv | % { if(Get-MailContact -Filter "DisplayName -eq '$($_.DisplayName)' -or ExternalEmailAddress -eq '$($_.ExternalEmailAddress)'" -ErrorAction SilentlyContinue){Write-Host "Contact $($_.ExternalEmailAddress) already exists" -ForegroundColor Yellow} else { try { New-MailContact -Name $_.DisplayName -FirstName $_.FirstName -LastName $_.LastName -DisplayName $_.DisplayName -Alias $_.Alias -ExternalEmailAddress $_.ExternalEmailAddress | Out-Null; Write-Host "Contact $($_.ExternalEmailAddress) added successfully" -ForegroundColor Green } catch { Write-Host "Failed to add contact $($_.ExternalEmailAddress). Error: $_" -ForegroundColor Red } } }

Test bez zmian (tryb „WhatIf”)

Chcesz sprawdzić import bez tworzenia kontaktów?
W skrypcie głównym odkomentuj linię WhatIf = $true. Dzięki temu zobaczysz, co zostałoby utworzone.

Weryfikacja po imporcie

  • Centrum administracyjne Microsoft 365 → Exchange admin centerRecipients → Contacts.
  • Tu zobaczysz nowo dodane pozycje, możesz też je edytować (telefon, firma, uwagi).

Najczęstsze problemy i rozwiązania

  • „Failed to import CSV” – sprawdź kodowanie (UTF-8), separator (,), brak pustych kolumn.
  • Duplikaty – skrypt ich nie tworzy; jeżeli kontakt istnieje (po DisplayName lub ExternalEmailAddress), dostaniesz żółty komunikat.
  • Brak uprawnień – upewnij się, że konto ma rolę Exchange Admin / odpowiednie RBAC.
  • Throttling / limity – przy bardzo dużych paczkach rozważ batchowanie (np. po 500 rekordów) lub przerwę Start-Sleep -Seconds 1 w pętli.

Dodaj komentarz