File created successfully at: C:\Users\MikeSwanson\AppData\Local\Temp\create-migration-endpoint.ps1

# Create Exchange Online Migration Endpoint for Neptune Exchange
# Run this in an Exchange Online PowerShell session

Write-Host "=== Creating Migration Endpoint for heieck.org ===" -ForegroundColor Cyan
Write-Host ""

# Check if endpoint already exists
$existingEndpoint = Get-MigrationEndpoint -Identity "Neptune-Heieck" -ErrorAction SilentlyContinue

if ($existingEndpoint) {
    Write-Host "Migration endpoint 'Neptune-Heieck' already exists" -ForegroundColor Yellow
    Write-Host "Status: $($existingEndpoint.Status)" -ForegroundColor Gray
    Write-Host ""
    Write-Host "If you need to recreate it, run:" -ForegroundColor Gray
    Write-Host "Remove-MigrationEndpoint -Identity 'Neptune-Heieck' -Confirm:`$false" -ForegroundColor White
    exit 0
}

# Create credentials
Write-Host "Creating Neptune Exchange credentials..." -ForegroundColor Cyan
$neptunePass = ConvertTo-SecureString "Gptf*77ttb##" -AsPlainText -Force
$neptuneCred = New-Object PSCredential("ACG\administrator", $neptunePass)

Write-Host "Creating migration endpoint..." -ForegroundColor Cyan

try {
    New-MigrationEndpoint `
        -Name "Neptune-Heieck" `
        -ExchangeOutlookAnywhere `
        -Autodiscover:$false `
        -RemoteServer "neptune.acghosting.com" `
        -Credentials $neptuneCred `
        -Authentication Basic `
        -ErrorAction Stop

    Write-Host "Migration endpoint created successfully!" -ForegroundColor Green

    # Show details
    Write-Host "`nEndpoint details:" -ForegroundColor Cyan
    Get-MigrationEndpoint -Identity "Neptune-Heieck" | Format-List Identity, RemoteServer, EndpointType, Status

} catch {
    Write-Host "Failed to create endpoint: $($_.Exception.Message)" -ForegroundColor Red
    exit 1
}


Now let me create the script to create the migration batch as well.


Write

# Create Migration Batch for heieck.org mailboxes
# Run this AFTER creating the migration endpoint

Write-Host "=== Creating Migration Batch for heieck.org ===" -ForegroundColor Cyan
Write-Host ""

# Verify endpoint exists
$endpoint = Get-MigrationEndpoint -Identity "Neptune-Heieck" -ErrorAction SilentlyContinue
if (!$endpoint) {
    Write-Host "ERROR: Migration endpoint 'Neptune-Heieck' not found!" -ForegroundColor Red
    Write-Host "Run create-migration-endpoint.ps1 first" -ForegroundColor Yellow
    exit 1
}

Write-Host "Found migration endpoint: Neptune-Heieck" -ForegroundColor Green

# Create CSV data
$csvData = @"
EmailAddress
sheila@heieck.org
jjh@heieck.org
"@

$csvBytes = [System.Text.Encoding]::UTF8.GetBytes($csvData)

# Get target delivery domain
Write-Host "`nGetting target delivery domain..." -ForegroundColor Cyan
$domains = Get-AcceptedDomain
$targetDomain = ($domains | Where-Object { $_.DomainName -like "*.onmicrosoft.com" }).DomainName

if (!$targetDomain) {
    Write-Host "ERROR: Could not find onmicrosoft.com domain!" -ForegroundColor Red
    exit 1
}

Write-Host "Target delivery domain: $targetDomain" -ForegroundColor Green

# Create batch name
$batchName = "Heieck-$(Get-Date -Format 'yyyyMMdd-HHmm')"

Write-Host "`nCreating migration batch: $batchName..." -ForegroundColor Cyan

try {
    New-MigrationBatch `
        -Name $batchName `
        -SourceEndpoint "Neptune-Heieck" `
        -CSVData $csvBytes `
        -TargetDeliveryDomain $targetDomain `
        -AutoStart `
        -AutoComplete `
        -ErrorAction Stop

    Write-Host "Migration batch created and started!" -ForegroundColor Green

    # Show status
    Write-Host "`n=== Migration Status ===" -ForegroundColor Cyan
    Get-MigrationBatch -Identity $batchName | Format-List Status, State, TotalCount, SyncedItemCount

    Write-Host "`n=== Users ===" -ForegroundColor Cyan
    Get-MigrationUser -BatchId $batchName | Format-Table Identity, Status, ItemsTransferred, PercentageComplete -AutoSize

    Write-Host "`nMonitor with:" -ForegroundColor Yellow
    Write-Host "Get-MigrationBatch -Identity '$batchName' | Get-MigrationUser | Format-Table Identity, Status, ItemsTransferred, PercentageComplete" -ForegroundColor White

} catch {
    Write-Host "Failed to create batch: $($_.Exception.Message)" -ForegroundColor Red
    exit 1
}


File created successfully at: C:\Users\MikeSwanson\AppData\Local\Temp\create-migration-batch.ps1

# Create Migration Batch for heieck.org mailboxes
# Run this AFTER creating the migration endpoint

Write-Host "=== Creating Migration Batch for heieck.org ===" -ForegroundColor Cyan
Write-Host ""

# Verify endpoint exists
$endpoint = Get-MigrationEndpoint -Identity "Neptune-Heieck" -ErrorAction SilentlyContinue
if (!$endpoint) {
    Write-Host "ERROR: Migration endpoint 'Neptune-Heieck' not found!" -ForegroundColor Red
    Write-Host "Run create-migration-endpoint.ps1 first" -ForegroundColor Yellow
    exit 1
}

Write-Host "Found migration endpoint: Neptune-Heieck" -ForegroundColor Green

# Create CSV data
$csvData = @"
EmailAddress
sheila@heieck.org
jjh@heieck.org
"@

$csvBytes = [System.Text.Encoding]::UTF8.GetBytes($csvData)

# Get target delivery domain
Write-Host "`nGetting target delivery domain..." -ForegroundColor Cyan
$domains = Get-AcceptedDomain
$targetDomain = ($domains | Where-Object { $_.DomainName -like "*.onmicrosoft.com" }).DomainName

if (!$targetDomain) {
    Write-Host "ERROR: Could not find onmicrosoft.com domain!" -ForegroundColor Red
    exit 1
}

Write-Host "Target delivery domain: $targetDomain" -ForegroundColor Green

# Create batch name
$batchName = "Heieck-$(Get-Date -Format 'yyyyMMdd-HHmm')"

Write-Host "`nCreating migration batch: $batchName..." -ForegroundColor Cyan

try {
    New-MigrationBatch `
        -Name $batchName `
        -SourceEndpoint "Neptune-Heieck" `
        -CSVData $csvBytes `
        -TargetDeliveryDomain $targetDomain `
        -AutoStart `
        -AutoComplete `
        -ErrorAction Stop

    Write-Host "Migration batch created and started!" -ForegroundColor Green

    # Show status
    Write-Host "`n=== Migration Status ===" -ForegroundColor Cyan
    Get-MigrationBatch -Identity $batchName | Format-List Status, State, TotalCount, SyncedItemCount

    Write-Host "`n=== Users ===" -ForegroundColor Cyan
    Get-MigrationUser -BatchId $batchName | Format-Table Identity, Status, ItemsTransferred, PercentageComplete -AutoSize

    Write-Host "`nMonitor with:" -ForegroundColor Yellow
    Write-Host "Get-MigrationBatch -Identity '$batchName' | Get-MigrationUser | Format-Table Identity, Status, ItemsTransferred, PercentageComplete" -ForegroundColor White

} catch {
    Write-Host "Failed to create batch: $($_.Exception.Message)" -ForegroundColor Red
    exit 1
}


Now let me provide instructions to run these scripts in sequence. The user should already be connected to Exchange Online PowerShell.


Graph API access isn't working due to an app registration permission issue, but we don't need it. Let's proceed with the Exchange Online migration using PowerShell (which you're already connected to).

I've created two scripts:

**Step 1: Create the migration endpoint**
```powershell
& "C:\Users\MikeSwanson\AppData\Local\Temp\create-migration-endpoint.ps1"
```

This will create the connection to Neptune Exchange Server (neptune.acghosting.com).

**Step 2: Create and start the migration batch**
```powershell
& "C:\Users\MikeSwanson\AppData\Local\Temp\create-migration-batch.ps1"
```

This will:
- Create a migration batch for sheila@heieck.org and jjh@heieck.org
- Automatically start the migration
- Automatically complete when done

Run these commands in your Exchange Online PowerShell session. The first command creates the endpoint with the corrected syntax (using `-RemoteServer` instead of `-ExchangeServer`).


PS C:\Users\MikeSwanson> $neptunePass = ConvertTo-SecureString "Gptf*77ttb##" -AsPlainText -Force
PS C:\Users\MikeSwanson>   $neptuneCred = New-Object PSCredential("ACG\administrator", $neptunePass)
PS C:\Users\MikeSwanson>
PS C:\Users\MikeSwanson>   New-MigrationEndpoint `
>>     -Name "Neptune-Heieck" `
>>     -ExchangeOutlookAnywhere `
>>     -Autodiscover:$false `
>>     -RemoteServer "neptune.acghosting.com" `
>>     -Credentials $neptuneCred `
>>     -Authentication Basic
New-MigrationEndpoint : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:3
+   New-MigrationEndpoint `
+   ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-MigrationEndpoint], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,New-MigrationEndpoint

PS C:\Users\MikeSwanson> New-MigrationEndpoint `
>>     -Name "Neptune-Heieck" `
>>     -ExchangeOutlookAnywhere `
>>     -Autodiscover:$false `
>>     -RemoteServer "neptune.acghosting.com" `
>>     -RPCProxyServer "neptune.acghosting.com" `
>>     -Credentials $neptuneCred `
>>     -Authentication Basic
New-MigrationEndpoint : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:1
+ New-MigrationEndpoint `
+ ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-MigrationEndpoint], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,New-MigrationEndpoint

PS C:\Users\MikeSwanson>

Gather Neptune Exchange server details and credentials

Gathering Neptune Exchange server details

Access Neptune via VPN for internal management

Assess mailbox sizes and user count for migration planning

Create Microsoft 365 mailboxes for heieck.org users

Create Exchange Online migration endpoint

Creating Exchange Online migration endpoint

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


The user is still getting "Parameter set cannot be resolved using the specified named parameters" errors. This suggests the parameter combination is still wrong for Exchange Online migration endpoints.

Let me think about this. For Exchange Online cutover migrations from on-premises Exchange, the `-ExchangeOutlookAnywhere` switch might need different parameters. Let me check what the correct syntax is.

Actually, for a cutover migration from Exchange 2016, we might need to use:
1. `-ExchangeRemoteMove` for hybrid scenarios (but user said this isn't hybrid)
2. Or we need different parameters for Outlook Anywhere

Looking at the Exchange Online documentation, for Outlook Anywhere endpoints, we typically need:
- `-ExchangeOutlookAnywhere` (switch)
- `-Autodiscover` (bool)
- `-RemoteServer` (string) - the Exchange server FQDN
- `-Credentials` (PSCredential)
- Either `-EmailAddress` for autodiscover testing OR both `-ExchangeServer` and `-RPCProxyServer`

Wait, let me reconsider. The issue might be that `-ExchangeOutlookAnywhere` is a switch that defines a parameter set, and we need to include the right combination.

For ExchangeOutlookAnywhere endpoints, we typically need:
- If Autodiscover:$true - need EmailAddress
- If Autodiscover:$false - need ExchangeServer and RPCProxyServer (or just RemoteServer?)

Actually, looking at this more carefully, I think the issue is that for `-ExchangeOutlookAnywhere` migrations:
- We need `-ExchangeServer` (not `-RemoteServer`)
- We need `-RPCProxyServer`
- Or we use `-EmailAddress` with `-Autodiscover:$true`

Let me try a different approach. Maybe we should use:
```powershell
New-MigrationEndpoint `
  -ExchangeOutlookAnywhere `
  -Name "Neptune-Heieck" `
  -Autodiscover:$false `
  -ExchangeServer "neptune.acghosting.com" `
  -RPCProxyServer "neptune.acghosting.com" `
  -Credentials $neptuneCred `
  -Authentication Basic
```

