Назад | Перейти на главную страницу

как сделать резервную копию / экспортировать электронную почту office 365 в pst в гибридной среде обмена?

У нас есть обмен гибридной средой. (некоторые пользователи используют обмен onpremises, а некоторые - Office 365.)

Когда мы хотим экспортировать электронные письма из onpremis мы используем команду ниже для экспорта почтового ящика и архива.

 New-MailboxExportRequest -Mailbox "user" -FilePath \\mysrv\l$\PST\Mailbox-user.pst; New-MailboxExportRequest -Mailbox "user" -IsArchive  -FilePath \\mysrv\l$\PST\Mailbox-user-archive.pst -confirm:$false

New-MailboxExportRequest отлично работает для пользователей onpremis, а не для Office 365. Есть ли способ экспортировать почтовый ящик пользователя Office 365 в pst с помощью powershell?

Что я пробовал до сих пор:

Я вошел в офис 365

$UserCredential = Get-Credential
Import-Module MSOnline

Connect-MsolService -Credential $UserCredential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication  Basic -AllowRedirection

Import-PSSession $Session

и попробовал New-MailboxExportRequest

Но выдает ошибку. очевидно, офис 365 не знает эту команду

PS C:\Users\pp> New-MailboxExportRequest
New-MailboxExportRequest : The term 'New-MailboxExportRequest' 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:1
+ New-MailboxExportRequest
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (New-MailboxExportRequest:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Также Get-Command *Export* результаты следующие

Пытался погуглить, но не нашел подходящего варианта. может кто-нибудь направить меня, пожалуйста? Какая команда совместима с офисной средой для этого?

PS: я пытался https://www.codetwo.com/admins-blog/how-to-export-office-365-mailboxes-to-pst-using-ediscovery/ с лицензией E5 и отлично работает в графическом интерфейсе. Но меня беспокоит даже электронное обнаружение, и есть ли у меня возможность делать это с помощью PowerShell? я имею в виду сценарий / автоматизацию через PowerShell?

Вы не можете экспортировать почтовый ящик Exchange Online напрямую в PST через PowerShell с помощью встроенных инструментов. Обязательный New-MailboxExportRequest не существует в сети (или не доступен для нас, смертных).

Ты можешь:

  • eDiscovery, похоже, только с графическим интерфейсом.
  • Выгрузить / перенести почтовый ящик в локальный Exchange и запустить New-MailboxExportRequest локально (и при необходимости выполнить миграцию обратно в Exchange Online)
  • Используйте различные сторонние инструменты, которые выполняют экспорт через EWS или MAPI.
  • Полный доступ к делегированию сценария, привязка Outlook к делегированному почтовому ящику и экспорт в PST. Технически очень вероятно, но я никогда не видел, чтобы кто-то делал это. Я не углублялся в eDiscovery, но считаю, что это более-менее то, как eDiscovery экспортирует в PST (старые биржи также использовались для привязки к Outlook для экспорта PST). Но без значительного опыта работы с MAPI модель Outlook COM довольно сложна в использовании (я написал несколько сценариев Outlook, но эмулировать экспорт PST, мягко говоря, сложно).

Я расстроен так же, как и ты. Экспорт почтовых ящиков уходящих пользователей для длительного хранения бесполезно раздражает. Если бы мы могли просто экспортировать в Azure Blob так же, как и импорт, это было бы хорошим началом.

Это не ответ на вопрос: я еще не пробовал экспортировать напрямую из Exchange Online в PST.

Это сделано в качестве дополнения к последнему пункту ответа @DonZoomiks. Немного Powershell, взятый Франкенштейном из разных малоизвестных источников и извлекающий почту из Exchange Online. При необходимости настройте.

Продукт представляет собой настраиваемый объект, содержащий полученную почту. Возможно, кто-то сможет потренироваться и поделится, как пройти оттуда в PST без передачи Outlook?

Требование Управляемый API 2.2 веб-служб Exchange (EWS)

Итак, первые 2 функции:

function Enter-ExchangeOnlineSession {
  <#
      .Synopsis
      Sets up a user session with ExchangeOnline, typically to fetch mail.
      .DESCRIPTION
      Sets up a user session with ExchangeOnline, typically to fetch mail.
      .EXAMPLE
      $CredMail = Get-Credential -UserName user@domain.com
      $Service = Enter-ExchangeOnlineSession -Credential $CredMail -MailDomain domain.com
      .INPUTS
      Inputs to this cmdlet (if any)
      .OUTPUTS
      Output from this cmdlet (if any)
      .NOTES
      General notes
      .COMPONENT
      The component this cmdlet belongs to
      .ROLE
      The role this cmdlet belongs to
      .FUNCTIONALITY
      The functionality that best describes this cmdlet
  #>
  Param(
    [Parameter(ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true,
        Position=0)]
    [ValidateNotNullOrEmpty()]
    [string]$EWSAssemblyPath = 'C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll',

    # Parameter Credential
    [Parameter(Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=1)]
    [System.Management.Automation.CredentialAttribute()]
    $Credential,

    # Parameter Maildomain
    [Parameter(Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=2)]
    [string]$MailDomain,

    # Parameter Maildomain
    [Parameter(Mandatory=$false, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=3)]
    [string]$AutoDiscoverCallbackUrl = 'https://autodiscover-s.outlook.com/autodiscover/autodiscover.xml'

  )

  # Set the path to your copy of EWS Managed API and load the assembly.
  [void][Reflection.Assembly]::LoadFile($EWSAssemblyPath) 

  # Establish the session and return the service connection object.
  $service =  New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
  $Service.Credentials = New-Object System.Net.NetworkCredential($Credential.UserName, $Credential.GetNetworkCredential().Password, $MailDomain)

  $TestUrlCallback = {
    param ([string] $url)
    if ($url -eq $AutoDiscoverCallbackUrl) {$true} else {$false}
  }
  $service.AutodiscoverUrl($Credential.UserName, $TestUrlCallback)

  return $Service
}

и

function Get-ExchangeOnlineMailContent {
  <#
      .Synopsis
      Fetches content from an Exchange Online user session, typically mail.
      .DESCRIPTION
      Fetches content from an Exchange Online user session, typically mail.
      .EXAMPLE
      $Service = Enter-ExchangeOnlineSession -Credential $CredMail -MailDomain example.com
      Get-ExchangeOnlineMailContent -ServiceObject $Service -PageSize 5 -Offset 0 -PageIndexLimit 15 -WellKnownFolderName Inbox
      .INPUTS
      Inputs to this cmdlet (if any)
      .OUTPUTS
      Output from this cmdlet (if any)
      .NOTES
      General notes
      .COMPONENT
      The component this cmdlet belongs to
      .ROLE
      The role this cmdlet belongs to
      .FUNCTIONALITY
      The functionality that best describes this cmdlet
  #>

  Param(
    [Parameter(Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=0)]
    $ServiceObject,

    # Define paging as described in https://msdn.microsoft.com/en-us/library/office/dn592093(v=exchg.150).aspx
    [Parameter(Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=1)]
    [int]$PageSize,

    [Parameter(Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=2)]
    [int]$Offset,

    #Translates into multiples of $PageSize
    [Parameter(Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=3)]
    [int]$PageIndexLimit,

    # WellKnownFolderNames doc https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.wellknownfoldername(v=exchg.80).aspx
    [Parameter(Mandatory=$true, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=4)]
    [ValidateSet('Calendar',
                'Contacts',
                'DeletedItems',
                'Drafts',
                'Inbox',
                'Journal',
                'Notes',
                'Outbox',
                'SentItems',
                'Tasks',
                'MsgFolderRoot',
                'PublicFoldersRoot',
                'Root',
                'JunkEmail',
                'SearchFolders',
                'VoiceMail',
                'RecoverableItemsRoot',
                'RecoverableItemsDeletions',
                'RecoverableItemsVersions',
                'RecoverableItemsPurges',
                'ArchiveRoot',
                'ArchiveMsgFolderRoot',
                'ArchiveDeletedItems',
                'ArchiveRecoverableItemsRoot',
                'ArchiveRecoverableItemsDeletions',
                'ArchiveRecoverableItemsVersions',
                'ArchiveRecoverableItemsPurges',
                'SyncIssues',
                'Conflicts',
                'LocalFailures',
                'ServerFailures',
                'RecipientCache',
                'QuickContacts',
                'ConversationHistory',  
                'ToDoSearch')]
    [string]$WellKnownFolderName,

    [Parameter(Mandatory=$false, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=5)]
    [switch]$ParseOriginalRecipient,

    [Parameter(Mandatory=$false, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=6)]
    [switch]$OriginalRecipientAddressOnly,

    [Parameter(Mandatory=$false, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=7)]
    [datetime]$MailFromDate,

    [Parameter(Mandatory=$false, 
        ValueFromPipeline=$true,
        ValueFromPipelineByPropertyName=$true, 
        ValueFromRemainingArguments=$false, 
        Position=8)]
    [switch]$ConsoleOutput
  )

  # Create Property Set to include body and header, set body to text.
  $PropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
  $PropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text

  if ($ParseOriginalRecipient)
  {
    $PR_TRANSPORT_MESSAGE_HEADERS = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x007D,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String)
    $PropertySet.add($PR_TRANSPORT_MESSAGE_HEADERS)
  }

  $PageIndex = 0

  # Page through folder.
  do 
  { 
    # Limit the view to $pagesize number of email starting at $Offset.
    $PageView = New-Object Microsoft.Exchange.WebServices.Data.ItemView($PageSize,$PageIndex,$Offset)

    # Get folder data.
    $FindResults = $ServiceObject.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::$WellKnownFolderName,$PageView) 
    foreach ($MailItem in $FindResults.Items)
    {
      # Load extended properties.
      $MailItem.Load($propertySet)

      if ($ParseOriginalRecipient)
      {
        # Extended properties are one string, split by linebreak then find the line beginning with 'To:', containing original recipient address before exchange aliasing replaces it.
        $OriginalRecipientStringRaw = ($MailItem.ExtendedProperties.value.split([Environment]::NewLine) | Where-Object {$_ -match '^To:'}).trimstart('To:').trim()

        $MailItem | Add-Member -NotePropertyName ExtendedHeader -NotePropertyValue $OriginalRecipientStringRaw

        if ($OriginalRecipientAddressOnly)
        {
          # Removes everything but the address 'my.name@example.com' when string has form of e.g. '"My Name" <my.name@example.com>'
          $MailItem | Add-Member -NotePropertyName OriginalRecipient -NotePropertyValue ($OriginalRecipientStringRaw | ForEach-Object {($_.ToString() -creplace '^[^<]*<', '').trimend('>')})
        }
        else
        {
          $MailItem | Add-Member -NotePropertyName OriginalRecipient -NotePropertyValue $OriginalRecipientStringRaw
        }
        if ($ConsoleOutput) {write-host -ForegroundColor Cyan "$($MailItem.DateTimeReceived) | $($MailItem.OriginalRecipient) | $($MailItem.Sender)"}
      }

      # Output result.
      $MailItem | Select-Object -Property *
    } 

    # Increment $index to next page.
    $PageIndex += $PageSize
  } while (($FindResults.MoreAvailable) `
            -and ($PageIndex -lt $PageIndexLimit) `
            -and ($MailItem.DateTimeReceived -gt $MailFromDate)) # Do/While there are more emails to retrieve and pagelimit is not exceeded and datetimereceived is later than date.
}

тогда можно:

$Cred = Get-Credential #Example user: user@example.com
$domain = 'example.com'

# Set how many emails we want to read at a time
$PageSizeNumOfEmails = 10
$OffSet = 0
$PageIndexLimit = 2000
$MailFolder = 'Inbox'
$DeltaTimeStamp = (Get-Date).AddDays(-30) #Go how many days back?

try
{
  $Session = Enter-ExchangeOnlineSession -Credential $Cred -MailDomain $domain
}
catch
{
  $Message = $_.exception.message
  Write-Host -ForegroundColor Yellow $Message
}

$Mails = Get-ExchangeOnlineMailContent -ServiceObject $Session `
                                        -PageSize $PageSizeNumOfEmails `
                                        -Offset $OffSet `
                                        -PageIndexLimit $PageIndexLimit `
                                        -WellKnownFolderName $MailFolder `
                                        -ParseOriginalRecipient `
                                        -OriginalRecipientAddressOnly `
                                        -MailFromDate $DeltaTimeStamp | Where-Object {$_.DateTimeReceived -gt $DeltaTimeStamp} | select *

и наконец процесс $Mails как хочешь.