grahamr975 / EWS-Office365-Contact-Sync

Uses Exchange Web Services to synchronize a Global Address List in Office 365 to a user's mailbox
MIT License
94 stars 21 forks source link

ModernAuth Update #56

Closed benj288 closed 1 year ago

benj288 commented 2 years ago

Hello,

i currently can't get the Contacts List and also can't execute the Contact Sync due to Basic auth deactivation. (Errors in particular: "Can't fetch Data" "Autodiscover failed") Is there a way, to update the Script, without making a Azure AD App? Thank you Kind regards

grahamr975 commented 2 years ago

@benj288

Are you using the -ModernAuth flag?

benj288 commented 2 years ago

Yes, i get this error however, when the script is trying to fetch the Contact info image

SeidelMahla commented 2 years ago

Hey, got the same error. Is there an easy way to fix this? Thanks :)

benj288 commented 1 year ago

I have so far resolved the issue regarding the fetching of the Contact info after implementing an Azure app and adapting the Get-GALContacts Module (Issue #46) However, I get following error when it is trying to Sync to the Mailbox.

VERBOSE: Loading module from path 'C:\Kontaktesynchronisierung\Skripts\SyncModul\EWSContacts\Module\bin\Microsoft.IdentityModel.Clients.ActiveDirectory.dll'. PS>TerminatingError(Connect-EXCExchange): "Exception calling "AutodiscoverUrl" with "2" argument(s): "The Autodiscover service couldn't be located.""

TerminatingError(Connect-EXCExchange): "Exception calling "AutodiscoverUrl" with "2" argument(s): "The Autodiscover service couldn't be located."" 2022.07.18 15:27:13 ERROR Kontakte Sync fehlgeschlagen fuer Mail@mycompany.com Exception calling "AutodiscoverUrl" with "2" argument(s): "The Autodiscover service couldn't be located."

Is there a updated version of the Connect-EXCExchange Module and the Sync-ContactList module?

christianneeb commented 1 year ago

Which version of PowerShell you are using?

Can you try to run this command prior and then try again? I currently using PowerShell 4.0 on Server 2012 R2 and this helped me

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

JimSnead commented 1 year ago

I fixed it by installing the new [Exchange Online Powershell V2 Module ]

(https://docs.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps)

and editing the "Get-GALContacts.ps1" script. (See below)

EDIT: I got the flag for "DIRECTORY" working. You need to modify the script "Get-Mailboxes.ps1" (See very bottom)

function Get-GALContacts {
    <#
    .SYNOPSIS
        Uses Office 365 services to generate a list of contacts. Only includes contacts with an email address.

    .PARAMETER ConnectionUri
        Used to connect to Office 365, by default this is https://outlook.office365.com/powershell-liveid/.

    .PARAMETER Credentials
        Office 365 Admin Credentials
    .PARAMETER ExcludeContactsWithoutPhoneNumber
        Switch; Only return contacts that have a phone or mobile number
    .PARAMETER ExcludeSharedMailboxContacts
        Switch; Excludes contacts that are a shared mailbox, or a mailbox without a liscense
    .PARAMETER IncludeNonUserContacts
        Switch; Also return contacts that aren't users/mailboxes in your directory. These contacts must still have an email address.

    .EXAMPLE
        PS C:\> Get-GALContacts -ConnectionUri 'https://outlook.office365.com/powershell-liveid/' -Credentials $Credentials
    #>
[CmdletBinding()]
param (
    [Parameter(Position = 0, Mandatory = $true)]
    [string]
    $ConnectionUri,

    [Parameter(Position = 1, Mandatory = $true)]
    [System.Management.Automation.PSCredential]
    $Credentials,

    [Parameter(Position = 2, Mandatory = $false)]
    [bool]
    $ExcludeContactsWithoutPhoneNumber,

    [Parameter(Position = 3, Mandatory = $false)]
    [bool]
    $ExcludeSharedMailboxContacts,

    [Parameter(Position = 4, Mandatory = $false)]
    [bool]
    $IncludeNonUserContacts
)
process {
    try {
        # Connect to Office 365 Exchange Server using a Remote Session
        Connect-ExchangeOnline -ConnectionUri $ConnectionUri -Credential $Credentials

        # Import Global Address List into Powershell from Office 365 Exchange as an array
        $ContactList = Get-User -ResultSize unlimited 

        # If the ExcludeSharedMailboxContacts switch is enabled, exclude contacts that are a shared mailbox or mailbox with no liscense
        if ($ExcludeSharedMailboxContacts) {

            $DirectoryList = $(Get-EXOMailbox -ResultSize unlimited | Where-Object {$_.HiddenFromAddressListsEnabled -Match "False"})

            $EmailAddressList = $DirectoryList.PrimarySMTPAddress
            $ContactList = $ContactList | Select-Object DisplayName,FirstName,LastName,Title,Company,Department,WindowsEmailAddress,Phone,MobilePhone | Where-Object {$EmailAddressList.Contains($_.WindowsEmailAddress)}
        } else {
            $ContactList = $ContactList | Select-Object DisplayName,FirstName,LastName,Title,Company,Department,WindowsEmailAddress,Phone,MobilePhone
        }

        # If the IncludeNonUserContacts switch is enabled, also include contacts that aren't actual users in the directory
        if ($IncludeNonUserContacts) {
            $ContactList += Get-Contact -ResultSize unlimited | Select-Object DisplayName,FirstName,LastName,Title,Company,Department,WindowsEmailAddress,Phone,MobilePhone
        }

        # If the ExcludeContactsWithoutPhoneNumber switch is enabled, exclude contacts that don't have a phone or mobile number
        if ($ExcludeContactsWithoutPhoneNumber) {
            $ContactList = $ContactList | Where-Object {$_.Phone -or $_.MobilePhone}
        }
        Disconnect-ExchangeOnline -Confirm:$false

    # Only return contacts with email addresses
    return $ContactList | Where-Object {$null -ne $_.WindowsEmailAddress -and "" -ne $_.WindowsEmailAddress}
    } catch {
        Write-Log -Level "FATAL" -Message "Failed to fetch Global Address List Contacts from Office 365 Directory" -exception $_.Exception.Message
    }
}
}

This is the Get-Mailboxes.ps1 script

function Get-Mailboxes {
    <#
    .SYNOPSIS
        Uses Office 365 services to generate a list of contacts 

    .PARAMETER ConnectionUri
        Used to connect to Office 365, by default this is https://outlook.office365.com/powershell-liveid/.

    .PARAMETER Credentials
        Office 365 Admin Credentials

    .EXAMPLE
        PS C:\> Get-GALContacts -ConnectionUri 'https://outlook.office365.com/powershell-liveid/' -Credentials $Credentials
    #>
[CmdletBinding()]
param (
    [Parameter(Position = 0, Mandatory = $true)]
    [string]
    $ConnectionUri,

    [Parameter(Position = 1, Mandatory = $true)]
    [System.Management.Automation.PSCredential]
    $Credentials
)
process {
    try {
    # $Null = @() is a workaround for this function returning a random filename such as "tmp_z1ci55dv.kke" at the start of the output....
    $Null = @(
        # Connect to Office 365 Exchange Server using a Remote Session
     Connect-ExchangeOnline -ConnectionUri $ConnectionUri -Credential $Credentials 

            $DirectoryList = $(Get-Mailbox -ResultSize unlimited | Where-Object {$_.HiddenFromAddressListsEnabled -Match "False"}).PrimarySMTPAddress

        Disconnect-ExchangeOnline -Confirm:$false

    )

    } catch {
        Write-Log -Level "FATAL" -Message "Failed to fetch user mailbox list from Office 365 directory" -exception $_.Exception.Message
    }
    return $DirectoryList | Where-Object {$null -ne $_ -and "" -ne $_}
}
}
benj288 commented 1 year ago

Which version of PowerShell you are using?

Can you try to run this command prior and then try again? I currently using PowerShell 4.0 on Server 2012 R2 and this helped me

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

Where have you added this line?

benj288 commented 1 year ago

Sorry for writing again - i have made our script finally work. However, in my Azure AD Sign-in logs, there is still an entry coming up from the script. Since basic auth will be disabled on October 1st, i need to adjust the script to this.

My only problem is the Sync-ContactList.ps1 Has anyone adjusted this script for an Azure APP? If so, could you please share this with me? I would be grateful.

Kind regards Ben

grahamr975 commented 1 year ago

@benj288 Could you source the website where you found the basic authentication depreciation date? I thought it was next year, rather than October 1st. Thanks

christianneeb commented 1 year ago

@benj288 Could you source the website where you found the basic authentication depreciation date? I thought it was next year, rather than October 1st. Thanks

You will find the informations here: https://docs.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-basic-authentication-exchange-online

benj288 commented 1 year ago

Yes they announced it last year Did anybody adjust their scripts?

benj288 commented 1 year ago

@christianneeb Where have you added the

In your Scripts?

grahamr975 commented 1 year ago

@benj288 Several users have had success with setting up an Azure app for ExchangeOnline in issue #46. I'm working on an update for the main script with a tutorial for setting this up.

As for the EWS portion of the script, I don't think this needs to be changed as it's already coded to generate an OAuth token from the user credentials when using the -ModernAuth flag.

christianneeb commented 1 year ago

I run the script via a scheduled Task and therefor created a small script that referenced to this script here. Script is running on a Windows Server 2012 R2 with PowerShell 4.0. If you have any newer version, you wont need to add this line.

grafik

benj288 commented 1 year ago

@benj288 Several users have had success with setting up an Azure app for ExchangeOnline in issue #46. I'm working on an update for the main script with a tutorial for setting this up.

As for the EWS portion of the script, I don't think this needs to be changed as it's already coded to generate an OAuth token from the user credentials when using the -ModernAuth flag.

Thank you for your info. Is there new version of the Main script working?

grahamr975 commented 1 year ago

@benj288 I'm still working on the new version + a guide for setting up an Azure app cert. Once it's available, I'll publish it for everyone.

grahamr975 commented 1 year ago

@benj288 and others,

I published the new OAuth script version & guide in commit 9fcfe1f06192848882564615dd9aa05e71d69970. All basic authentication has been upgraded to certificate based. If anyone has any questions, please reach out.