Viimeisin päivitys: 2025-10-29

Lähetä sähköposteja Opterista Microsoft 365:n avulla

Sovelletaan alkaen Opter 2025.06.00:sta.

Jos käytät sähköpostipalveluna Microsoft 365:tä, sinun on todennettava Opter rekisteröimällä se sovelluksena Azuressa.

Sovelluksen rekisteröinti Azureen voidaan tehdä PowerShell-skriptillä, joka on saatavilla koodiesimerkkinä alla. Syy siihen, miksi skriptiä ei voi suorittaa päivityksen yhteydessä, on se, että skriptin suorittajalla on oltava oikeus muuttaa Microsoft Entra ID:tä (entinen Azure Active Directory) ja hänellä on oltava organisaatiosi Microsoft 365:n järjestelmänvalvojan oikeudet, mitä Opter ei ole. Skripti tekee tarvittavat asetukset Entra ID:hen ja Exchangeen. Kun skripti on suoritettu, toimiston asetusten välilehdelle Palvelimet on syötettävä joitakin tietoja.

Vaihe 1: Selvitä Microsoft 365 -tietosi

Kun skripti käynnistyy, sinun on annettava seuraavat neljä tietoa. Aloita selvittämällä ne siten, että ne ovat saatavillasi, mieluiten tekstitiedostossa, jotta voit helposti kopioida ne, kun niitä tarvitaan.

Sinun on oltava Microsoft Entra ID:n ja Microsoft 365:n järjestelmänvalvoja organisaatiossasi, jotta voit hakea tiedot ja suorittaa skriptin.

  1. Azure Tenant ID

    Kirjaudu osoitteeseen portal.azure.com ja etsi hakusanoilla "asiakasorganisaatio" tai "tenant properties". Kopioi sitten Tenant ID:n arvo.

  2. Microsoft 365 -järjestelmänvalvojan käyttäjätunnus

    Yleensä sähköpostiosoite. Koska olet järjestelmänvalvoja, voit luultavasti käyttää omaa osoitettasi. Osoitetta käytetään vain komentosarjassa asetusten tekemiseen Microsoft 365/Exchange Adminissa.

  3. Microsoft 365 -verkkotunnus

    Yleensä sama verkkotunnus kuin järjestelmänvalvojatilin sähköpostiosoitteessa.

  4. Tällä hetkellä ensisijaisena lähettäjänä käytetty sähköpostiosoite

    Tätä sähköpostiosoitetta käytetään ensisijaisesti Opterin sähköpostien lähettämiseen. Se löytyy kentästä S-posti välilehdeltä Yleinen Opterin toimistoasetuksissa.

    Opter-järjestelmän omistaja tietää, mitä lähettäjäosoitteita Opter käyttää.

    Esimerkiksi laskuja on mahdollista lähettää eri lähettäjän osoitteesta ( S-posti -kenttä Laskun yksityiskohdat -välilehdellä toimiston asetuksissa), mutta se on lisättävä Microsoft 365:een jälkikäteen. Voit lisätä sähköpostiosoitteen vain skriptin avulla. Lisätietoa: Vaihtoehtoiset lähettäjän osoitteet alla.

Vaihe 2: Avaa Windows Powershell

Etsi Windowsin Käynnistä-valikosta"windows powershell" ja avaa Windows PowerShell, ei Windows PowerShell ISE.

Komentorivi avautuu. Aseta RemoteSigned-oikeus liittämällä alla oleva teksti komentoriville ja painamalla Enter. Lisätietoja oikeuksista on saatavilla Microsoftin verkkosivustolla.

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Kun olet suorittanut skriptin, voit palauttaa oikeudet komennolla Set-ExecutionPolicy Restricted -Scope CurrentUser.

Vaihe 3: Suorita skripti

Kopioi ja tallenna seuraava skripti PS1-tiedostona tietokoneellesi. Suorita se sitten Windows PowerShellistä liittämällä polku komentoriville ja painamalla Enteriä.

Skripti käyttää tiettyjen komponenttien tiettyjä versioita. Sinun on mahdollisesti ensin poistettava jo asennetut komponentit (skriptissä on apukoodi).

Koska skripti pakottaa komponenttien tietyt versiot, se saattaa "häiritä" PowerShellin senhetkistä ympäristöä, ja se on palautettava manuaalisesti. Jos sinulla on PowerShell-ympäristö, jota käytetään tuotannossa ja jota ei saa häiritä, voit suorittaa skriptin virtuaalisella tietokoneella.

#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()

Sinulta kysytään, haluatko asentaa moduulit, ja sinun on vastattava kyllä.

Kun saat kehotuksen syöttää vaiheessa 1 selvittämiäsi tietoja, kuten Azure tenant ID:n, kopioi ja liitä ne ja paina Enteriä, jolloin skriptin suorittaminen jatkuu.

Mitä skripti tekee?

