Sist oppdatert: 2025-06-25

Send e-post fra Opter med Microsoft 365

Gjelder fra og med Opter 2025.06.00.

Hvis du bruker Microsoft 365 som e-posttjeneste, må du autentisere Opter ved å registrere programmet som en app i Azure.

Appregistreringen i Azure kan gjøres med et PowerShell-skript som er tilgjengelig som kodeeksempel nedenfor. Grunnen til at skriptet ikke kan kjøres i forbindelse med en oppdatering, er at personen som kjører det, må ha skriverettigheter for Azure AD og være Microsoft 365-administrator for organisasjonen din, noe Opter ikke er. Skriptet foretar de nødvendige innstillingene i Azure og Exchange. Når skriptet er kjørt, må noen data legges inn i Servere-fanen i kontorinnstillingene.

Trinn 1: Finn ut Microsoft 365-opplysningene dine

Når skriptet kjøres, må du oppgi følgende fire opplysninger. Begynn med å finne dem frem slik at du har dem for hånden, gjerne i en tekstfil, slik at du bare kan kopiere dem inn når tiden er inne.

Du må være administrator av Azure og Microsoft 365 i organisasjonen din for å få tilgang til dataene og kjøre skriptet.

  1. Azure Tenant ID

    Logg inn på portal.azure.com og søk etter "klientorganisasjon" eller "tenant properties". Kopier deretter verdien for Tenant ID.

  2. Brukernavn for en Microsoft 365-administratorkonto

    Vanligvis en e-postadresse. Siden du er administrator, kan du sannsynligvis bruke din egen adresse.

  3. Microsoft 365-domene

    Vanligvis det samme domenet som i e-postadressen til administratorkontoen.

  4. E-postadresse som skal brukes som avsender

    Dette er adressen som brukes til å sende e-post fra Opter, det vil si e-postkontoen du har opprettet for Opter i Microsoft 365. Hvis du allerede har en eksisterende adresse å sende fra, finner du den i feltet Brukernavn på fanen Servere i kontorinnstillingene.

Trinn 2: Åpne Windows Powershell

Søk etter "windows powershell" i Start-menyen i Windows, og åpne Windows PowerShell, ikke Windows PowerShell ISE.

En ledetekst åpnes. Angi RemoteSigned-rettigheten ved å lime inn det nedenstående i ledeteksten og trykke på Enter. Mer informasjon om rettighetene er tilgjengelig på Microsofts nettsted.

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Når du har kjørt skriptet, kan du tilbakestille rettighetene med kommandoen Set-ExecutionPolicy Restricted -Scope CurrentUser.

Trinn 3: Kjør skriptet

Kopier og lagre følgende skript som en PS1-fil på datamaskinen din. Kjør det deretter fra Windows PowerShell ved å lime inn banen til filen på kommandolinjen og trykke på Enter.

Skriptet bruker spesifikke versjoner av visse komponenter. Det kan hende du må avinstallere komponenter du allerede har installert først (hjelpekode er tilgjengelig i skriptet).

Ettersom skriptet tvinger inn bestemte versjoner av komponentene, kan det hende det "ødelegger" det eksisterende miljøet i PowerShell, og at det må gjenopprettes manuelt. Hvis du har et PowerShell-miljø som brukes i produksjon og ikke skal forstyrres, kan du kjøre skriptet på en virtuell maskin.

#Run the following command manually in Windows PowerShell before running the script below: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser


#Script to create app registration in Azure with Mail.Send rights for e-mail addresses in Mail-Enabled secutity group created.
#Application secret is set to expire after 999 years. This can be changed to the desired value by modifying $AppYears value
#Please note that tenant wide admin consent must be granted manually after this script has been executed.
#For Opter AB, 2025-04-24, David Magnusson Rosén
#
#Change log
#------------------------------------------------------------------------------------------------------------------------------
#202
#
#


#Code to uninstall entire module with sub-modules if needed 
#foreach ($module in (get-module -listavailable ModuleName*).name |get-unique) {write-host "removing module $module" uninstall-module $module }


#Install/import required modules
echo "Installing/importing required modules (can take several minutes)"