But the user already tried this and it failed. Maybe I should consider alternative endpoint types—IMAP would be simpler to configure though it won't preserve server-side rules, or there might be specific requirements for Exchange 2016 migrations I'm missing.


Let me check the available parameter sets for the command. Run this:

```powershell
Get-Help New-MigrationEndpoint -Parameter * | Select-Object Name, Required, ParameterSetName | Format-Table -AutoSize
```

This will show us which parameters work together. However, let me try a different approach - using the EmailAddress parameter for validation:

```powershell
New-MigrationEndpoint `
    -Name "Neptune-Heieck" `
    -ExchangeOutlookAnywhere `
    -Autodiscover:$false `
    -ExchangeServer "neptune.acghosting.com" `
    -RPCProxyServer "neptune.acghosting.com" `
    -Credentials $neptuneCred `
    -EmailAddress "sheila@heieck.org" `
    -Authentication Basic
```

Or alternatively, let's try using autodiscover (which might work since Neptune is publicly accessible):

```powershell
New-MigrationEndpoint `
    -Name "Neptune-Heieck" `
    -ExchangeOutlookAnywhere `
    -Autodiscover:$true `
    -EmailAddress "sheila@heieck.org" `
    -Credentials $neptuneCred
```

If neither works, try checking what Exchange Online actually supports:

```powershell
Get-Command New-MigrationEndpoint -Syntax
```

This will show the exact parameter combinations that are valid.


PS C:\Users\MikeSwanson> Get-Command New-MigrationEndpoint -Syntax

New-MigrationEndpoint -ExchangeRemoteMove -Name <string> -RemoteServer <Object> [-ApplicationId <string>] [-AppSecretKeyVaultUrl <string>] [-Credentials <pscredential>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-RemoteTenant <string>] [-SkipVerification] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -IMAP -Name <string> -RemoteServer <Object> [-AcceptUntrustedCertificates] [-Authentication <Object>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-Port <int>] [-Security <Object>] [-SkipVerification] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Autodiscover -Credentials <pscredential> -EmailAddress <Object> -ExchangeOutlookAnywhere -Name <string> [-AcceptUntrustedCertificates] [-MailboxPermission <Object>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-SkipVerification] [-SourceMailboxLegacyDN <string>] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Credentials <pscredential> -ExchangeOutlookAnywhere -Name <string> [-AcceptUntrustedCertificates] [-Authentication <Object>] [-EmailAddress <Object>] [-ExchangeServer <string>] [-MailboxPermission <Object>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-NspiServer <string>] [-Partition <Object>] [-RPCProxyServer <Object>] [-SkipVerification] [-SourceMailboxLegacyDN <string>] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Credentials <pscredential> -Name <string> -PublicFolderDatabaseServerLegacyDN <string> -PublicFolderToUnifiedGroup -RPCProxyServer <Object> -SourceMailboxLegacyDN <string> [-Authentication <Object>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-SkipVerification] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Credentials <pscredential> -Name <string> -PublicFolder -PublicFolderDatabaseServerLegacyDN <string> -RPCProxyServer <Object> -SourceMailboxLegacyDN <string> [-Authentication <Object>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-SkipVerification] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Autodiscover -Credentials <pscredential> -EmailAddress <Object> -ExchangeRemoteMove -Name <string> [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-SkipVerification] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Compliance -Credentials <pscredential> -Name <string> -RemoteServer <Object> [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-SkipVerification] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Credentials <pscredential> -Name <string> -PublicFolderToUnifiedGroup -RemoteServer <Object> [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-SkipVerification] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Credentials <pscredential> -Name <string> -PublicFolder -RemoteServer <Object> [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-SkipVerification] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Name <string> -RemoteServer <Object> [-Credentials <pscredential>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-SkipVerification] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Gmail -Name <string> -ServiceAccountKeyFileData <byte[]> [-EmailAddress <Object>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-SkipVerification] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]

New-MigrationEndpoint -Gmail -Name <string> -OAuthCode <securestring> [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-Partition <Object>] [-RedirectUri <string>] [-SkipVerification] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]

PS C:\Users\MikeSwanson>

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


Perfect! Now I can see the exact parameter sets. Looking at the syntax, for ExchangeOutlookAnywhere without autodiscover, the correct syntax is:

```
New-MigrationEndpoint -Credentials <pscredential> -ExchangeOutlookAnywhere -Name <string> [-AcceptUntrustedCertificates] [-Authentication <Object>] [-EmailAddress <Object>] [-ExchangeServer <string>] [-MailboxPermission <Object>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-NspiServer <string>] [-Partition <Object>] [-RPCProxyServer <Object>] [-SkipVerification] [-SourceMailboxLegacyDN <string>] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]
```

The issue is that when you use `-ExchangeOutlookAnywhere`, you MUST include BOTH `-ExchangeServer` AND `-RPCProxyServer`. Let me also check if we need `-Autodiscover:$false` - actually, looking at the syntax, there's no `-Autodiscover:$false` parameter in this parameter set. The `-Autodiscover` switch only appears in specific parameter sets.

So the correct command should be:

```powershell
New-MigrationEndpoint `
    -Name "Neptune-Heieck" `
    -ExchangeOutlookAnywhere `
    -Credentials $neptuneCred `
    -ExchangeServer "neptune.acghosting.com" `
    -RPCProxyServer "neptune.acghosting.com" `
    -Authentication Basic
```

Wait, looking more carefully, I notice that the parameter set shows `[-Authentication <Object>]` which means it's optional. Let me also note that `-EmailAddress` is optional in this parameter set.

Actually, there's an alternative approach using the `-Autodiscover` parameter with `-EmailAddress`, which might be simpler since it doesn't require specifying the server details manually. I should test both methods to see which one works better for this scenario.


Perfect! Now I can see the exact parameter sets. For ExchangeOutlookAnywhere, we need to use the correct combination. Let's try the autodiscover version first since it's simpler:

```powershell
New-MigrationEndpoint `
    -Name "Neptune-Heieck" `
    -ExchangeOutlookAnywhere `
    -Autodiscover `
    -Credentials $neptuneCred `
    -EmailAddress "sheila@heieck.org"
```

If that doesn't work (autodiscover might fail), use the manual version with BOTH ExchangeServer AND RPCProxyServer:

```powershell
New-MigrationEndpoint `
    -Name "Neptune-Heieck" `
    -ExchangeOutlookAnywhere `
    -Credentials $neptuneCred `
    -ExchangeServer "neptune.acghosting.com" `
    -RPCProxyServer "neptune.acghosting.com" `
    -Authentication Basic
```

Notice I removed `-Autodiscover:$false` because that parameter doesn't exist in the manual parameter set - you either use the `-Autodiscover` switch (for the autodiscover parameter set) or you don't use it at all (for the manual parameter set).

Try the first command (with autodiscover). If Neptune's autodiscover is properly configured, it should work automatically.


Write-ErrorMessage : ||When manually discovering the migration endpoint, you must specify the Legacy DN or the email
address of a mailbox in the source domain if the SkipVerification parameter isn't specified.
At C:\Users\MikeSwanson\AppData\Local\Temp\tmpEXO_bvelnrng.k2l\tmpEXO_bvelnrng.k2l.psm1:1191 char:13
+             Write-ErrorMessage $ErrorObject
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-MigrationEndpoint], MigrationPermanentException
    + FullyQualifiedErrorId : [Server=SJ0PR10MB4447,RequestId=17df4b65-d44c-36b6-5cf8-7e2e9efa5e5f,TimeStamp=Wed, 14 J
   an 2026 17:54:30 GMT],Write-ErrorMessage

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


The error says we need to either:
1. Specify the Legacy DN or email address of a mailbox in the source domain
2. Use -SkipVerification parameter

Looking at the syntax again, for the manual ExchangeOutlookAnywhere parameter set:
```
New-MigrationEndpoint -Credentials <pscredential> -ExchangeOutlookAnywhere -Name <string> [-AcceptUntrustedCertificates] [-Authentication <Object>] [-EmailAddress <Object>] [-ExchangeServer <string>] [-MailboxPermission <Object>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-NspiServer <string>] [-Partition <Object>] [-RPCProxyServer <Object>] [-SkipVerification] [-SourceMailboxLegacyDN <string>] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]
```

So we need to add either:
- `-EmailAddress "sheila@heieck.org"`
- `-SourceMailboxLegacyDN` (but we don't have that)
- `-SkipVerification`

Let me add the EmailAddress parameter.


Good! Now we need to add the `-EmailAddress` parameter for verification. Try this:

```powershell
New-MigrationEndpoint `
    -Name "Neptune-Heieck" `
    -ExchangeOutlookAnywhere `
    -Credentials $neptuneCred `
    -ExchangeServer "neptune.acghosting.com" `
    -RPCProxyServer "neptune.acghosting.com" `
    -EmailAddress "sheila@heieck.org" `
    -Authentication Basic
```

The `-EmailAddress` parameter tells Exchange Online to test connectivity by verifying that mailbox exists on the source server.

If it still has issues connecting (maybe SSL certificate problems), you can add:

```powershell
New-MigrationEndpoint `
    -Name "Neptune-Heieck" `
    -ExchangeOutlookAnywhere `
    -Credentials $neptuneCred `
    -ExchangeServer "neptune.acghosting.com" `
    -RPCProxyServer "neptune.acghosting.com" `
    -EmailAddress "sheila@heieck.org" `
    -Authentication Basic `
    -AcceptUntrustedCertificates
```

Try the first command first. This should create the migration endpoint successfully.


PS C:\Users\MikeSwanson>   New-MigrationEndpoint `
>>       -Name "Neptune-Heieck" `
>>       -ExchangeOutlookAnywhere `
>>       -Credentials $neptuneCred `
>>       -ExchangeServer "neptune.acghosting.com" `
>>       -RPCProxyServer "neptune.acghosting.com" `
>>       -EmailAddress "sheila@heieck.org" `
>>       -Authentication Basic
Write-ErrorMessage : ||Unable to determine the MailboxPermission for this endpoint because we couldn't connect to the
source mailbox.
At C:\Users\MikeSwanson\AppData\Local\Temp\tmpEXO_bvelnrng.k2l\tmpEXO_bvelnrng.k2l.psm1:1191 char:13
+             Write-ErrorMessage $ErrorObject
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-MigrationEndpoint], UnableToDiscove...issionException
    + FullyQualifiedErrorId : [Server=SJ0PR10MB4447,RequestId=b6fce7ab-2c69-c40d-56e8-99ec7557464a,TimeStamp=Wed, 14 J
   an 2026 17:55:16 GMT],Write-ErrorMessage

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


The error says it can't connect to the source mailbox. This could be because:
1. SSL certificate issues
2. The RPC proxy isn't accessible from Microsoft's servers
3. Authentication issues
4. Port/firewall issues

Let me try adding `-AcceptUntrustedCertificates` and also `-SkipVerification` to bypass the connectivity test.


The connection is failing. Let's try with `-AcceptUntrustedCertificates` and `-SkipVerification` to bypass the connectivity test:

```powershell
New-MigrationEndpoint `
    -Name "Neptune-Heieck" `
    -ExchangeOutlookAnywhere `
    -Credentials $neptuneCred `
    -ExchangeServer "neptune.acghosting.com" `
    -RPCProxyServer "neptune.acghosting.com" `
    -EmailAddress "sheila@heieck.org" `
    -Authentication Basic `
    -AcceptUntrustedCertificates `
    -SkipVerification
```

The `-SkipVerification` flag will create the endpoint without testing connectivity first. The actual migration will test the connection when it starts.

However, if this works but the migration itself fails to connect, we might need to check if Neptune's Outlook Anywhere (RPC over HTTPS) is properly configured and accessible from the internet. Can you verify that users can currently connect to Neptune using Outlook from outside the network?


PS C:\Users\MikeSwanson>   New-MigrationEndpoint `
>>       -Name "Neptune-Heieck" `
>>       -ExchangeOutlookAnywhere `
>>       -Credentials $neptuneCred `
>>       -ExchangeServer "neptune.acghosting.com" `
>>       -RPCProxyServer "neptune.acghosting.com" `
>>       -EmailAddress "sheila@heieck.org" `
>>       -Authentication Basic `
>>       -AcceptUntrustedCertificates `
>>       -SkipVerification
Write-ErrorMessage : ||Unable to determine the MailboxPermission for this endpoint because we couldn't connect to the
source mailbox.
At C:\Users\MikeSwanson\AppData\Local\Temp\tmpEXO_bvelnrng.k2l\tmpEXO_bvelnrng.k2l.psm1:1191 char:13
+             Write-ErrorMessage $ErrorObject
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-MigrationEndpoint], UnableToDiscove...issionException
    + FullyQualifiedErrorId : [Server=SJ0PR10MB4447,RequestId=9fb565c2-8be8-d93e-6bb2-b5eed1f85aa7,TimeStamp=Wed, 14 J
   an 2026 17:56:00 GMT],Write-ErrorMessage

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


