Guide
New-MgUserMessage: Create Outlook Drafts
You typed Send-MgMessage and PowerShell said the term is not recognized. The cmdlet doesn't exist. Microsoft Graph PowerShell splits draft email work across New-MgUserMessage (create the draft), Update-MgUserMessage (edit it), and Send-MgUserMessage (dispatch it). This guide walks the full draft workflow: hashtable parameters, the scopes each step needs, attachments, and the 2-command CLI equivalent.
Written by Prem Keshari Senior SRE
Command references used in this guide: nylas email drafts create, nylas email drafts list, and nylas email drafts send.
What does New-MgUserMessage do?
New-MgUserMessage is the Microsoft Graph PowerShell cmdlet that creates a draft email in a mailbox without sending it. It wraps the Graph endpoint POST /users/{id}/messages, which per the create message reference lets you "create a draft of a new message in either JSON or MIME format" and "update the draft later to add content to the body or change other message properties." On success Graph returns 201 Created plus the full message object, including the draft's ID — the handle every later step uses.
The required permission is Mail.ReadWrite for delegated and application auth alike. That split matters for least-privilege setups: a script that only stages drafts for human review never needs Mail.Send at all. The Send-MgUserMail guide covers the immediate-send path; this page covers the 2-step draft workflow.
Why is Send-MgMessage not recognized?
Send-MgMessage doesn't exist in any Microsoft.Graph module, which is why PowerShell answers with CommandNotFoundException. Graph PowerShell cmdlet names encode the full resource path, and messages live under users — so every mail cmdlet carries the User segment. Three real cmdlets cover sending and drafting, and the wrong guess is usually a blend of two of them.
| Cmdlet | Graph endpoint | What it does |
|---|---|---|
New-MgUserMessage | POST /users/{id}/messages | Creates a draft; returns the message object (201) |
Send-MgUserMessage | POST /users/{id}/messages/{id}/send | Sends an existing draft (202, empty body) |
Send-MgUserMail | POST /users/{id}/sendMail | Composes and sends in one call — no draft step |
Send-MgMessage | — | Does not exist; CommandNotFoundException |
Quick disambiguation: sending one email now means Send-MgUserMail. Staging email for review before it leaves the mailbox means New-MgUserMessage followed by Send-MgUserMessage. Run Get-Command -Module Microsoft.Graph.Mail to list the roughly two dozen mail cmdlets actually installed and stop guessing names.
How do you create a draft with New-MgUserMessage?
Creating a draft takes 1 cmdlet call with hashtable parameters for the body and recipients. The draft appears in the mailbox's Drafts folder immediately, visible in Outlook, and stays there until something sends or deletes it. Capture the return value — the draft ID in $draft.Id is required for every follow-up step.
Connect-MgGraph -Scopes "Mail.ReadWrite"
$draft = New-MgUserMessage -UserId "me@contoso.com" `
-Subject "Q3 capacity plan — for review" `
-Body @{
ContentType = "Text"
Content = "Draft of the capacity plan summary. Numbers attached."
} `
-ToRecipients @(
@{ EmailAddress = @{ Address = "ops-lead@contoso.com" } }
)
$draft.Id # e.g. AAMkAGI2... — keep thisEditing the draft later uses Update-MgUserMessage with the same hashtable shapes (its cmdlet reference documents every updatable property). That two-phase pattern (create now, refine later) is what the draft endpoint exists for, and it's the property the one-shot Send-MgUserMail can't give you.
How do you add an attachment to the draft?
Attachments are added to an existing draft with New-MgUserMessageAttachment, documented in its cmdlet reference. The file content travels base64-encoded inside a #microsoft.graph.fileAttachment object, so the 2 lines below read the file as bytes and encode them with [Convert]::ToBase64String before the upload.
$bytes = [System.IO.File]::ReadAllBytes("C:\reports\capacity.xlsx")
New-MgUserMessageAttachment -UserId "me@contoso.com" -MessageId $draft.Id `
-BodyParameter @{
"@odata.type" = "#microsoft.graph.fileAttachment"
Name = "capacity.xlsx"
ContentBytes = [Convert]::ToBase64String($bytes)
}How do you send the draft with Send-MgUserMessage?
Send-MgUserMessage dispatches the draft by ID. The underlying message: send reference states it sends "an existing draft message" (new, reply, reply-all, and forward drafts all qualify) and "saves the message in the Sent Items folder." Success returns 202 Accepted with an empty response body, so don't parse the output for a message object that isn't there.
# Requires the Mail.Send scope (Mail.ReadWrite alone cannot send)
Connect-MgGraph -Scopes "Mail.ReadWrite", "Mail.Send"
Send-MgUserMessage -UserId "me@contoso.com" -MessageId $draft.IdThe scope boundary is the workflow's security feature. A nightly report generator can run under Mail.ReadWrite and produce drafts all week, while the send step lives in a separate session, or with a separate human, holding Mail.Send. Calling Send-MgUserMessage without that scope fails with ErrorAccessDenied, which is exactly the failure you want from a compromised draft generator.
How does the CLI handle the same draft workflow?
The nylas email drafts command group covers the create-review-send loop in 2 commands with no hashtable scaffolding, and the same syntax works on Gmail, iCloud, and IMAP accounts, not just Outlook. Authentication is one nylas auth login instead of an Entra app registration. The hashtable draft above becomes a single flag-based call.
# Create the draft
nylas email drafts create \
--to ops-lead@contoso.com \
--subject "Q3 capacity plan — for review" \
--body "Draft of the capacity plan summary."
# List pending drafts, grab the ID
nylas email drafts list --json | jq -r '.[] | "\(.id) \(.subject)"'
# Send after review
nylas email drafts send DRAFT_IDThis draft-then-send separation is also the human-in-the-loop pattern for AI agents: the agent holds only the draft tool, a person runs the send. The prompt injection defense guide builds that argument in full.
Next steps
- Send-MgUserMail: Graph Email in PowerShell — the one-call send path, delegated and app-only auth
- Replace Send-MgUserMessage — migrate draft-send scripts to a shorter CLI pipeline
- Manage email drafts from the CLI — list, edit, and batch-send drafts across providers
- PowerShell email guide — every method for sending email from PowerShell, compared
- Full command reference — flags and examples for every drafts subcommand