echo "Installing prerequisites..."
#PowerShellGet
if (Get-Module -ListAvailable -Name PowerShellGet) 
{
    echo "Updating module PowerShellGet..."
    Update-Module -Name PowerShellGet -Force

else 
{
    echo "Installing module PowerShellGet..."
    Install-Module -Name PowerShellGet -Scope CurrentUser -Force
}

echo "Installing module Az.Accounts..."
Install-Module -Name Az.Accounts -Scope CurrentUser -RequiredVersion 2.12.1 -AllowClobber -Repository PSGallery -Force
echo "Importing relevant functions from module Az.Accounts..."
Import-Module Az.Accounts -RequiredVersion 2.12.1

echo "Installing module Az.Resources..."
Install-Module -Name Az.Resources -Scope CurrentUser -RequiredVersion 6.6.0 -AllowClobber -Repository PSGallery -Force
echo "Importing relevant functions from module Az.Resources..."
Import-Module Az.Resources -RequiredVersion 6.6.0

echo "Installing module AzureAD..."
Install-Module AzureAD
echo "Importing relevant functions from module AzureAD..."
Import-Module AzureAD -Function Connect-AzureAD, Get-AzureADApplication, New-AzureADApplication, New-AzureADServicePrincipal, Add-AzADAppPermission, Get-AzADServicePrincipal, Get-AzADServicePrincipal_List

echo "Installing module Microsoft.Graph.Authentication..."
Install-Module Microsoft.Graph.Authentication -Scope CurrentUser -Repository PSGallery -AllowClobber -Force -requiredversion 1.27
echo "Importing relevant functions from module Microsoft.Graph.Authentication..."
Import-Module Microsoft.Graph.Authentication -Function Connect-MgGraph 
echo ""

echo "Installing module Microsoft.Graph.Applications..."
Install-Module Microsoft.Graph.Applications -Scope CurrentUser -Repository PSGallery -AllowClobber -Force
echo "Importing relevant functions from module Microsoft.Graph.Applications..."
Import-Module Microsoft.Graph.Applications -Function Add-MgApplicationPassword
echo ""

echo "Installing module ExchangeOnlineManagement..."
Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser -RequiredVersion 3.6.0 -Repository PSGallery  -AllowClobber  -Force
echo "Importing module ExchangeOnlineManagement..."
Import-Module ExchangeOnlineManagement -RequiredVersion 3.6.0 -Function Connect-ExchangeOnline, New-DistributionGroup, New-ApplicationAccessPolicy, Add-DistributionGroupMember
echo ""

echo "Necessary modules/functions installed/imported!"
echo ""

#Query for tenant Id
$TenantId = Read-Host "Please provide your Azure Tenant Id"

#Connect to AzureAD 
Connect-AzureAD -TenantId $TenantId
Connect-AzAccount


#Create app registration and service principal
$appName = "OpterMessageProxy"
if(!($myApp = Get-AzureADApplication -Filter "DisplayName eq '$($appName)'"  -ErrorAction SilentlyContinue))
{
    $myApp = New-AzureADApplication -DisplayName $appName    
    $myServicePrincipal = New-AzureADServicePrincipal -AccountEnabled $true -AppId $myApp.AppId -AppRoleAssignmentRequired $true -DisplayName $myApp.DisplayName
    $AppId = $myApp.AppId
}

#Wait for app registration to complete
echo "Wait for app registration to complete..."
Start-Sleep -Seconds 15

#Get service principal for Ms Graph
$graphApiId = '00000003-0000-0000-c000-000000000000'
$mailSendId = 'b633e1c5-b582-4048-a93e-9f11b44c7e96'
$graphSp = Get-AzADServicePrincipal -Filter "appId eq '$graphApiId'"

#Connect to MsGraph
Connect-MgGraph -Scopes "Application.ReadWrite.All", "DelegatedPermissionGrant.ReadWrite.All" 

#Add Mail.Send rights to app registration
Add-AzADAppPermission -ObjectId $myApp.ObjectId -ApiId $graphApiId -PermissionId $mailSendId -Type Role

#Wait for rights assignment to complete
Start-Sleep -Seconds 15

#Create a secret for the app registration
$AppYears = "999"

$PasswordCred = @{ 
    displayName = "Secret_${appName}_unlimited"
    endDateTime = (Get-Date).AddYears($AppYears)
}

# Add App Client Secret - Valid for 999 years
$Secret = Add-MgApplicationPassword -ApplicationId $myApp.ObjectId -PasswordCredential $PasswordCred
$SecretText = $Secret.SecretText 
# Write Client Secret value
echo "Secret: ${SecretText}" 

#For future use
#Grant tenant-wide consent for app registration
# Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Graph'" -Property AppRoles | Select -ExpandProperty appRoles |fl
# $params = @{
  # "PrincipalId" ="aaaaaaaa-bbbb-cccc-1111-222222222222"
  # "ResourceId" = "a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1"
  # "AppRoleId" = "df021288-bdef-4463-88db-98f22de89214"
# }
# New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId 'aaaaaaaa-bbbb-cccc-1111-222222222222' -BodyParameter $params | 
#  Format-List Id, AppRoleId, CreatedDateTime, PrincipalDisplayName, PrincipalId, PrincipalType, ResourceDisplayName

#Connect to Exchange Online
$UserPrincipleName = Read-Host "Please provide your Microsoft365 admin user (usually yourname@yourdomain.com)"
Connect-ExchangeOnline -UserPrincipalName $UserPrincipleName

#Set up mail sending restrictions
$UserDomain = Read-Host "Please provide your Microsoft365 domain(usually yourdomain.com)"
$SenderAddress = Read-Host "Please provide an existing e-mail address to be used as sender"
$GroupName = "${appName}_group"
$mesGroup = New-DistributionGroup -Name $GroupName -PrimarySmtpAddress "${appName}@${UserDomain}" -Alias $GroupName.ToLower() -Type security 
$accessPolicy = New-ApplicationAccessPolicy -AppId $myApp.AppId -PolicyScopeGroupId "${appName}@${UserDomain}" -AccessRight RestrictAccess -Description "Restrict this app to members of distribution group ${GroupName}."
$dgMember = Add-DistributionGroupMember -Identity $GroupName -Member $SenderAddress -Confirm:$false

#Show settings to use in Opter office settings and copy them to clipboard
#$ButtonType = [System.Windows.Forms.MessageBoxButtons]::OK
$MessageIcon = [System.Windows.Forms.MessageBoxIcon]::Information
$MessageBody =  "Ms Graph Tenant Id:     ${TenantId} `n"
$MessageBody += "Ms Graph Client Id:     ${AppId} `n"
$MessageBody += "Ms Graph Client Secret: ${SecretText} `n"
$MessageInfo = "`n`n"
$MessageInfo += "NB!`nThe client secret disappears when you close this message and cannot be retreived or restored.`n"
$MessageInfo += "If you don't make a note of it, you have to create a new one manually in the Azure portal!`n`n"
$MessageInfo += "The above settings have been copied to the clipboard. Enter them in the office settings in Opter."
$MessageTitle = "Info to be used in Opter office settings"

Set-Clipboard -Value $MessageBody
#[System.Windows.Forms.MessageBox]::Show("${MessageBody} ${MessageInfo}",$MessageTitle,$ButtonType,$MessageIcon)


#Custom result form
$color = [System.Drawing.Color]::White
$form = New-Object System.Windows.Forms.Form
$form.Text = $MessageTitle
$form.BackColor = $color
$form.Width = 800  
$form.Height = 275

$lblTenantId = New-Object System.Windows.Forms.Label
$lblTenantId.Text = "Ms Graph Tenant Id:"
$lblTenantId.AutoSize = $true
$lblTenantId.Font = New-Object System.Drawing.Font("Courier", 10
$lblTenantId.Location = New-Object System.Drawing.Point(10,20)

$txtTenantId = New-Object System.Windows.Forms.TextBox
$txtTenantId.Height = 20
$txtTenantId.Width = 375
$txtTenantId.Multiline = $true
$txtTenantId.Text = $TenantId
$txtTenantId.Font = New-Object System.Drawing.Font("Courier New", 10
$txtTenantId.Location = New-Object System.Drawing.Point(200,20)

$lblClientId = New-Object System.Windows.Forms.Label
$lblClientId.Text = "Ms Graph Client Id:"
$lblClientId.AutoSize = $true
$lblClientId.Font = New-Object System.Drawing.Font("Courier", 10
$lblClientId.Location = New-Object System.Drawing.Point(10,50)

$txtClientId = New-Object System.Windows.Forms.TextBox
$txtClientId.Height = 20
$txtClientId.Width = 375
$txtClientId.Multiline = $true
$txtClientId.Text = $AppId
$txtClientId.Font = New-Object System.Drawing.Font("Courier New", 10
$txtClientId.Location = New-Object System.Drawing.Point(200,50)

$lblClientSecret = New-Object System.Windows.Forms.Label
$lblClientSecret.Text = "Ms Graph Client Secret:"
$lblClientSecret.AutoSize = $true
$lblClientSecret.Font = New-Object System.Drawing.Font("Courier", 10
$lblClientSecret.Location = New-Object System.Drawing.Point(10,80)

$txtClientSecret = New-Object System.Windows.Forms.TextBox
$txtClientSecret.Height = 20
$txtClientSecret.Width = 375
$txtClientSecret.Multiline = $true
$txtClientSecret.Text = $SecretText
$txtClientSecret.Font = New-Object System.Drawing.Font("Courier New", 10
$txtClientSecret.Location = New-Object System.Drawing.Point(200,80)

$lblMessage = New-Object System.Windows.Forms.Label
$lblMessage.Text = $MessageInfo
$lblMessage.AutoSize = $true
$lblMessage.Font = New-Object System.Drawing.Font("Courier", 10
$lblMessage.Location = New-Object System.Drawing.Point(10,90)

$form.Controls.Add($lblTenantId)
$form.Controls.Add($txtTenantId)
$form.Controls.Add($lblClientId)
$form.Controls.Add($txtClientId)
$form.Controls.Add($lblClientSecret)
$form.Controls.Add($txtClientSecret)
$form.Controls.Add($lblMessage)

$form.ShowDialog()

Du blir spurt om du vil installere modulene, og du må svare ja på dette.

Når du blir bedt om å oppgi opplysningene du fant ut i trinn 1, for eksempel Azure Tenant ID-en, limer du dem inn og trykker på Enter, så fortsetter skriptet å kjøre.

Hva gjør skriptet?

Vi deler det opp i blokker.

  • Linjene 20–70 installerer MS Graph-modulene for PowerShell. De er nødvendige for at resten av skriptet skal fungere. Modulene legges i C:\Program Files\WindowsPowerShell\Modules\.

  • Linjene 72–77 logger på Azure AD.

  • Linjene 80–119 registrerer Opter som en app i Azure med navnet "OpterMessageProxy" og gir appen rett til å sende e-post. Du kan endre navnet "OpterMessageProxy" til noe annet på linje 81, men det er enklere å beholde standardnavnet i tilfelle du skulle trenge å kontakte kundestøtte senere.

  • Linjene 132–142 legger til OpterMessageProxy i en rettighetsgruppe i Exchange med begrensede rettigheter.

  • Linjene 144–224 viser informasjonen som må legges inn i kontorinnstillingene i Opter (fanen Servere). Informasjonen kopieres til utklippstavlen, men kan også kopieres fra dialogboksen som åpnes. Ikke lukk dialogboksen før du har lagt inn informasjonen i kontorinnstillingene. Eller du kan lime inn informasjonen i en tekstfil eller et annet sted, som du deretter kan kopiere fra.

    Klienthemmeligheten kan ikke hentes tilbake eller gjenopprettes. Hvis du ikke limer den inn noe sted, må du opprette en ny i Azure-portalen. De andre dataene kan hentes fra Azure-portalen i etterkant hvis det er behov for det.

Trinn 4: Aktiver Azure-tilkoblingen i Opter

Klikk på fanen Servere under Innstillinger > Kontor, og fyll ut følgende felt med informasjonen du limte inn i tekstfilen i trinn 2:

  • Ms Graph Tenant Id

  • Ms Graph Client Id

  • Ms Graph Client Secret

Klikk deretter på Test e-post, skriv inn deg selv som mottaker og sjekk at du mottar en melding.

Hvis det finnes en verdi i Ms Graph Tenant Id-feltet, spiller det ingen rolle om feltene over på denne fanen er utfylt (SMTP-server, Port, Brukernavn, Passord og Sikker overføring (SSL)). Disse dataene brukes ikke, autentiseringen gjøres gjennom appregistreringen i Azure. Det kan være nyttig å fjerne informasjonen i dem slik at det ikke oppstår misforståelser.

Trinn 5: Gi OpterMessageProxy-appen administratorrettigheter

Logg inn på portal.azure.com, og søk etter "OpterMessageProxy". Gå til API permissions i menyen til venstre, og klikk på Grant admin consent for {0}

App-registrering i Azure

Du finner appregistreringen på portal.azure.com ved å søke etter "optermessageproxy" og velge søkeresultatet merket Application. Du kan også gå til appregistreringer og se i listen over registrerte programmer.

Under OpterMessageProxy kan du se og kopiere Ms Graph Tenant Id = Directory (tenant) ID (2) og Ms Graph Client Id = Application (client) ID (1).

Ms Graph Client Secret kan ikke vises eller gjenopprettes i Azure-portalen. Hvis du ikke klarte å lime den inn etter at skriptet ble kjørt, må du opprette en ny hemmelighet. Gå til Manage (1) > Certificates & secrets (2) i menyen til venstre, og klikk på New client secret. Der kan du også sjekke når klienthemmeligheten utløper.

Alternative e-postadresser

Hvis du for eksempel ønsker å sende fakturaer fra Opter med en annen adresse, for eksempel invoice@budfirman.se, legger du til de alternative adressene i sikkerhetsgruppen OpterMessageProxy_group i Exchange. Hvis du endret navnet da du registrerte Opter i Azure, vil gruppen få det navnet du oppga + "_group". Mer informasjon er tilgjengelig på Microsofts nettsted: Tillat medlemmer å sende som eller sende på vegne av en gruppe (Microsoft). Alle avsenderadressene du har lagt til i Opter, må være inkludert i sikkerhetsgruppen.

Mer informasjon om og eksempler på hvordan du legger til forskjellige avsenderadresser, finnes på Alternativa e-postadresser.

Tofaktorautentisering (2FA, MFA) kan ikke brukes på e-postkontoer som brukes av Opter.

Se også