The endpoint creation is still failing even with SkipVerification. The error says "Unable to determine the MailboxPermission for this endpoint because we couldn't connect to the source mailbox."

This suggests that Exchange Online is still trying to connect to Neptune even with SkipVerification, and it's failing. This could be because:

1. Outlook Anywhere (RPC over HTTPS) might not be properly configured on Neptune
2. Neptune might not be accessible from the internet for Outlook Anywhere
3. The mailbox permission needs to be explicitly specified

Looking at the syntax again:
```
New-MigrationEndpoint -Credentials <pscredential> -ExchangeOutlookAnywhere -Name <string> [-AcceptUntrustedCertificates] [-Authentication <Object>] [-EmailAddress <Object>] [-ExchangeServer <string>] [-MailboxPermission <Object>] [-MaxConcurrentIncrementalSyncs <Object>] [-MaxConcurrentMigrations <Object>] [-NspiServer <string>] [-Partition <Object>] [-RPCProxyServer <Object>] [-SkipVerification] [-SourceMailboxLegacyDN <string>] [-TestMailbox <Object>] [-WhatIf] [-Confirm] [<CommonParameters>]
```

I see there's a `-MailboxPermission` parameter. Maybe we need to explicitly specify that.

Also, I notice there's an IMAP option. Since we can't seem to get Outlook Anywhere working, we could try IMAP migration instead if Neptune has IMAP enabled.

Let me try specifying the MailboxPermission parameter explicitly, and if that doesn't work, we should investigate whether IMAP is available, or whether we need to do PST export/import instead.


The endpoint creation is still failing. This suggests Neptune's Outlook Anywhere might not be properly configured for external access. Let's try specifying the `-MailboxPermission` parameter explicitly:

```powershell
New-MigrationEndpoint `
    -Name "Neptune-Heieck" `
    -ExchangeOutlookAnywhere `
    -Credentials $neptuneCred `
    -ExchangeServer "neptune.acghosting.com" `
    -RPCProxyServer "neptune.acghosting.com" `
    -EmailAddress "sheila@heieck.org" `
    -Authentication Basic `
    -MailboxPermission Admin `
    -AcceptUntrustedCertificates `
    -SkipVerification
```

If this still fails, we have two alternatives:

**Option A: Check if IMAP is enabled on Neptune** (easier migration):
```powershell
# Connect to Neptune and check
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://neptune.acghosting.com/PowerShell/' -Authentication Basic -Credential $neptuneCred -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)
Invoke-Command -Session $session -ScriptBlock { Get-ImapSettings -Server NEPTUNE }
```

**Option B: PST Export/Import method** (more manual but reliable):
1. Export mailboxes from Neptune to PST files
2. Upload PSTs to Azure
3. Import to Microsoft 365 mailboxes

Try the MailboxPermission command first. If that doesn't work, let me know and we'll check IMAP or proceed with PST export.


PS C:\Users\MikeSwanson>   New-MigrationEndpoint `
>>       -Name "Neptune-Heieck" `
>>       -ExchangeOutlookAnywhere `
>>       -Credentials $neptuneCred `
>>       -ExchangeServer "neptune.acghosting.com" `
>>       -RPCProxyServer "neptune.acghosting.com" `
>>       -EmailAddress "sheila@heieck.org" `
>>       -Authentication Basic `
>>       -MailboxPermission Admin `
>>       -AcceptUntrustedCertificates `
>>       -SkipVerification

Identity       EndpointType            RemoteServer
--------       ------------            ------------
Neptune-Heieck ExchangeOutlookAnywhere

PS C:\Users\MikeSwanson>

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


Excellent! The migration endpoint was created successfully! Now I need to update the todo list to mark that task as completed and move on to creating the migration batch.


Perfect! The migration endpoint was created successfully! Now let's create the migration batch to start moving the mailboxes.


TodoWrite

Gather Neptune Exchange server details and credentials

Gathering Neptune Exchange server details

Access Neptune via VPN for internal management

Assess mailbox sizes and user count for migration planning

Create Microsoft 365 mailboxes for heieck.org users

Create Exchange Online migration endpoint

Creating Exchange Online migration endpoint

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


Great! Now I need to create the migration batch. Let me run the script I created earlier or create the commands directly.


Now let's create and start the migration batch:

```powershell
# Create CSV data for the two mailboxes
$csvData = @"
EmailAddress
sheila@heieck.org
jjh@heieck.org
"@

$csvBytes = [System.Text.Encoding]::UTF8.GetBytes($csvData)

# Get the target delivery domain (*.onmicrosoft.com)
$domains = Get-AcceptedDomain
$targetDomain = ($domains | Where-Object { $_.DomainName -like "*.onmicrosoft.com" }).DomainName

Write-Host "Target delivery domain: $targetDomain"

# Create the migration batch
$batchName = "Heieck-$(Get-Date -Format 'yyyyMMdd-HHmm')"

New-MigrationBatch `
    -Name $batchName `
    -SourceEndpoint "Neptune-Heieck" `
    -CSVData $csvBytes `
    -TargetDeliveryDomain $targetDomain `
    -AutoStart `
    -AutoComplete

Write-Host "`nMigration batch '$batchName' created and started!"
Write-Host "`nCheck status with:"
Write-Host "Get-MigrationBatch -Identity '$batchName' | Format-List"
Write-Host "Get-MigrationUser -BatchId '$batchName' | Format-Table Identity, Status, ItemsTransferred, PercentageComplete"
```

This will:
1. Create a migration batch for both mailboxes
2. Automatically start the migration
3. Automatically complete when done (no manual finalization needed)

Run this command and let me know the result!


S C:\Users\MikeSwanson>   # Create CSV data for the two mailboxes
PS C:\Users\MikeSwanson>   $domains = Get-AcceptedDomain
PS C:\Users\MikeSwanson>   $targetDomain = ($domains | Where-Object { $_.DomainName -like "*.onmicrosoft.com" }).DomainName
PS C:\Users\MikeSwanson>
PS C:\Users\MikeSwanson>   Write-Host "Target delivery domain: $targetDomain"
Target delivery domain: heieckorg.onmicrosoft.com
PS C:\Users\MikeSwanson>
PS C:\Users\MikeSwanson>   # Create the migration batch
PS C:\Users\MikeSwanson>   $batchName = "Heieck-$(Get-Date -Format 'yyyyMMdd-HHmm')"
PS C:\Users\MikeSwanson>
PS C:\Users\MikeSwanson>   New-MigrationBatch `
>>       -Name $batchName `
>>       -SourceEndpoint "Neptune-Heieck" `
>>       -CSVData $csvBytes `
>>       -TargetDeliveryDomain $targetDomain `
>>       -AutoStart `
>>       -AutoComplete
New-MigrationBatch : Cannot bind argument to parameter 'CSVData' because it is null.
At line:4 char:16
+       -CSVData $csvBytes `
+                ~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [New-MigrationBatch], ParameterBindingValidationExcept
   ion
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,New-MigrationBatch

PS C:\Users\MikeSwanson>
PS C:\Users\MikeSwanson>   Write-Host "`nMigration batch '$batchName' created and started!"

Migration batch 'Heieck-20260114-1058' created and started!
PS C:\Users\MikeSwanson>   Write-Host "`nCheck status with:"

Check status with:
PS C:\Users\MikeSwanson>   Write-Host "Get-MigrationBatch -Identity '$batchName' | Format-List"
Get-MigrationBatch -Identity 'Heieck-20260114-1058' | Format-List
PS C:\Users\MikeSwanson>   Write-Host "Get-MigrationUser -BatchId '$batchName' | Format-Table Identity, Status,
>>   ItemsTransferred, PercentageComplete"
Get-MigrationUser -BatchId 'Heieck-20260114-1058' | Format-Table Identity, Status,
  ItemsTransferred, PercentageComplete
PS C:\Users\MikeSwanson>

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


The user didn't run the CSV creation part - they only ran the second half of my command. The $csvBytes variable was null because they skipped this part:

```powershell
$csvData = @"
EmailAddress
sheila@heieck.org
jjh@heieck.org
"@

$csvBytes = [System.Text.Encoding]::UTF8.GetBytes($csvData)
```

So the New-MigrationBatch command failed because $csvBytes was null. I need to give them the complete command again, all together.


You need to create the CSV data first. The $csvBytes variable was null because that part didn't run. Run this complete command:

```powershell
# Create CSV data for the two mailboxes
$csvData = @"
EmailAddress
sheila@heieck.org
jjh@heieck.org
"@

$csvBytes = [System.Text.Encoding]::UTF8.GetBytes($csvData)

# Get the target delivery domain
$domains = Get-AcceptedDomain
$targetDomain = ($domains | Where-Object { $_.DomainName -like "*.onmicrosoft.com" }).DomainName

Write-Host "Target delivery domain: $targetDomain"

# Create the migration batch
$batchName = "Heieck-$(Get-Date -Format 'yyyyMMdd-HHmm')"

New-MigrationBatch `
    -Name $batchName `
    -SourceEndpoint "Neptune-Heieck" `
    -CSVData $csvBytes `
    -TargetDeliveryDomain $targetDomain `
    -AutoStart `
    -AutoComplete

Write-Host "`nMigration batch '$batchName' created and started!"
Write-Host "`nCheck status with:"
Write-Host "Get-MigrationBatch -Identity '$batchName' | Format-List"
Write-Host "Get-MigrationUser -BatchId '$batchName' | Format-Table Identity, Status, ItemsTransferred, PercentageComplete"
```

Copy and paste the entire block at once to ensure all variables are set correctly.


PS C:\Users\MikeSwanson>   Write-Host "Get-MigrationUser -BatchId '$batchName' | Format-Table Identity, Status,
>>   ItemsTransferred, PercentageComplete"
Get-MigrationUser -BatchId 'Heieck-20260114-1058' | Format-Table Identity, Status,
  ItemsTransferred, PercentageComplete
PS C:\Users\MikeSwanson>   # Create CSV data for the two mailboxes
PS C:\Users\MikeSwanson>   $csvData = @"
>>   EmailAddress
>>   sheila@heieck.org
>>   jjh@heieck.org
>>   "@
>>
>>   $csvBytes = [System.Text.Encoding]::UTF8.GetBytes($csvData)
>>
>>   # Get the target delivery domain
>>   $domains = Get-AcceptedDomain
>>   $targetDomain = ($domains | Where-Object { $_.DomainName -like "*.onmicrosoft.com" }).DomainName
>>
>>   Write-Host "Target delivery domain: $targetDomain"
>>
>>   # Create the migration batch
>>   $batchName = "Heieck-$(Get-Date -Format 'yyyyMMdd-HHmm')"
>>
>>   New-MigrationBatch `
>>       -Name $batchName `
>>       -SourceEndpoint "Neptune-Heieck" `
>>       -CSVData $csvBytes `
>>       -TargetDeliveryDomain $targetDomain `
>>       -AutoStart `
>>       -AutoComplete
>>
>>   Write-Host "`nMigration batch '$batchName' created and started!"
>>   Write-Host "`nCheck status with:"
>>   Write-Host "Get-MigrationBatch -Identity '$batchName' | Format-List"
>>   Write-Host "Get-MigrationUser -BatchId '$batchName' | Format-Table Identity, Status,
>>   ItemsTransferred, PercentageComplete"
>>
>>
>>
>>

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


The user pasted the command but it seems like it's just sitting there waiting for more input. The PowerShell prompt hasn't returned yet. They might need to press Enter to execute the command block, or there might be an issue with the here-string formatting.

Let me wait to see what output they get. Actually, looking at the prompt, it seems like PowerShell is waiting for more input (the >> prompt continues). They need to press Enter to execute the command block.


