Entra / Microsoft 365 · Exchange Online
Send welcome email graph
Sends welcome mail to newly created mailboxes using Microsoft Graph mail send with an app registration.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-ExchangeOnline
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
param([string] $TenantId = "",[string] $AppId = "",[int] $LookbackDays = 7)$Modules = Get-ModuleIf ("ExchangeOnlineManagement" -notin $Modules.Name) {Write-Host "Please connect to Exchange Online Management before continuing...";break}# Date to Check for new accounts - we use the last 7 days here, but that's easily changable.[string]$CheckDate = (Get-Date).AddDays(-$LookbackDays)# Get Graph access token - change these values for the app you use.$AppSecret = "~_Q2.IPI3kpbmhOG.VtCb1r0_J9G4-D8jG"# Construct URI and body needed for authentication$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"$body = @{client_id = $AppIdscope = "https://graph.microsoft.com/.default"client_secret = $AppSecretgrant_type = "client_credentials"}$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing# Unpack Access Token$token = ($tokenRequest.Content | ConvertFrom-Json).access_token$Headers = @{'Content-Type' = "application\json"'Authorization' = "Bearer $Token" }# Define some variables for the message#HTML header with styles$htmlhead="<html><style>BODY{font-family: Arial; font-size: 10pt;}H1{font-size: 22px;}H2{font-size: 18px; padding-top: 10px;}H3{font-size: 16px; padding-top: 8px;}</style>"#Header for the message$HtmlBody = "<body><h1>Welcome to Our Company</h1><p><strong>Generated:</strong> $(Get-Date -Format g)</p><h2><u>We're Pleased to Have You Here</u></h2>"# Other lines$htmlline1 = "<p><b>Welcome to Office 365</b></p>"$htmlline2 = "<p>You can open Office Online by clicking <a href=https://www.office.com/?auth=2>here</a> </p>"$htmlline3 = "<p>Have a great time and be sure to call the help desk if you need assistance.</p>"# Find all mailboxes created in the target period[datetime]$DisplayDate = $CheckDateWrite-Host ("Finding User mailboxes created since {0}" -f (Get-Date($DisplayDate) -format g))$Users = (Get-ExoMailbox -Filter "WhenMailboxCreated -gt '$CheckDate'" -RecipientTypeDetails UserMailbox -ResultSize Unlimited -Properties WhenMailboxCreated | Select-Object WhenMailboxCreated, DisplayName, UserPrincipalName, PrimarySmtpAddress)If (!($Users)) {Write-Host "No users found - exiting" ; break} Else { Write-Host $Users.Count "mailboxes found to process"}# Mail.Send can send from any user. In this example, because we're sending messages to welcome people, we look up the mailboxes on the system to# find one tagged as the HR admin. You can use whatever method you like as long as the result is a resolveable SMTP address. If you use an application# access policy to restrict access to the API, make sure this user is included.$MsgFrom = Get-Recipient -Filter {CustomAttribute1 -eq "HRAdmin"} | Select-Object -ExpandProperty PrimarySmtpAddressIf ($null -eq $MsgFrom) { Write-Host "Can't find user defined as the sender for the messages - exiting!"; break}# Use the same approach to define CC recipients for the message$ccRecipient1 = Get-Recipient -Filter {CustomAttribute1 -eq "HRCC1"} | Select-Object -ExpandProperty PrimarySmtpAddress$ccRecipient2 = Get-Recipient -Filter {CustomAttribute1 -eq "HRCC2"} | Select-Object -ExpandProperty PrimarySmtpAddressIf (($null -eq $ccRecipient1 ) -or ($null -eq $ccRecipient2)) { Write-Host "CC Recipients are not defined. Exiting!" ; break}Write-Host "Messages will be sent from" $MsgFrom "and CC'd to" $ccRecipient1 "and" $ccRecipient2# Define attachment to send to new users$AttachmentFile = "C:\temp\WelcomeToOffice365ITPros.docx"$ContentBase64 = [convert]::ToBase64String( [system.io.file]::readallbytes($AttachmentFile))$SentMessages = 0# Create and send welcome message for each userForEach ($User in $Users) {$EmailRecipient = $User.PrimarySmtpAddressWrite-Host "Sending welcome email to" $User.DisplayName$MsgSubject = "A Hundred Thousand Welcomes to " + $User.DisplayName$htmlHeaderUser = "<h2>New User " + $User.DisplayName + "</h2>"$htmlline1 = "<p><b>Welcome to Office 365</b></p>"$htmlline2 = "<p>You can open Office Online by clicking <a href=https://www.office.com/?auth=2>here</a> </p>"$htmlline3 = "<p>Have a great time and be sure to call the help desk if you need assistance.</p>"$htmlbody = $htmlheaderUser + $htmlline1 + $htmlline2 + $htmlline3 + "<p>"$HtmlMsg = "</body></html>" + $HtmlHead + $HtmlBody# Create message body and properties and send$MessageParams = @{"URI" = "https://graph.microsoft.com/v1.0/users/$MsgFrom/sendMail""Headers" = $Headers"Method" = "POST""ContentType" = 'application/json'"Body" = (@{"message" = @{"subject" = $MsgSubject"body" = @{"contentType" = 'HTML'"content" = $htmlMsg }"attachments" = @(@{"@odata.type" = "#microsoft.graph.fileAttachment""name" = $AttachmentFile"contenttype" = "application/vnd.openxmlformats-officedocument.wordprocessingml.document""contentBytes" = $ContentBase64 } )"toRecipients" = @(@{"emailAddress" = @{"address" = $EmailRecipient }} )"ccRecipients" = @(@{"emailAddress" = @{"address" = $ccRecipient1 }} ,@{"emailAddress" = @{"address" = $ccRecipient2 }} )}}) | ConvertTo-JSON -Depth 6}# Send the messageInvoke-RestMethod @Messageparams$SentMessages++}Write-Host "All done." $SentMessages "welcome messages sent to happy users"
Parameters
ParameterDefaultNotes
-TenantId""Microsoft Entra tenant ID for app-only Graph authentication.-AppId""Application (client) ID for the app registration used to connect.-LookbackDays7How many days back to search for newly created mailboxes or recent activity.Attribution
Author
Office365itpros