Search code examples
powershellsmtpoffice365mailmessage

Supported way to send office 365 smtp email which allow us to attach a file


I have this code to send email with attachment:-

$encpassword = convertto-securestring -String "*****" -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "***@***", $encpassword
Connect-PnPOnline -Url $sourceWebURL -Credentials $cred
Send-MailMessage -to "" -from "" -Credentials $cred -bcc "" -Port "587" -UseSSL "true" -Subject "subject" -Body "<b>1</b><br><b>2</b>" -BodyAsHtml -SmtpServer "smtp.office365.com"  -Attachments "C:\s.csv"

but based on the documentation's warning that Send-MailMessage is obsolete @ https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage?view=powershell-7.3

and at the same time using Send-PnPMail does not support sending attachments @ https://pnp.github.io/powershell/cmdlets/Send-PnPMail.html .

so my question is how we can send an email using power shell using a supported/recommended approach which allow us to attach a file.

Thanks


Solution

  • What the Send-MailMessage documentation's warning that Send-MailMessage is obsolete fails to mention is the underlying reason as to why it is now obsolete. For example, Send-MailMessage still works just fine when you continue to connect to your on-premise Exchange Server so why the message?

    The reason is as part of Microsoft’s "Secure by Default" policy, Microsoft is permanently disabling Basic Authentication in Exchange Online for everyone on October 1, 2022 (Basic Authentication and Exchange Online – September 2021 Update - Microsoft Tech Community).

    This includes Exchange Web Services (EWS), Exchange ActiveSync (EAS), POP, IMAP, Remote PowerShell, MAPI, RPC, SMTP AUTH, and OAB. All client applications need to switch to Modern Authentication/OAuth or Microsoft Graph API to continue to function.

    Send-MailMessage uses Basic Authentication (Username and password with an option to use SSL) but wasn't made to use Modern Authentication methods. It was primarily designed to work with on-premise Exchange Servers and didn't have to worry about those pesky things like MFA or options for using key/value/tokens for authentication. Therefore, it's use is now obsolete when trying to use it with Exchange Online/O365 servers.


    The O365 supported method is to use Microsoft Graph to send the message with attachment. It's a little more complicated than a vanilla Send-MailMessage, because you need to use JSON to create the configuration. You also need to convert the file Attachment to a Base64 encoded string so that it can be added to the JSON message.

    Import-Module Microsoft.Graph.Users.Actions
    Connect-MgGraph
    
    #Convert File to Base64
    $filename = "C:\attachment.csv"
    $filenameBase64string = [Convert]::ToBase64String([IO.File]::ReadAllBytes($filename))
    
    $params = @{
        Message = @{
            Subject = "Important Attachment"
            Body = @{
                ContentType = "html"
                Content = "Please find <b>Important Document</b> attached"
            }
            ToRecipients = @(
                @{
                    EmailAddress = @{
                        Address = "[email protected]"
                    }
                }
            )
            Attachments = @(
                @{
                    "@odata.type" = "#microsoft.graph.fileAttachment"
                    Name = "attachment.csv"
                    ContentType = "text/plain"
                    ContentBytes = $filenameBase64string
                }
            )
        }
    }
    
    Send-MgUserMail -UserId [email protected] -BodyParameter $params