It looks like PowerShell is waiting for more input (the `>>` prompt). Press **Enter** one more time to execute the command block.

If it still doesn't execute, press **Ctrl+C** to cancel, then try this simplified version:

```powershell
$csvData = "EmailAddress`nsheila@heieck.org`njjh@heieck.org"
$csvBytes = [System.Text.Encoding]::UTF8.GetBytes($csvData)
$batchName = "Heieck-$(Get-Date -Format 'yyyyMMdd-HHmm')"

New-MigrationBatch -Name $batchName -SourceEndpoint "Neptune-Heieck" -CSVData $csvBytes -TargetDeliveryDomain "heieckorg.onmicrosoft.com" -AutoStart -AutoComplete

Get-MigrationBatch -Identity $batchName | Format-List
```

This should create the migration batch and start moving the mailboxes from Neptune to Microsoft 365.


PS C:\Users\MikeSwanson> $csvData = "EmailAddress`nsheila@heieck.org`njjh@heieck.org"
PS C:\Users\MikeSwanson>   $csvBytes = [System.Text.Encoding]::UTF8.GetBytes($csvData)
PS C:\Users\MikeSwanson>   $batchName = "Heieck-$(Get-Date -Format 'yyyyMMdd-HHmm')"
PS C:\Users\MikeSwanson>
PS C:\Users\MikeSwanson>   New-MigrationBatch -Name $batchName -SourceEndpoint "Neptune-Heieck" -CSVData $csvBytes
Write-ErrorMessage : ||Staged OutlookAnywhere migration is deprecated. If your organization is
hybrid, you can use Hybrid Remote onboarding. If your organization is non-hybrid, you can use
Exchange Cutover onboarding.
At C:\Users\MikeSwanson\AppData\Local\Temp\tmpEXO_bvelnrng.k2l\tmpEXO_bvelnrng.k2l.psm1:1191 char:13
+             Write-ErrorMessage $ErrorObject
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-MigrationBatch], StagedOutlookAn...portedExcepti
   on
    + FullyQualifiedErrorId : [Server=SJ0PR10MB4447,RequestId=a4a3974a-e568-66ff-fe7f-90e6361a8614,Ti
   meStamp=Wed, 14 Jan 2026 18:00:06 GMT],Write-ErrorMessage

PS C:\Users\MikeSwanson>   -TargetDeliveryDomain "heieckorg.onmicrosoft.com" -AutoStart -AutoComplete
-TargetDeliveryDomain : The term '-TargetDeliveryDomain' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At line:1 char:3
+   -TargetDeliveryDomain "heieckorg.onmicrosoft.com" -AutoStart -AutoC ...
+   ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (-TargetDeliveryDomain:String) [], CommandNotFoundExcep
   tion
    + FullyQualifiedErrorId : CommandNotFoundException

PS C:\Users\MikeSwanson>
PS C:\Users\MikeSwanson>   Get-MigrationBatch -Identity $batchName | Format-List
Write-ErrorMessage : ||The migration batch "Heieck-20260114-1100" can't be found.
At C:\Users\MikeSwanson\AppData\Local\Temp\tmpEXO_bvelnrng.k2l\tmpEXO_bvelnrng.k2l.psm1:1191 char:13
+             Write-ErrorMessage $ErrorObject
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-MigrationBatch], ManagementObjectNotFoundExcepti
   on
    + FullyQualifiedErrorId : [Server=SJ0PR10MB4447,RequestId=ecb2d3d3-d589-237a-2bea-e495ae92c518,Ti
   meStamp=Wed, 14 Jan 2026 18:00:08 GMT],Write-ErrorMessage

PS C:\Users\MikeSwanson>

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


Ah! The error message is very clear: "Staged OutlookAnywhere migration is deprecated. If your organization is hybrid, you can use Hybrid Remote onboarding. If your organization is non-hybrid, you can use Exchange Cutover onboarding."

So the issue is that we're trying to create a staged migration, but Microsoft has deprecated staged migrations for Outlook Anywhere endpoints. We need to use either:
1. Cutover migration (for non-hybrid, which this is)
2. Hybrid migration (if it were a hybrid setup)

For a cutover migration with only 2 mailboxes, we should use the `-Cutover` parameter instead of specifying a source endpoint. Let me check the syntax for cutover migrations.

Actually, looking at the syntax we got earlier, there was no `-Cutover` parameter shown. Let me think about this...

For a cutover migration from on-premises Exchange to Exchange Online, we typically don't use a migration endpoint at all for small batches. We can use IMAP migration instead, or we can try to do a proper cutover migration.

Actually, I think the issue is that cutover migrations work differently. Let me provide the correct approach.

For a cutover migration (moving all mailboxes from on-premises to cloud), the command is different. We might need to delete the endpoint and recreate it, or we might need to use IMAP instead.

Let me suggest using IMAP migration as an alternative, which is simpler and more reliable for small migrations like this.


The error shows that staged Outlook Anywhere migrations are deprecated. For a small migration like this (only 2 mailboxes), we should use either a **Cutover migration** or **IMAP migration**.

Since we only have 2 mailboxes and the Outlook Anywhere approach is deprecated, let's use **IMAP migration** which is simpler and more reliable for small migrations.

First, let's check if IMAP is enabled on Neptune:


Write

# Check if IMAP is enabled on Neptune Exchange
$cred = New-Object System.Management.Automation.PSCredential ('ACG\administrator', (ConvertTo-SecureString 'Gptf*77ttb##' -AsPlainText -Force))
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck

Write-Host "Connecting to Neptune Exchange..." -ForegroundColor Cyan
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://neptune.acghosting.com/PowerShell/' -Authentication Basic -Credential $cred -SessionOption $sessionOption

Write-Host "Checking IMAP settings..." -ForegroundColor Cyan
$imapSettings = Invoke-Command -Session $session -ScriptBlock {
    Get-ImapSettings -Server NEPTUNE | Select-Object Server, ProtocolLogEnabled, UnencryptedOrTLSBindings, SSLBindings
}

$imapSettings | Format-List

Write-Host "`nChecking if IMAP is enabled for mailboxes..." -ForegroundColor Cyan
$mailboxes = Invoke-Command -Session $session -ScriptBlock {
    Get-CASMailbox sheila@heieck.org, jjh@heieck.org | Select-Object DisplayName, ImapEnabled
}

$mailboxes | Format-Table -AutoSize

Remove-PSSession $session
Write-Host "`nDone" -ForegroundColor Green


File created successfully at: C:\Users\MikeSwanson\AppData\Local\Temp\check-neptune-imap.ps1

# Check if IMAP is enabled on Neptune Exchange
$cred = New-Object System.Management.Automation.PSCredential ('ACG\administrator', (ConvertTo-SecureString 'Gptf*77ttb##' -AsPlainText -Force))
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck

Write-Host "Connecting to Neptune Exchange..." -ForegroundColor Cyan
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://neptune.acghosting.com/PowerShell/' -Authentication Basic -Credential $cred -SessionOption $sessionOption

Write-Host "Checking IMAP settings..." -ForegroundColor Cyan
$imapSettings = Invoke-Command -Session $session -ScriptBlock {
    Get-ImapSettings -Server NEPTUNE | Select-Object Server, ProtocolLogEnabled, UnencryptedOrTLSBindings, SSLBindings
}

$imapSettings | Format-List

Write-Host "`nChecking if IMAP is enabled for mailboxes..." -ForegroundColor Cyan
$mailboxes = Invoke-Command -Session $session -ScriptBlock {
    Get-CASMailbox sheila@heieck.org, jjh@heieck.org | Select-Object DisplayName, ImapEnabled
}

$mailboxes | Format-Table -AutoSize

Remove-PSSession $session
Write-Host "`nDone" -ForegroundColor Green


Let me have the user run this script to check if IMAP is enabled on Neptune. If IMAP is enabled, we can create an IMAP migration endpoint instead, which is much simpler and still supported by Microsoft.


Bash

powershell.exe -ExecutionPolicy Bypass -File "C:\Users\MikeSwanson\AppData\Local\Temp\check-neptune-imap.ps1"

Check if IMAP is enabled on Neptune Exchange


Connecting to Neptune Exchange...
Checking IMAP settings...

Server                   : NEPTUNE
ProtocolLogEnabled       : False
UnencryptedOrTLSBindings : {[::]:143, 0.0.0.0:143}
SSLBindings              : {[::]:993, 0.0.0.0:993}
PSComputerName           : neptune.acghosting.com
RunspaceId               : 22417183-c607-43a2-854b-fa36ae6eb85b

Checking if IMAP is enabled for mailboxes...

Done
Cannot process argument transformation on parameter 'Identity'. Cannot convert the "System.Collections.ArrayList"
value of type "System.Collections.ArrayList" to type "Microsoft.Exchange.Configuration.Tasks.MailboxIdParameter".
    + CategoryInfo          : InvalidData: (:) [Get-CASMailbox], ParameterBindin...mationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-CASMailbox
    + PSComputerName        : neptune.acghosting.com


[Request interrupted by user]


Imap won't get calendar/contacts, will it?

Gather Neptune Exchange server details and credentials

Access Neptune via VPN for internal management

Assess mailbox sizes and user count for migration planning

Create Microsoft 365 mailboxes for heieck.org users

Create Exchange Online migration endpoint

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


The user is asking about IMAP limitations. They're right - IMAP only migrates email, not calendar or contacts. For a full migration including calendar and contacts, we need a different approach.

Let me think about the options:
1. IMAP - only email
2. PST export/import - includes everything (email, calendar, contacts)
3. Third-party migration tools
4. Manual Outlook setup with both accounts

Since this is only 2 mailboxes with a total of about 3GB, the PST export/import method is probably the most practical. We can:
1. Export mailboxes from Neptune to PST files
2. Upload PSTs to Azure for import
3. Microsoft 365 will import everything

Let me provide this information to the user.


You're absolutely right - IMAP only migrates email, not calendar or contacts. For a complete migration including everything, we have better options:

**Best option for 2 mailboxes (3GB total): PST Export/Import**

This will migrate:
- All emails
- Calendar items
- Contacts
- Tasks
- Notes

Here's the process:

**Step 1: Export from Neptune to PST files**
```powershell
# Connect to Neptune
$cred = New-Object PSCredential('ACG\administrator', (ConvertTo-SecureString 'Gptf*77ttb##' -AsPlainText -Force))
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://neptune.acghosting.com/PowerShell/' -Authentication Basic -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)
Import-PSSession $session

# Export mailboxes to PST
New-MailboxExportRequest -Mailbox "sheila@heieck.org" -FilePath "\\neptune\PST_Export\sheila.pst"
New-MailboxExportRequest -Mailbox "jjh@heieck.org" -FilePath "\\neptune\PST_Export\jjh.pst"
```

**Step 2: Upload PSTs to Azure and import to Microsoft 365**

Or would you prefer a simpler approach: Have the users run Outlook with both accounts connected temporarily, and let Outlook sync everything to Microsoft 365? That's often the easiest for small migrations.

Which approach would you like to use?


What about just exporting the PSTs from neptune and importing them?

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


The user is asking about exporting PSTs from Neptune and importing them directly. This is a good approach - simpler than going through Azure. Let me outline the process:

1. Export PSTs from Neptune Exchange
2. Download the PST files locally
3. Import them to Microsoft 365 mailboxes

This is definitely doable and avoids the complexity of Azure upload. Let me provide the steps.


Yes, that's exactly what I'm suggesting! Here's the straightforward process:

**Step 1: Export PSTs from Neptune**

```powershell
# Connect to Neptune
$cred = New-Object PSCredential('ACG\administrator', (ConvertTo-SecureString 'Gptf*77ttb##' -AsPlainText -Force))
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://neptune.acghosting.com/PowerShell/' -Authentication Basic -Credential $cred -SessionOption $sessionOption
Import-PSSession $session -DisableNameChecking

# Create export requests (need a network share accessible by Neptune)
New-MailboxExportRequest -Mailbox "sheila@heieck.org" -FilePath "\\neptune\c$\Temp\sheila.pst"
New-MailboxExportRequest -Mailbox "jjh@heieck.org" -FilePath "\\neptune\c$\Temp\jjh.pst"

# Check progress
Get-MailboxExportRequest | Format-Table Name, Status, PercentComplete
```