Jaamme sen lohkoihin.

  • Rivit 20-70 asentavat MS Graph -moduulit PowerShelliä varten. Niitä tarvitaan, jotta skriptin loppuosa toimii. Moduulit sijoitetaan polulle C:\Program Files\WindowsPowerShell\Modules\.

  • Riveillä 72-77 kirjaudutaan Microsoft Entra ID:hen (entinen Azure Active Directory).

  • Rivit 80-119 rekisteröivät Opterin sovellukseksi Azuressa nimellä "OpterMessageProxy" ja antavat sovellukselle oikeuden lähettää sähköposteja. Voit muuttaa nimen "OpterMessageProxy" joksikin muuksi rivillä 81, mutta on helpompaa säilyttää oletusnimi, jos sinun on joskus otettava yhteys tukeen.

  • Rivit 132-142 lisäävät OpterMessageProxyn Exchange-käyttäjäoikeusryhmään, jolla on rajoitetut oikeudet.

  • Riveillä 144-224 näytetään tiedot, jotka on syötettävä Opterin toimistoasetuksiin (välilehti Palvelimet). Tiedot kopioidaan leikepöydälle, mutta ne voidaan kopioida myös avautuvasta valintaikkunasta. Älä sulje valintaikkunaa ennen kuin olet syöttänyt tiedot toimiston asetuksiin. Tai voit liittää tiedot tekstitiedostoon tai muuhun paikkaan, josta voit myöhemmin kopioida ne.

    Asiakasluottamuksellisuutta ei voi hakea tai palauttaa. Jos et liitä sitä mihinkään, sinun on luotava uusi Azure-portaalissa. Muut tiedot voidaan tarvittaessa hakea Azure-portaalista jälkikäteen.

Vaihe 4: Yhdistä Opter ja Microsoft 365/MS Graph

Napsauta Asetukset > Toimistot > Palvelimet -välilehteä ja täytä seuraavat kentät tekstitiedostoon liittämilläsi tiedoilla:

  • Ms Graph Tenant Id

  • Ms Graph Client Id

  • Ms Graph Client Secret

Napsauta sitten kohtaa Testaa sähköposti, kirjoita itsesi vastaanottajaksi ja tarkista, että saat viestin.

Jos kentässä Ms Graph Tenant Id on arvo, ei ole väliä, onko tämän välilehden yläpuolella olevat kentät täytetty (SMTP-palvelin, Portti, Käyttäjänimi, Salasana ja Suojattu lähetys (SSL)). Näitä tietoja ei käytetä, vaan todennus tapahtuu sovelluksen rekisteröinnin kautta Azuressa. Voi olla hyödyllistä poistaa niissä olevat tiedot, jotta väärinkäsityksiä ei pääse syntymään.

Vaihe 5: Anna OpterMessageProxy-sovellukselle järjestelmänvalvojan oikeudet.

Kirjaudu sisään osoitteeseen portal.azure.com ja etsi "OpterMessageProxy". Siirry vasemmanpuoleisessa valikossa kohtaan API permissions ja napsauta kohtaa Grant admin consent for {0}

Sovelluksen rekisteröinti Azuressa

Löydät sovelluksen rekisteröinnin osoitteessa portal.azure.com etsimällä hakusanalla "optermessageproxy" ja valitsemalla hakutuloksen, joka on merkitty Application. Voit myös siirtyä sovellusten rekisteröintiin ja tarkastella rekisteröityjen ohjelmien luetteloa.

Kohdassa OpterMessageProxy voit katsoa ja kopioida Ms Graph Tenant Id = Directory (tenant) ID (2) ja Ms Graph Client Id = Application (client) ID (1).

Kohdetta Ms Graph Client Secret ei voi tarkastella tai palauttaa Azure-portaalissa. Jos et liittänyt sitä skriptin suorittamisen jälkeen, sinun on luotava uusi luottamuksellisuus. Siirry vasemmanpuoleisessa valikossa kohtaan Manage (1) > Certificates & secrets (2) ja valitse New client secret. Sieltä voit myös tarkistaa, milloin asiakasluottamuksellisuus päättyy.

Useita verkkotunnuksia

Jos sinulla on useita verkkotunnuksia, esimerkiksi "budfirman.centraleurope.se" ja "budfirman.nordics.se", sinun on suoritettava skripti kerran jokaiselle verkkotunnukselle ja vaihdettava sovelluksen rekisteröinnin nimi joka kerta, kun suoritat sen. Ellei nimeä muuteta, edellinen sovelluksen rekisteröinti korvataan, kun komentosarja ajetaan uudelleen. Tee näin:

  1. Muuta komentosarjan riviä 81 siten, että nimi tunnistaa ensimmäisen verkkotunnuksen. Kuriiripalvelun osalta rivi 81 muutetaan seuraavasti:

    $appName = "OpterMessageProxy"

    osoitteeseen

    $appName = "OpterMessageProxy_centraleurope"

  2. Tallenna ja suorita skripti.

  3. Vaihda riville 81 seuraavan toimialueen nimi. Budfirmanin tapauksessa alkaen:

    $appName = "OpterMessageProxy_centraleurope"

    osoitteeseen

    $appName = "OpterMessageProxy_nordics"

  4. Tallenna ja suorita skripti uudelleen.

Nyt Azuressa on kaksi sovellusrekisteröintiä, joita voidaan hallita erikseen.

Vaihtoehtoiset lähettäjän osoitteet

Jos esimerkiksi haluat lähettää laskut Opterista eri osoitteella, esimerkiksi osoitteella invoice@budfirman.se, lisää vaihtoehtoiset osoitteet OpterMessageProxy_group-suojausryhmään Exchangessa. Jos muutit nimeä rekisteröidessäsi Opterin Azureen, ryhmän nimi on määrittelemäsi + "_group". Kaikkien Opteriin lisäämiesi lähettäjäosoitteiden on oltava suojaryhmän jäseniä.

Lisätietoja ja esimerkkejä eri lähettäjäosoitteiden lisäämisestä on kohdassa Vaihtoehtoiset sähköpostiosoitteet.

Lähettäjäosoitteen lisääminen OpterMessageProxy_group-ryhmän jäseneksi Exchange-hallintakeskuksessa. Lisätietoja on saatavilla Microsoftin verkkosivustolla.

Katso myös