**Step 2: Download the PSTs** (once exports complete)

Copy them from Neptune to your local machine or a location accessible for import.

**Step 3: Import to Microsoft 365**

Upload PSTs to Azure blob storage, then import via Microsoft 365 admin center (Compliance > Import).

Or for just 2 small mailboxes, the **easiest method**: Have each user:
1. Open Outlook
2. Add their NEW Microsoft 365 account
3. Add their OLD Neptune account (IMAP or Exchange)
4. Drag/drop all folders from old to new

This takes 10 minutes per user and gets everything. Want to go that route, or do the PST export?


They aren't using outlook, OWA only - so we'll need to use the blob

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration


The user confirms they're using OWA only, so we need to do the PST export/import via Azure blob storage. Let me provide the complete process:

1. Export PSTs from Neptune
2. Upload to Azure blob storage
3. Import to Microsoft 365 via the import service

Let me create scripts to help with this process.


Got it. Let's do the PST export and Azure blob import. Here's the complete process:

**Step 1: Export PSTs from Neptune**


Write

# Export mailboxes from Neptune to PST files
$cred = New-Object PSCredential('ACG\administrator', (ConvertTo-SecureString 'Gptf*77ttb##' -AsPlainText -Force))
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck

Write-Host "Connecting to Neptune Exchange..." -ForegroundColor Cyan
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://neptune.acghosting.com/PowerShell/' -Authentication Basic -Credential $cred -SessionOption $sessionOption
Import-PSSession $session -DisableNameChecking -AllowClobber | Out-Null

Write-Host "Connected to Neptune Exchange" -ForegroundColor Green
Write-Host ""

# Create export directory
$exportPath = "C:\Temp\PST_Export"
Write-Host "Creating export directory: $exportPath" -ForegroundColor Cyan
Invoke-Command -Session $session -ScriptBlock {
    param($path)
    if (!(Test-Path $path)) {
        New-Item -Path $path -ItemType Directory -Force | Out-Null
    }
} -ArgumentList $exportPath

Write-Host "Export directory ready" -ForegroundColor Green
Write-Host ""

# Start export requests
Write-Host "Creating export request for sheila@heieck.org..." -ForegroundColor Cyan
New-MailboxExportRequest -Mailbox "sheila@heieck.org" -FilePath "\\neptune\c$\Temp\PST_Export\sheila.pst" -ErrorAction SilentlyContinue

Write-Host "Creating export request for jjh@heieck.org..." -ForegroundColor Cyan
New-MailboxExportRequest -Mailbox "jjh@heieck.org" -FilePath "\\neptune\c$\Temp\PST_Export\jjh.pst" -ErrorAction SilentlyContinue

Write-Host ""
Write-Host "Export requests created!" -ForegroundColor Green
Write-Host ""
Write-Host "Check progress with:" -ForegroundColor Yellow
Write-Host "Get-MailboxExportRequest | Format-Table Name, Status, PercentComplete, BytesTransferred -AutoSize" -ForegroundColor White
Write-Host ""
Write-Host "Files will be saved to: \\neptune\c$\Temp\PST_Export\" -ForegroundColor Gray

Remove-PSSession $session


File created successfully at: C:\Users\MikeSwanson\AppData\Local\Temp\export-neptune-psts.ps1

# Export mailboxes from Neptune to PST files
$cred = New-Object PSCredential('ACG\administrator', (ConvertTo-SecureString 'Gptf*77ttb##' -AsPlainText -Force))
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck

Write-Host "Connecting to Neptune Exchange..." -ForegroundColor Cyan
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://neptune.acghosting.com/PowerShell/' -Authentication Basic -Credential $cred -SessionOption $sessionOption
Import-PSSession $session -DisableNameChecking -AllowClobber | Out-Null

Write-Host "Connected to Neptune Exchange" -ForegroundColor Green
Write-Host ""

# Create export directory
$exportPath = "C:\Temp\PST_Export"
Write-Host "Creating export directory: $exportPath" -ForegroundColor Cyan
Invoke-Command -Session $session -ScriptBlock {
    param($path)
    if (!(Test-Path $path)) {
        New-Item -Path $path -ItemType Directory -Force | Out-Null
    }
} -ArgumentList $exportPath

Write-Host "Export directory ready" -ForegroundColor Green
Write-Host ""

# Start export requests
Write-Host "Creating export request for sheila@heieck.org..." -ForegroundColor Cyan
New-MailboxExportRequest -Mailbox "sheila@heieck.org" -FilePath "\\neptune\c$\Temp\PST_Export\sheila.pst" -ErrorAction SilentlyContinue

Write-Host "Creating export request for jjh@heieck.org..." -ForegroundColor Cyan
New-MailboxExportRequest -Mailbox "jjh@heieck.org" -FilePath "\\neptune\c$\Temp\PST_Export\jjh.pst" -ErrorAction SilentlyContinue

Write-Host ""
Write-Host "Export requests created!" -ForegroundColor Green
Write-Host ""
Write-Host "Check progress with:" -ForegroundColor Yellow
Write-Host "Get-MailboxExportRequest | Format-Table Name, Status, PercentComplete, BytesTransferred -AutoSize" -ForegroundColor White
Write-Host ""
Write-Host "Files will be saved to: \\neptune\c$\Temp\PST_Export\" -ForegroundColor Gray

Remove-PSSession $session


I need to update the todo list to reflect the new approach - PST export/import instead of direct migration batch.


TodoWrite

Gather Neptune Exchange server details and credentials

Gathering Neptune Exchange server details

Access Neptune via VPN for internal management

Assess mailbox sizes and user count for migration planning

Create Microsoft 365 mailboxes for heieck.org users

Export mailboxes from Neptune to PST files

Download PST files from Neptune

Upload PST files to Azure blob storage

Import PST files to Microsoft 365 mailboxes

Verify mailbox data after migration


Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable

Create and start migration batch

Monitor migration progress

Verify mailbox data after migration

Export mailboxes from Neptune to PST files

Download PST files from Neptune

Upload PST files to Azure blob storage

Import PST files to Microsoft 365 mailboxes

Verify mailbox data after migration


Good, I've updated the todo list to reflect the PST export/import approach. Now let me continue with creating the scripts and instructions for the process.


Now let me create the script to help with the Azure blob storage setup:


Write

# Setup Azure Storage for PST Import
# This script helps prepare for PST import to Microsoft 365

Write-Host "=== Microsoft 365 PST Import Setup ===" -ForegroundColor Cyan
Write-Host ""

Write-Host "Step 1: Create Azure Storage Account" -ForegroundColor Yellow
Write-Host "---------------------------------------" -ForegroundColor Gray
Write-Host "1. Go to: https://portal.azure.com"
Write-Host "2. Create a Storage Account (or use existing)"
Write-Host "3. Create a container named 'pstimport'"
Write-Host "4. Generate a SAS token with:"
Write-Host "   - Read, Write, List permissions"
Write-Host "   - Valid for 7 days"
Write-Host ""

Write-Host "Step 2: Upload PST files using AzCopy" -ForegroundColor Yellow
Write-Host "---------------------------------------" -ForegroundColor Gray
Write-Host "Download AzCopy from: https://aka.ms/downloadazcopy"
Write-Host ""
Write-Host "Upload command (replace <SAS-URL> with your SAS token):"
Write-Host "azcopy copy 'C:\Temp\PST_Export\*.pst' '<SAS-URL>' --recursive" -ForegroundColor White
Write-Host ""

Write-Host "Step 3: Create PST Import Job in Microsoft 365" -ForegroundColor Yellow
Write-Host "---------------------------------------" -ForegroundColor Gray
Write-Host "1. Go to: https://compliance.microsoft.com/informationgovernance?viewid=import"
Write-Host "2. Click 'Import' > 'Upload your data'"
Write-Host "3. Choose 'Upload via network'"
Write-Host "4. Provide your Azure Storage SAS URL"
Write-Host "5. Map PST files to mailboxes:"
Write-Host "   sheila.pst -> sheila@heieck.org"
Write-Host "   jjh.pst -> jjh@heieck.org"
Write-Host "6. Start the import job"
Write-Host ""

Write-Host "Alternative: Use Microsoft 365 Import Service" -ForegroundColor Yellow
Write-Host "---------------------------------------" -ForegroundColor Gray
Write-Host "If you have the Security & Compliance PowerShell module:"
Write-Host ""
Write-Host "Connect-IPPSSession" -ForegroundColor White
Write-Host "New-ComplianceSecurityFilter -FilterName 'PST Import'" -ForegroundColor White
Write-Host ""

Write-Host "First, run export-neptune-psts.ps1 to export the mailboxes" -ForegroundColor Green


File created successfully at: C:\Users\MikeSwanson\AppData\Local\Temp\setup-azure-import.ps1

# Setup Azure Storage for PST Import
# This script helps prepare for PST import to Microsoft 365

Write-Host "=== Microsoft 365 PST Import Setup ===" -ForegroundColor Cyan
Write-Host ""

Write-Host "Step 1: Create Azure Storage Account" -ForegroundColor Yellow
Write-Host "---------------------------------------" -ForegroundColor Gray
Write-Host "1. Go to: https://portal.azure.com"
Write-Host "2. Create a Storage Account (or use existing)"
Write-Host "3. Create a container named 'pstimport'"
Write-Host "4. Generate a SAS token with:"
Write-Host "   - Read, Write, List permissions"
Write-Host "   - Valid for 7 days"
Write-Host ""

Write-Host "Step 2: Upload PST files using AzCopy" -ForegroundColor Yellow
Write-Host "---------------------------------------" -ForegroundColor Gray
Write-Host "Download AzCopy from: https://aka.ms/downloadazcopy"
Write-Host ""
Write-Host "Upload command (replace <SAS-URL> with your SAS token):"
Write-Host "azcopy copy 'C:\Temp\PST_Export\*.pst' '<SAS-URL>' --recursive" -ForegroundColor White
Write-Host ""

Write-Host "Step 3: Create PST Import Job in Microsoft 365" -ForegroundColor Yellow
Write-Host "---------------------------------------" -ForegroundColor Gray
Write-Host "1. Go to: https://compliance.microsoft.com/informationgovernance?viewid=import"
Write-Host "2. Click 'Import' > 'Upload your data'"
Write-Host "3. Choose 'Upload via network'"
Write-Host "4. Provide your Azure Storage SAS URL"
Write-Host "5. Map PST files to mailboxes:"
Write-Host "   sheila.pst -> sheila@heieck.org"
Write-Host "   jjh.pst -> jjh@heieck.org"
Write-Host "6. Start the import job"
Write-Host ""

Write-Host "Alternative: Use Microsoft 365 Import Service" -ForegroundColor Yellow
Write-Host "---------------------------------------" -ForegroundColor Gray
Write-Host "If you have the Security & Compliance PowerShell module:"
Write-Host ""
Write-Host "Connect-IPPSSession" -ForegroundColor White
Write-Host "New-ComplianceSecurityFilter -FilterName 'PST Import'" -ForegroundColor White
Write-Host ""

Write-Host "First, run export-neptune-psts.ps1 to export the mailboxes" -ForegroundColor Green


Now let me run the export script to start the PST export process from Neptune.


Let's start the PST export:


Bash

powershell.exe -ExecutionPolicy Bypass -File "C:\Users\MikeSwanson\AppData\Local\Temp\export-neptune-psts.ps1"

Export mailboxes from Neptune to PST files


Connecting to Neptune Exchange...
Connected to Neptune Exchange

Creating export directory: C:\Temp\PST_Export
Export directory ready

Creating export request for sheila@heieck.org...
Creating export request for jjh@heieck.org...

Export requests created!

Check progress with:
Get-MailboxExportRequest | Format-Table Name, Status, PercentComplete, BytesTransferred -AutoSize

Files will be saved to: \\neptune\c$\Temp\PST_Export\
The syntax is not supported by this runspace. This can occur if the runspace is in no-language mode.
    + CategoryInfo          : ParserError: (
    param($pat...Out-Null
    }
:String) [], ParseException
    + FullyQualifiedErrorId : ScriptsNotAllowed
    + PSComputerName        : neptune.acghosting.com


There's a language mode restriction on the Neptune server that prevents running script blocks. Let me try a different approach - create the directory manually and then run the export requests.


The script had an issue with language mode on Neptune. Let me try a simpler approach:


[Request interrupted by user]


Export is already started

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


The user is saying the export is already started, so I don't need to troubleshoot the script error. Let me check the progress of the export requests and provide the next steps.


Great! Let's check the progress of the PST exports:

```powershell
# Reconnect to Neptune and check export status
$cred = New-Object PSCredential('ACG\administrator', (ConvertTo-SecureString 'Gptf*77ttb##' -AsPlainText -Force))
$sessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://neptune.acghosting.com/PowerShell/' -Authentication Basic -Credential $cred -SessionOption $sessionOption
Import-PSSession $session -DisableNameChecking -AllowClobber

# Check export progress
Get-MailboxExportRequest | Format-Table Name, Status, PercentComplete, BytesTransferred -AutoSize
```

Once the exports show **Status: Completed**, you'll need to:

1. **Download the PST files** from `\\neptune\c$\Temp\PST_Export\`
   - sheila.pst (should be ~0.66 GB)
   - jjh.pst (should be ~2.39 GB)

2. **Upload to Azure Storage** using AzCopy

3. **Import to Microsoft 365** via the compliance center

While the exports are running, would you like me to help set up the Azure Storage account and get the AzCopy commands ready?


[PS] C:\Windows\system32>  New-MailboxExportRequest -Mailbox "sheila@heieck.org" -FilePath "\\neptune\c$\Temp\sheila.pst"

Name          Mailbox                                        Status
----          -------                                        ------
MailboxExport acg.local/Hosting/heieck.org/sheila@heieck.org Queued

[PS] C:\Windows\system32>  New-MailboxExportRequest -Mailbox "jjh@heieck.org" -FilePath "\\neptune\c$\Temp\jjh.pst"

Name          Mailbox                                     Status
----          -------                                     ------
MailboxExport acg.local/Hosting/heieck.org/jjh@heieck.org Queued

[PS] C:\Windows\system32>Get-MailboxExportRequest | Format-Table Name, Status, PercentComplete

Name              Status PercentComplete
----              ------ ---------------
MailboxExport InProgress
MailboxExport InProgress

[PS] C:\Windows\system32>Get-MailboxExportRequest | Format-Table Name, Status, PercentComplete

Name              Status PercentComplete
----              ------ ---------------
MailboxExport InProgress
MailboxExport InProgress

[PS] C:\Windows\system32>Get-MailboxExportRequest | Format-Table Name, Status, PercentComplete

Name              Status PercentComplete
----              ------ ---------------
MailboxExport InProgress
MailboxExport InProgress

[PS] C:\Windows\system32>Get-MailboxExportRequest | Format-Table Name, Status, PercentComplete

Name              Status PercentComplete
----              ------ ---------------
MailboxExport InProgress
MailboxExport InProgress

[PS] C:\Windows\system32>

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


The exports are in progress. The user is monitoring them. I should help prepare for the next steps while the exports complete. Let me update the todo list and help set up the Azure blob storage and import process.


Good! Both exports are running. While they complete, let's prepare the Azure Storage and import process.


TodoWrite

Gather Neptune Exchange server details and credentials

Gathering Neptune Exchange server details

Access Neptune via VPN for internal management

Assess mailbox sizes and user count for migration planning

Create Microsoft 365 mailboxes for heieck.org users

Export mailboxes from Neptune to PST files

Download PST files from Neptune

Upload PST files to Azure blob storage

Import PST files to Microsoft 365 mailboxes

Verify mailbox data after migration


Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


The exports are running. I should help prepare the Azure storage setup and create a guide for the import process. Let me create a comprehensive setup guide.


Write

# Microsoft 365 PST Import via Azure Blob Storage
# Complete guide for heieck.org migration

Write-Host "=== PST Import to Microsoft 365 ===" -ForegroundColor Cyan
Write-Host ""
Write-Host "Exports are running on Neptune. When complete:" -ForegroundColor Yellow
Write-Host ""

Write-Host "STEP 1: Download PST files from Neptune" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Gray
Write-Host "Option A - Copy via network share (from your machine):"
Write-Host "  Copy-Item '\\neptune\c$\Temp\sheila.pst' 'C:\Temp\PST_Import\'"
Write-Host "  Copy-Item '\\neptune\c$\Temp\jjh.pst' 'C:\Temp\PST_Import\'"
Write-Host ""
Write-Host "Option B - Copy via RDP to Neptune:"
Write-Host "  RDP to neptune.acghosting.com"
Write-Host "  Copy files from C:\Temp\ to your local machine"
Write-Host ""

Write-Host "STEP 2: Create Azure Storage Account" -ForegroundColor Green
Write-Host "=====================================" -ForegroundColor Gray
Write-Host "1. Go to https://portal.azure.com"
Write-Host "2. Create a Resource Group: 'rg-pst-import' (or use existing)"
Write-Host "3. Create Storage Account:"
Write-Host "   - Name: something like 'heieckpstimport'"
Write-Host "   - Performance: Standard"
Write-Host "   - Redundancy: LRS (cheapest)"
Write-Host "4. Create a container named: 'pstimport'"
Write-Host "5. Generate SAS token for the container:"
Write-Host "   - Permissions: Read, Write, List"
Write-Host "   - Expiry: 7 days from now"
Write-Host "   - Copy the SAS URL"
Write-Host ""

Write-Host "STEP 3: Download and Install AzCopy" -ForegroundColor Green
Write-Host "====================================" -ForegroundColor Gray
Write-Host "Download from: https://aka.ms/downloadazcopy-v10-windows"
Write-Host "Extract to: C:\AzCopy\"
Write-Host ""

Write-Host "STEP 4: Upload PST files to Azure" -ForegroundColor Green
Write-Host "==================================" -ForegroundColor Gray
Write-Host "Run this command (replace <SAS-URL> with your actual SAS URL):"
Write-Host ""
Write-Host 'C:\AzCopy\azcopy.exe copy "C:\Temp\PST_Import\*.pst" "<SAS-URL>" --recursive' -ForegroundColor White
Write-Host ""
Write-Host "Example SAS URL format:"
Write-Host "https://heieckpstimport.blob.core.windows.net/pstimport?sv=2021-06-08&ss=b&srt=sco&sp=rwlc&se=..." -ForegroundColor Gray
Write-Host ""

Write-Host "STEP 5: Create Import Mapping CSV" -ForegroundColor Green
Write-Host "==================================" -ForegroundColor Gray
Write-Host "Create a file named 'import-mapping.csv' with this content:"
Write-Host ""
Write-Host 'Workload,FilePath,Name,Mailbox,IsArchive,TargetRootFolder,ContentCodePage,SPFileContainer,SPManifestContainer,SPSiteUrl' -ForegroundColor White
Write-Host 'Exchange,sheila.pst,sheila,sheila@heieck.org,FALSE,/,,,,' -ForegroundColor White
Write-Host 'Exchange,jjh.pst,jjh,jjh@heieck.org,FALSE,/,,,,' -ForegroundColor White
Write-Host ""

Write-Host "STEP 6: Start Microsoft 365 PST Import" -ForegroundColor Green
Write-Host "=======================================" -ForegroundColor Gray
Write-Host "Method A - Via Compliance Center (Web UI):"
Write-Host "  1. Go to: https://compliance.microsoft.com/informationgovernance?viewid=import"
Write-Host "  2. Click 'Import' > 'Upload your data'"
Write-Host "  3. Choose 'Upload via network'"
Write-Host "  4. Provide SAS URL and upload the mapping CSV"
Write-Host "  5. Start the import job"
Write-Host ""
Write-Host "Method B - Via PowerShell (faster):"
Write-Host "  Connect-IPPSSession -UserPrincipalName admin@heieck.org"
Write-Host "  `$SAS = 'https://heieckpstimport.blob.core.windows.net/pstimport?sv=...'"
Write-Host "  New-ComplianceSearch -Name 'Heieck PST Import' -ExchangeLocation All"
Write-Host ""

Write-Host "MONITORING:" -ForegroundColor Yellow
Write-Host "==========" -ForegroundColor Gray
Write-Host "Check import job status:"
Write-Host "  Get-MailboxImportRequest | Format-Table Name, Mailbox, Status, PercentComplete"
Write-Host ""

Write-Host "When exports complete, check status with:" -ForegroundColor Cyan
Write-Host "Get-MailboxExportRequest | Format-Table Name, Mailbox, Status, PercentComplete, BytesTransferred -AutoSize"


File created successfully at: C:\Users\MikeSwanson\AppData\Local\Temp\azure-pst-import-guide.ps1

# Microsoft 365 PST Import via Azure Blob Storage
# Complete guide for heieck.org migration

Write-Host "=== PST Import to Microsoft 365 ===" -ForegroundColor Cyan
Write-Host ""
Write-Host "Exports are running on Neptune. When complete:" -ForegroundColor Yellow
Write-Host ""

Write-Host "STEP 1: Download PST files from Neptune" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Gray
Write-Host "Option A - Copy via network share (from your machine):"
Write-Host "  Copy-Item '\\neptune\c$\Temp\sheila.pst' 'C:\Temp\PST_Import\'"
Write-Host "  Copy-Item '\\neptune\c$\Temp\jjh.pst' 'C:\Temp\PST_Import\'"
Write-Host ""
Write-Host "Option B - Copy via RDP to Neptune:"
Write-Host "  RDP to neptune.acghosting.com"
Write-Host "  Copy files from C:\Temp\ to your local machine"
Write-Host ""

Write-Host "STEP 2: Create Azure Storage Account" -ForegroundColor Green
Write-Host "=====================================" -ForegroundColor Gray
Write-Host "1. Go to https://portal.azure.com"
Write-Host "2. Create a Resource Group: 'rg-pst-import' (or use existing)"
Write-Host "3. Create Storage Account:"
Write-Host "   - Name: something like 'heieckpstimport'"
Write-Host "   - Performance: Standard"
Write-Host "   - Redundancy: LRS (cheapest)"
Write-Host "4. Create a container named: 'pstimport'"
Write-Host "5. Generate SAS token for the container:"
Write-Host "   - Permissions: Read, Write, List"
Write-Host "   - Expiry: 7 days from now"
Write-Host "   - Copy the SAS URL"
Write-Host ""

Write-Host "STEP 3: Download and Install AzCopy" -ForegroundColor Green
Write-Host "====================================" -ForegroundColor Gray
Write-Host "Download from: https://aka.ms/downloadazcopy-v10-windows"
Write-Host "Extract to: C:\AzCopy\"
Write-Host ""

Write-Host "STEP 4: Upload PST files to Azure" -ForegroundColor Green
Write-Host "==================================" -ForegroundColor Gray
Write-Host "Run this command (replace <SAS-URL> with your actual SAS URL):"
Write-Host ""
Write-Host 'C:\AzCopy\azcopy.exe copy "C:\Temp\PST_Import\*.pst" "<SAS-URL>" --recursive' -ForegroundColor White
Write-Host ""
Write-Host "Example SAS URL format:"
Write-Host "https://heieckpstimport.blob.core.windows.net/pstimport?sv=2021-06-08&ss=b&srt=sco&sp=rwlc&se=..." -ForegroundColor Gray
Write-Host ""

Write-Host "STEP 5: Create Import Mapping CSV" -ForegroundColor Green
Write-Host "==================================" -ForegroundColor Gray
Write-Host "Create a file named 'import-mapping.csv' with this content:"
Write-Host ""
Write-Host 'Workload,FilePath,Name,Mailbox,IsArchive,TargetRootFolder,ContentCodePage,SPFileContainer,SPManifestContainer,SPSiteUrl' -ForegroundColor White
Write-Host 'Exchange,sheila.pst,sheila,sheila@heieck.org,FALSE,/,,,,' -ForegroundColor White
Write-Host 'Exchange,jjh.pst,jjh,jjh@heieck.org,FALSE,/,,,,' -ForegroundColor White
Write-Host ""

Write-Host "STEP 6: Start Microsoft 365 PST Import" -ForegroundColor Green
Write-Host "=======================================" -ForegroundColor Gray
Write-Host "Method A - Via Compliance Center (Web UI):"
Write-Host "  1. Go to: https://compliance.microsoft.com/informationgovernance?viewid=import"
Write-Host "  2. Click 'Import' > 'Upload your data'"
Write-Host "  3. Choose 'Upload via network'"
Write-Host "  4. Provide SAS URL and upload the mapping CSV"
Write-Host "  5. Start the import job"
Write-Host ""
Write-Host "Method B - Via PowerShell (faster):"
Write-Host "  Connect-IPPSSession -UserPrincipalName admin@heieck.org"
Write-Host "  `$SAS = 'https://heieckpstimport.blob.core.windows.net/pstimport?sv=...'"
Write-Host "  New-ComplianceSearch -Name 'Heieck PST Import' -ExchangeLocation All"
Write-Host ""

Write-Host "MONITORING:" -ForegroundColor Yellow
Write-Host "==========" -ForegroundColor Gray
Write-Host "Check import job status:"
Write-Host "  Get-MailboxImportRequest | Format-Table Name, Mailbox, Status, PercentComplete"
Write-Host ""

Write-Host "When exports complete, check status with:" -ForegroundColor Cyan
Write-Host "Get-MailboxExportRequest | Format-Table Name, Mailbox, Status, PercentComplete, BytesTransferred -AutoSize"


I've created a comprehensive guide. Let me also create the CSV mapping file that will be needed for the import.


File created successfully at: C:\Users\MikeSwanson\AppData\Local\Temp\import-mapping.csv


Good. Now let me show the user the guide and next steps.


Perfect! The exports are running. I've created a complete guide for the next steps. Here's what to do:

**Monitor the exports** - Keep checking:
```powershell
Get-MailboxExportRequest | Format-Table Name, Mailbox, Status, PercentComplete, BytesTransferred -AutoSize
```

**When Status shows "Completed"**, here's your process:

**1. Download PST files from Neptune**
```powershell
# Create local directory
New-Item -Path "C:\Temp\PST_Import" -ItemType Directory -Force

# Copy files from Neptune
Copy-Item "\\neptune\c$\Temp\sheila.pst" "C:\Temp\PST_Import\"
Copy-Item "\\neptune\c$\Temp\jjh.pst" "C:\Temp\PST_Import\"
```

**2. Create Azure Storage** (quick steps):
- Go to https://portal.azure.com
- Create Storage Account → Create container named "pstimport"
- Generate SAS token (Read, Write, List permissions, 7 days expiry)

**3. Upload PSTs to Azure** using AzCopy:
- Download AzCopy: https://aka.ms/downloadazcopy-v10-windows
- Upload: `azcopy copy "C:\Temp\PST_Import\*.pst" "<YOUR-SAS-URL>" --recursive`

**4. Import to Microsoft 365**:
- Go to: https://compliance.microsoft.com/informationgovernance?viewid=import
- Use the CSV file I created: `C:\Users\MikeSwanson\AppData\Local\Temp\import-mapping.csv`

View the complete guide:
```powershell
notepad C:\Users\MikeSwanson\AppData\Local\Temp\azure-pst-import-guide.ps1
```

Keep monitoring the exports - they should complete within 10-30 minutes depending on the data.


Do I need to change anything here: Basics
Subscription
Azure subscription 1
Resource group
pstimport
Location
East US
Storage account name
heieckimport
Preferred storage type
Azure Blob Storage or Azure Data Lake Storage Gen 2
Performance
Standard
Replication
Read-access geo-redundant storage (RA-GRS)
Advanced
Enable hierarchical namespace
Disabled
Enable SFTP
Disabled
Enable network file system v3
Disabled
Allow cross-tenant replication
Disabled
Access tier
Hot
Enable large file shares
Enabled
Managed Identity for SMB
Disabled
Security
Secure transfer
Enabled
Blob anonymous access
Disabled
Allow storage account key access
Enabled
Default to Microsoft Entra authorization in the Azure portal
Disabled
Minimum TLS version
Version 1.2
Permitted scope for copy operations (preview)
From any storage account
Networking
Public network access
Enabled
Public network access scope
Enabled from all networks
Default routing tier
Microsoft network routing
Data protection
Point-in-time restore
Disabled
Blob soft delete
Enabled
Blob retainment period in days
7
Container soft delete
Enabled
Container retainment period in days
7
File share soft delete
Enabled
File share retainment period in days
7
Versioning
Disabled
Blob change feed
Disabled
Version-level immutability support
Disabled
Encryption
Encryption type
Microsoft-managed keys (MMK)
Enable support for customer-managed keys
Blobs and files only
Enable infrastructure encryption
Disabled

Gather Neptune Exchange server details and credentials

Access Neptune via VPN for internal management

Assess mailbox sizes and user count for migration planning

Create Microsoft 365 mailboxes for heieck.org users

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


The user is asking if they need to change anything in their Azure Storage Account configuration for PST import. Let me review the settings:

**Current settings:**
- Replication: Read-access geo-redundant storage (RA-GRS)
- Access tier: Hot
- Enable large file shares: Enabled

**What they actually need:**
- For PST import, they don't need geo-redundancy since this is temporary storage
- They could save money with LRS (Locally Redundant Storage)
- Hot tier is fine for active upload/download
- Large file shares don't matter for blob storage

**What should be changed:**
1. **Replication: RA-GRS → LRS** (save money, this is temporary)
2. Everything else looks fine

The configuration is mostly good for PST import. The main thing is the replication - they're paying for geo-redundancy they don't need for a temporary migration storage.


Yes, change these to save money (since this is temporary storage for migration):

**Change:**
- **Replication**: RA-GRS → **LRS (Locally-redundant storage)**
  - RA-GRS is expensive and unnecessary for temporary PST storage
  - LRS is much cheaper and fine for this use case

**Keep everything else as-is.** The current settings are fine:
- Hot tier ✓ (good for active upload/download)
- Public network access enabled ✓ (needed for AzCopy)
- Blob soft delete enabled ✓ (safety net)

**Summary:**
- Current: RA-GRS (4 copies across regions) = expensive
- Change to: LRS (3 copies in one datacenter) = much cheaper
- You'll delete this storage account after the import anyway

Everything else looks good. Create the storage account with LRS replication.


Resource group (move)
:
pstimport
Location
:
eastus
Subscription (move)
:
Azure subscription 1
Subscription ID
:
2aec0ace-b7d3-4b67-adf8-095d777d89a8
Disk state
:
Available
Performance
:
Standard
Replication
:
Locally-redundant storage (LRS)
Account kind
:
StorageV2 (general purpose v2)
Provisioning state
:
Succeeded
Created
:
1/14/2026, 12:10:04 PM

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


The user is showing me the storage account details after creation. It looks good - they changed the replication to LRS as I suggested. Now I need to guide them through:

1. Creating a container named "pstimport"
2. Generating a SAS token for the container
3. Getting ready to upload the PST files once the exports complete

Let me provide clear next steps.


Perfect! Storage account is created with LRS. Now let's create the container and get the SAS token:

**Step 1: Create Container**
1. In the Azure portal, go to your storage account "heieckimport"
2. Click "Containers" in the left menu
3. Click "+ Container"
4. Name: **pstimport**
5. Public access level: Private (no anonymous access)
6. Click "Create"

**Step 2: Generate SAS Token**
1. Click on the "pstimport" container you just created
2. Click "Shared access tokens" in the left menu (or "Generate SAS" button)
3. Configure:
   - **Signing method**: Account key
   - **Permissions**: ✓ Read, ✓ Write, ✓ List
   - **Start time**: Now
   - **Expiry time**: 7 days from now
   - **Allowed protocols**: HTTPS only
4. Click "Generate SAS token and URL"
5. **Copy the "Blob SAS URL"** - you'll need this for AzCopy

Once you have the SAS URL, we'll be ready to upload the PST files as soon as the exports complete.

Keep checking the export status on Neptune:
```powershell
Get-MailboxExportRequest | Format-Table Name, Mailbox, Status, PercentComplete, BytesTransferred -AutoSize
```

What's the current status of the exports?


sp=racwdl&st=2026-01-14T18:57:39Z&se=2026-01-22T03:12:39Z&spr=https&sv=2024-11-04&sr=c&sig=ILD69Ms%2BXO%2BJo2VVYVfsVLiawQpZHnJrGzzrDHJz1Vo%3D

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


The user has provided what appears to be a SAS token with parameters. This is a Shared Access Signature token for Azure Blob Storage. I need to construct the full SAS URL by combining this with the storage account and container information.

The storage account is: heieckimport
The container is: pstimport

So the full SAS URL would be:
https://heieckimport.blob.core.windows.net/pstimport?sp=racwdl&st=2026-01-14T18:57:39Z&se=2026-01-22T03:12:39Z&spr=https&sv=2024-11-04&sr=c&sig=ILD69Ms%2BXO%2BJo2VVYVfsVLiawQpZHnJrGzzrDHJz1Vo%3D

I should create the AzCopy commands ready to use once the PST files are downloaded from Neptune.


Perfect! I have your SAS token. Let me create the complete AzCopy upload commands:


# Upload PST files to Azure Blob Storage
# Run this after downloading PST files from Neptune

$sasUrl = "https://heieckimport.blob.core.windows.net/pstimport?sp=racwdl&st=2026-01-14T18:57:39Z&se=2026-01-22T03:12:39Z&spr=https&sv=2024-11-04&sr=c&sig=ILD69Ms%2BXO%2BJo2VVYVfsVLiawQpZHnJrGzzrDHJz1Vo%3D"

Write-Host "=== Uploading PST files to Azure Blob Storage ===" -ForegroundColor Cyan
Write-Host ""

# Check if PST files exist
$pstPath = "C:\Temp\PST_Import"
if (!(Test-Path $pstPath)) {
    Write-Host "ERROR: PST directory not found: $pstPath" -ForegroundColor Red
    Write-Host "First download PST files from Neptune to C:\Temp\PST_Import\" -ForegroundColor Yellow
    exit 1
}

$pstFiles = Get-ChildItem -Path $pstPath -Filter "*.pst"
if ($pstFiles.Count -eq 0) {
    Write-Host "ERROR: No PST files found in $pstPath" -ForegroundColor Red
    exit 1
}

Write-Host "Found $($pstFiles.Count) PST file(s):" -ForegroundColor Green
foreach ($file in $pstFiles) {
    $sizeMB = [math]::Round($file.Length / 1MB, 2)
    Write-Host "  - $($file.Name) ($sizeMB MB)" -ForegroundColor Gray
}
Write-Host ""

# Check for AzCopy
$azcopyPath = "C:\Program Files\AzCopy\azcopy.exe"
if (!(Test-Path $azcopyPath)) {
    # Try other common locations
    $azcopyPath = "C:\AzCopy\azcopy.exe"
    if (!(Test-Path $azcopyPath)) {
        Write-Host "ERROR: AzCopy not found!" -ForegroundColor Red
        Write-Host "Download from: https://aka.ms/downloadazcopy-v10-windows" -ForegroundColor Yellow
        Write-Host "Extract to C:\AzCopy\ or install to Program Files" -ForegroundColor Yellow
        exit 1
    }
}

Write-Host "Using AzCopy: $azcopyPath" -ForegroundColor Green
Write-Host ""

# Upload files
Write-Host "Uploading PST files to Azure..." -ForegroundColor Cyan
Write-Host "Target: heieckimport/pstimport" -ForegroundColor Gray
Write-Host ""

& $azcopyPath copy "$pstPath\*.pst" $sasUrl --recursive --overwrite=true

if ($LASTEXITCODE -eq 0) {
    Write-Host ""
    Write-Host "Upload completed successfully!" -ForegroundColor Green
    Write-Host ""
    Write-Host "Next step: Create PST Import job in Microsoft 365" -ForegroundColor Yellow
    Write-Host "Go to: https://compliance.microsoft.com/informationgovernance?viewid=import" -ForegroundColor White
} else {
    Write-Host ""
    Write-Host "Upload failed with exit code: $LASTEXITCODE" -ForegroundColor Red
}


File created successfully at: C:\Users\MikeSwanson\AppData\Local\Temp\upload-psts-to-azure.ps1

# Upload PST files to Azure Blob Storage
# Run this after downloading PST files from Neptune

$sasUrl = "https://heieckimport.blob.core.windows.net/pstimport?sp=racwdl&st=2026-01-14T18:57:39Z&se=2026-01-22T03:12:39Z&spr=https&sv=2024-11-04&sr=c&sig=ILD69Ms%2BXO%2BJo2VVYVfsVLiawQpZHnJrGzzrDHJz1Vo%3D"

Write-Host "=== Uploading PST files to Azure Blob Storage ===" -ForegroundColor Cyan
Write-Host ""

# Check if PST files exist
$pstPath = "C:\Temp\PST_Import"
if (!(Test-Path $pstPath)) {
    Write-Host "ERROR: PST directory not found: $pstPath" -ForegroundColor Red
    Write-Host "First download PST files from Neptune to C:\Temp\PST_Import\" -ForegroundColor Yellow
    exit 1
}

$pstFiles = Get-ChildItem -Path $pstPath -Filter "*.pst"
if ($pstFiles.Count -eq 0) {
    Write-Host "ERROR: No PST files found in $pstPath" -ForegroundColor Red
    exit 1
}

Write-Host "Found $($pstFiles.Count) PST file(s):" -ForegroundColor Green
foreach ($file in $pstFiles) {
    $sizeMB = [math]::Round($file.Length / 1MB, 2)
    Write-Host "  - $($file.Name) ($sizeMB MB)" -ForegroundColor Gray
}
Write-Host ""

# Check for AzCopy
$azcopyPath = "C:\Program Files\AzCopy\azcopy.exe"
if (!(Test-Path $azcopyPath)) {
    # Try other common locations
    $azcopyPath = "C:\AzCopy\azcopy.exe"
    if (!(Test-Path $azcopyPath)) {
        Write-Host "ERROR: AzCopy not found!" -ForegroundColor Red
        Write-Host "Download from: https://aka.ms/downloadazcopy-v10-windows" -ForegroundColor Yellow
        Write-Host "Extract to C:\AzCopy\ or install to Program Files" -ForegroundColor Yellow
        exit 1
    }
}

Write-Host "Using AzCopy: $azcopyPath" -ForegroundColor Green
Write-Host ""

# Upload files
Write-Host "Uploading PST files to Azure..." -ForegroundColor Cyan
Write-Host "Target: heieckimport/pstimport" -ForegroundColor Gray
Write-Host ""

& $azcopyPath copy "$pstPath\*.pst" $sasUrl --recursive --overwrite=true

if ($LASTEXITCODE -eq 0) {
    Write-Host ""
    Write-Host "Upload completed successfully!" -ForegroundColor Green
    Write-Host ""
    Write-Host "Next step: Create PST Import job in Microsoft 365" -ForegroundColor Yellow
    Write-Host "Go to: https://compliance.microsoft.com/informationgovernance?viewid=import" -ForegroundColor White
} else {
    Write-Host ""
    Write-Host "Upload failed with exit code: $LASTEXITCODE" -ForegroundColor Red
}


The user sent me the full SAS URL this time. I should acknowledge this and prepare the next steps.


Great! You have the full SAS URL. Now here's what to do:

**Next Steps:**

**1. Wait for PST exports to complete** - Check status:
```powershell
Get-MailboxExportRequest | Format-Table Name, Mailbox, Status, PercentComplete, BytesTransferred -AutoSize
```

**2. Download PST files from Neptune** when exports complete:
```powershell
# Create directory
New-Item -Path "C:\Temp\PST_Import" -ItemType Directory -Force

# Copy from Neptune
Copy-Item "\\neptune\c$\Temp\sheila.pst" "C:\Temp\PST_Import\"
Copy-Item "\\neptune\c$\Temp\jjh.pst" "C:\Temp\PST_Import\"
```

**3. Install AzCopy** (if not already installed):
- Download: https://aka.ms/downloadazcopy-v10-windows
- Extract to `C:\AzCopy\`

**4. Upload PSTs to Azure** - Run:
```powershell
& "C:\Users\MikeSwanson\AppData\Local\Temp\upload-psts-to-azure.ps1"
```

This script will automatically upload the PST files using your SAS URL.

**5. Import to Microsoft 365**:
- Go to: https://compliance.microsoft.com/informationgovernance?viewid=import
- Use the mapping CSV: `C:\Users\MikeSwanson\AppData\Local\Temp\import-mapping.csv`

**What's the current status of the exports on Neptune?**


The user just sent the SAS URL again. I already acknowledged it and created the upload script. They might be confirming they have it, or maybe they want me to do something specific with it. Let me check if they want me to proceed with something, or if they're just confirming.

Since I already created the upload script with this SAS URL, I should probably just confirm I have it and ask about the export status to keep things moving forward.


Got it - SAS URL is saved in the upload script.

What's the current status of the PST exports on Neptune? Run this to check:

```powershell
Get-MailboxExportRequest | Format-Table Name, Mailbox, Status, PercentComplete, BytesTransferred -AutoSize
```

Once they show **Status: Completed**, we can:
1. Download the PST files from Neptune
2. Upload to Azure using the script I created
3. Import to Microsoft 365

Are the exports still in progress or completed?


To create import jobs, you must be assigned the Mailbox Import Export role in Exchange Online. After this role is assigned, it might take up to 24 hours before you can start creating jobs.

Export mailboxes from Neptune to PST files

Download PST files from Neptune

Upload PST files to Azure blob storage

Import PST files to Microsoft 365 mailboxes

Verify mailbox data after migration


The user is seeing a message that they need the "Mailbox Import Export" role in Exchange Online, and it can take up to 24 hours after assignment. This is a permission requirement for PST imports.

Let me help them assign this role so they can proceed with the import once the PST files are ready.


You need to assign the Mailbox Import Export role. Let's do that now so it can propagate while the PST exports complete.

In your Exchange Online PowerShell session (you should still be connected), run:

```powershell
# Check current role assignments
Get-RoleGroup | Where-Object {$_.Roles -like "*Import*"} | Format-Table Name, Roles

# Get your admin account
$adminUser = (Get-AcceptedDomain | Where-Object {$_.DomainName -eq "heieck.org"}).DomainName
Write-Host "Enter the admin email for heieck.org:"
$adminEmail = Read-Host

# Assign the role
New-ManagementRoleAssignment -Role "Mailbox Import Export" -User $adminEmail
```

Or if you prefer, add yourself to the Organization Management role group which includes this permission:

```powershell
# Find your admin account
$adminEmail = "admin@heieck.org"  # Replace with actual admin account

# Add to Organization Management (includes import/export)
Add-RoleGroupMember -Identity "Organization Management" -Member $adminEmail
```

**Important**: After running this, you'll need to:
1. Close and reconnect your Exchange Online PowerShell session
2. Wait up to 60 minutes (usually faster than 24 hours) for permissions to propagate

While you're waiting for the role assignment and PST exports to complete, let me know when the exports finish and we'll proceed with downloading and uploading to Azure.

What's your admin email address for heieck.org?


admin email is sysadmin@heieck.org

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


The user provided the admin email. Let me create a script to assign the Mailbox Import Export role.


# Assign Mailbox Import Export role to admin
# Run this in Exchange Online PowerShell

$adminEmail = "sysadmin@heieck.org"

Write-Host "=== Assigning Mailbox Import Export Role ===" -ForegroundColor Cyan
Write-Host ""
Write-Host "Admin account: $adminEmail" -ForegroundColor Gray
Write-Host ""

try {
    # Check if already assigned
    $existing = Get-ManagementRoleAssignment -RoleAssignee $adminEmail -Role "Mailbox Import Export" -ErrorAction SilentlyContinue

    if ($existing) {
        Write-Host "Role already assigned!" -ForegroundColor Green
    } else {
        Write-Host "Assigning role..." -ForegroundColor Cyan
        New-ManagementRoleAssignment -Role "Mailbox Import Export" -User $adminEmail
        Write-Host "Role assigned successfully!" -ForegroundColor Green
    }

    Write-Host ""
    Write-Host "Note: It may take up to 60 minutes for permissions to propagate" -ForegroundColor Yellow
    Write-Host "Typically works within 15-30 minutes" -ForegroundColor Gray
    Write-Host ""
    Write-Host "Verify with:" -ForegroundColor Cyan
    Write-Host "Get-ManagementRoleAssignment -RoleAssignee '$adminEmail' | Format-Table Role, RoleAssigneeName" -ForegroundColor White

} catch {
    Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
}


File created successfully at: C:\Users\MikeSwanson\AppData\Local\Temp\assign-import-role.ps1

# Assign Mailbox Import Export role to admin
# Run this in Exchange Online PowerShell

$adminEmail = "sysadmin@heieck.org"

Write-Host "=== Assigning Mailbox Import Export Role ===" -ForegroundColor Cyan
Write-Host ""
Write-Host "Admin account: $adminEmail" -ForegroundColor Gray
Write-Host ""

try {
    # Check if already assigned
    $existing = Get-ManagementRoleAssignment -RoleAssignee $adminEmail -Role "Mailbox Import Export" -ErrorAction SilentlyContinue

    if ($existing) {
        Write-Host "Role already assigned!" -ForegroundColor Green
    } else {
        Write-Host "Assigning role..." -ForegroundColor Cyan
        New-ManagementRoleAssignment -Role "Mailbox Import Export" -User $adminEmail
        Write-Host "Role assigned successfully!" -ForegroundColor Green
    }

    Write-Host ""
    Write-Host "Note: It may take up to 60 minutes for permissions to propagate" -ForegroundColor Yellow
    Write-Host "Typically works within 15-30 minutes" -ForegroundColor Gray
    Write-Host ""
    Write-Host "Verify with:" -ForegroundColor Cyan
    Write-Host "Get-ManagementRoleAssignment -RoleAssignee '$adminEmail' | Format-Table Role, RoleAssigneeName" -ForegroundColor White

} catch {
    Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
}


I should update the todo list to reflect the current state - we need to add a task for assigning the import role and waiting for it to propagate.


TodoWrite

Gather Neptune Exchange server details and credentials

Gathering Neptune Exchange server details

Access Neptune via VPN for internal management

Assess mailbox sizes and user count for migration planning

Create Microsoft 365 mailboxes for heieck.org users

Export mailboxes from Neptune to PST files

Assign Mailbox Import Export role to admin

Wait for PST exports to complete on Neptune

Download PST files from Neptune

Upload PST files to Azure blob storage

Import PST files to Microsoft 365 mailboxes

Verify mailbox data after migration


Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration

Assign Mailbox Import Export role to admin

Wait for PST exports to complete on Neptune

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


Now let me provide the command for them to run in Exchange Online PowerShell.


Run this in your Exchange Online PowerShell session:

```powershell
# Assign Mailbox Import Export role
New-ManagementRoleAssignment -Role "Mailbox Import Export" -User "sysadmin@heieck.org"

# Verify assignment
Get-ManagementRoleAssignment -RoleAssignee "sysadmin@heieck.org" | Format-Table Role, RoleAssigneeName
```

This assigns the role to sysadmin@heieck.org. It typically propagates within 15-30 minutes (not the full 24 hours Microsoft mentions).

**While we wait for:**
1. Role assignment to propagate (~15-30 min)
2. PST exports to complete

**Can you check the export status?**
```powershell
Get-MailboxExportRequest | Format-Table Name, Mailbox, Status, PercentComplete, BytesTransferred -AutoSize
```

Once both are done, we'll:
1. Download PSTs from Neptune (`\\neptune\c$\Temp\`)
2. Upload to Azure using the script
3. Create the import job in Microsoft 365

What's the current export status showing?


Exports complete and in temp folder

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


The user says the PST exports are complete and in the temp folder on Neptune. Now I need to help them:

1. Download the PST files from Neptune to the local machine
2. Upload to Azure using the script I created
3. Then import to Microsoft 365 (after the role propagates)

Let me create commands to download the files from Neptune.


Perfect! Let's download the PST files from Neptune to your local machine:


Gather Neptune Exchange server details and credentials

Gathering Neptune Exchange server details

Access Neptune via VPN for internal management

Assess mailbox sizes and user count for migration planning

Create Microsoft 365 mailboxes for heieck.org users

Export mailboxes from Neptune to PST files

Assign Mailbox Import Export role to admin

Wait for PST exports to complete on Neptune

Download PST files from Neptune

Upload PST files to Azure blob storage

Import PST files to Microsoft 365 mailboxes

Verify mailbox data after migration


Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


[Request interrupted by user]


Already done

Download PST files from Neptune

Upload PST files to Azure blob storage

Verify mailbox data after migration


The user says the PST files are already downloaded. So let's move on to uploading them to Azure. I should update the todo list and help them upload to Azure using AzCopy.