![]() |
VOOZH | about |
dotnet add package Mailozaurr.Msg --version 2.0.10
NuGet\Install-Package Mailozaurr.Msg -Version 2.0.10
<PackageReference Include="Mailozaurr.Msg" Version="2.0.10" />
<PackageVersion Include="Mailozaurr.Msg" Version="2.0.10" />Directory.Packages.props
<PackageReference Include="Mailozaurr.Msg" />Project file
paket add Mailozaurr.Msg --version 2.0.10
#r "nuget: Mailozaurr.Msg, 2.0.10"
#:package Mailozaurr.Msg@2.0.10
#addin nuget:?package=Mailozaurr.Msg&version=2.0.10Install as a Cake Addin
#tool nuget:?package=Mailozaurr.Msg&version=2.0.10Install as a Cake Tool
Mailozaurr is available as a NuGet package and as a PowerShell module from PSGallery.
NuGet Package
👁 nuget downloads
👁 nuget version
PowerShell Module
👁 powershell gallery version
👁 powershell gallery preview
👁 powershell gallery platforms
👁 powershell gallery downloads
Project Information
👁 build status
👁 codecov
👁 top language
👁 license
👁 code size
Author and Social
👁 Twitter follow
👁 Blog
👁 LinkedIn
👁 Discord
Mailozaurr provides SMTP, POP3, IMAP, Microsoft Graph mail support, and mail-format tooling for PowerShell and .NET. Underneath it uses MimeKit and MailKit libraries written by Jeffrey Stedfast.
This repository has two branches:
v1-legacy: old module generation, written in PowerShell and still maintained until V2 is finalized.v2-speedygonzales: current rewrite in C# with newer functionality and better performance.In V2, some functionality was moved to dedicated projects:
For OAuth2 support, Mailozaurr also bundles:
Additional dependency:
Mailozaurr is no longer only a library and PowerShell module. The repository now also contains shared application-layer work and headless surfaces for broader automation scenarios:
.NET library for direct application and service integrationPowerShell module for administrators and automation usersmailozaurr executable for cross-platform CLI workflowsmailozaurr mcp serve for MCP-based integrationsCLI and MCP are intended to sit on top of shared Mailozaurr services instead of duplicating mailbox, draft, queue, send, and message-action behavior independently.
If you want the placement rules and longer-term cross-surface direction, see . If you want practical profile setup and usage guidance for CLI and MCP, see .
The repository now includes a cross-platform mailozaurr executable and an MCP server hosted by that same executable.
To see the current command surface from source:
dotnet run --project Sources/Mailozaurr.Cli -- --help
After building, the executable is available at:
Sources/Mailozaurr.Cli/bin/Debug/net8.0/mailozaurr.exe on WindowsSources/Mailozaurr.Cli/bin/Debug/net8.0/mailozaurr on macOS/LinuxThe executable currently supports:
profile ... for profile creation, bootstrap, login, auth refresh, readiness checks, summaries, validation, and secret managementdraft ... for saving, listing, exporting, importing, and deleting reusable draftssend ... for sending from a stored draft, a draft file, or direct command-line fieldsqueue ... for viewing and processing queued outbound messagesmail ... for folders, folder aliases, search, message retrieval, attachment export, mailbox actions, previews, and reusable action-plan batchesmcp serve for exposing the same shared services as MCP tools over stdioMost list and inspection commands support --json, which makes the executable useful in scripts, CI, and other automation surfaces.
Create a profile and inspect it:
mailozaurr profile create --profile work-imap --kind imap --name "Work IMAP" `
--setting server=imap.example.com --setting port=993 --json
mailozaurr profile set-secret --profile work-imap --name password --value "secret" --json
mailozaurr profile summary --profile work-imap --json
mailozaurr profile test --profile work-imap --scope mailbox --json
Search and inspect mail:
mailozaurr mail folders --profile work-imap --compact --json
mailozaurr mail search --profile work-imap --folder Inbox --query Invoice --compact --json
mailozaurr mail get --profile work-imap --folder Inbox --message-id 123 --compact --json
mailozaurr mail attachments --profile work-imap --folder Inbox --message-id 123 --json
mailozaurr mail save-attachments --profile work-imap --folder Inbox --message-id 123 --path C:\Temp\Attachments --json
Draft, send, and queue mail:
mailozaurr draft save --draft weekly-update --name "Weekly update" --profile work-smtp `
--to team@example.com --subject "Weekly update" --text "Status attached." --json
mailozaurr send --draft weekly-update --json
mailozaurr queue list --compact --json
mailozaurr queue process --json
Preview and execute mailbox actions:
mailozaurr mail preview-delete --profile work-imap --folder Inbox --message-id 123 --json
mailozaurr mail delete --profile work-imap --folder Inbox --message-id 123 --confirm-token <token> --json
mailozaurr mail preview-move --profile work-imap --folder Inbox --message-id 123 --target-folder Archive --json
mailozaurr mail move --profile work-imap --folder Inbox --message-id 123 --target-folder Archive --confirm-token <token> --json
Mailozaurr can also run as an MCP server over stdio:
mailozaurr mcp serve
The MCP surface is built on top of the same shared services as the CLI. Current tool areas include:
A minimal MCP client entry typically points to the executable and passes mcp serve as arguments:
{
"command": "mailozaurr",
"args": ["mcp", "serve"]
}
If your client prefers an absolute path, point it to the built executable instead.
Skills are a good fit on top of the MCP server, but they are not a replacement for the server itself.
mailozaurr mcp serve provides the actual mailbox and send toolsIn practice, that means Mailozaurr should own the reusable mailbox, queue, send, and action logic, while skills can teach an agent how to use those tools safely and consistently.
This started with a single goal to replace Send-MailMessage which is deprecated/obsolete with something more modern, but since MailKit and MimeKit have lots of options why not build on that?
If you find this project helpful, please consider supporting its development. Your sponsorship will help the maintainers dedicate more time to maintenance and new feature development for everyone.
It takes a lot of time and effort to create and maintain this project. By becoming a sponsor, you can help ensure that it stays free and accessible to everyone who needs it.
To become a sponsor, you can choose from the following options:
Your sponsorship is completely optional and not required for using this project. We want this project to remain open-source and available for anyone to use for free, regardless of whether they choose to sponsor it or not.
If you work for a company that uses our .NET libraries or PowerShell Modules, please consider asking your manager or marketing team if your company would be interested in supporting this project. Your company's support can help us continue to maintain and improve this project for the benefit of everyone.
Thank you for considering supporting this project!
To build a project and play with the sources you need to:
Install-Module PSPublishModule -Force -Verbose
Once the module is installed - go to Build folder and run: Manage-Mailozaurr.ps1.
This will make sure the project has required libraries.
Send-EmailMessage) using:
Send-EmailMessage via -RetryCount, -RetryDelayMilliseconds, -RetryDelayBackoff and -RetryAlways. Retries are only attempted for transient errors by default, but -RetryAlways forces retries on all errors.-UseConnectionPool and -ConnectionPoolSize for faster repeated sends. Use Clear-SmtpConnectionPool to reset the pool and Test-SmtpConnection to check if your server keeps connections open.Get-POP3Message -DeleteWait-POP3Message cmdlet supporting -Until, -StopOnMatch and -TimeoutSecondsSearch-POP3Mailbox returning messages (use -Count to limit results)Get-IMAPFolder -RootGet-IMAPMessage -DeleteImapIdleListenerWait-IMAPMessage cmdlet supporting -Until, -StopOnMatch and -TimeoutSecondsSearch-IMAPMailbox returning messages (use -Count to limit results)Get-EmailGraphFolder with -Connection or -MgGraphRequestSet-GraphMessageWait-GraphMessage cmdletSearch-GraphMailbox returning message info (use -Count to limit results)$graph = Connect-EmailGraph -Credential $cred
$graph | Get-EmailGraphFolder -UserPrincipalName 'user@example.com'
$graph | Get-EmailGraphMessage -UserPrincipalName 'user@example.com' -Limit 10 |
Save-GraphMessage -Path 'C:\Archive'
Both Connect-IMAP and Connect-POP3 support a variety of sign-in methods. You can use plain credentials, pass a PSCredential object, or supply an OAuth token.
# Username and password
$imap = Connect-IMAP -Server 'imap.example.com' -UserName 'user@example.com' -Password 'p@ssword'
# Credential object
$cred = Get-Credential
$pop3 = Connect-POP3 -Server 'pop.example.com' -Credential $cred
# OAuth2 token with a SecureString client secret
$googleClientSecret = Read-Host 'Google client secret' -AsSecureString
$oauth = Connect-OAuthGoogle -ClientId 'id' -ClientSecretSecureString $googleClientSecret -GmailAccount 'user@example.com' -Scope https://mail.google.com/
$imapOAuth = Connect-IMAP -Server 'imap.gmail.com' -Credential $oauth -OAuth2
After connecting you can list the top-level folders:
$client = Connect-IMAP -Server 'imap.example.com' -Credential $cred
Get-IMAPFolder -Client $client -Root
Using OAuth tokens works the same:
$token = Connect-OAuthGoogle -ClientId 'id' -ClientSecretSecretName 'gmail-client-secret' -ClientSecretVaultName 'MailSecrets' -GmailAccount 'user@example.com' -Scope https://mail.google.com/
$client = Connect-IMAP -Server 'imap.gmail.com' -Credential $token -OAuth2
Get-IMAPFolder -Client $client -Root
You can also open a specific folder by path:
$client = Connect-IMAP -Server 'imap.example.com' -Credential $cred
Get-IMAPFolder -Client $client -Path 'Inbox/Reports'
Once a folder is opened you can retrieve its messages using Get-IMAPMessage.
# Inbox messages
$client = Connect-IMAP -Server 'imap.example.com' -Credential $cred
Get-IMAPFolder -Client $client
Get-IMAPMessage -Client $client
# Nested folder
Get-IMAPFolder -Client $client -Path 'Inbox/Reports/2024'
Get-IMAPMessage -Client $client
# Sent and deleted items
Get-IMAPFolder -Client $client -Path 'Sent'
Get-IMAPMessage -Client $client
Get-IMAPFolder -Client $client -Path 'Deleted Items'
Get-IMAPMessage -Client $client
The ImapIdleListener class uses the IMAP IDLE command to raise events whenever
new mail arrives. Create an instance with your connected ImapClient, subscribe
to MessageArrived, and call StartAsync:
using var client = new ImapClient();
await client.ConnectAsync("imap.example.com", 993, SecureSocketOptions.SslOnConnect);
await client.AuthenticateAsync("user@example.com", "password");
var listener = new Mailozaurr.ImapIdleListener(client);
listener.MessageArrived += (s, msg) =>
Console.WriteLine($"New message: {msg.Message.Subject}");
await listener.StartAsync();
Call Stop() to end listening. See
Sources/Mailozaurr.Examples/ImapIdleListenerExample.cs for a full example.
Alternatively, use the PowerShell cmdlet Wait-IMAPMessage to output new
messages directly to the pipeline:
$cred = Get-Credential
$client = Connect-IMAP -Server 'imap.example.com' -Credential $cred
Wait-IMAPMessage -Client $client -Until { $_.Message.From.Mailboxes.Address -contains 'alice@example.com' } -StopOnMatch -TimeoutSeconds 600 -Action { param($m) "New IMAP from Alice: $($m.Message.Subject)" }
Press <kbd>Ctrl+C</kbd> to stop waiting for messages.
The same concept applies to POP3, IMAP and Microsoft Graph mailboxes. Wait-POP3Message, Wait-IMAPMessage and Wait-GraphMessage all support -Until, -StopOnMatch and -TimeoutSeconds parameters so you can wait for specific senders or stop after a period of time:
$cred = Get-Credential
$graph = Connect-EmailGraph -Credential $cred
Wait-GraphMessage -Connection $graph -UserPrincipalName 'user@example.com' -Until { $_.from.emailAddress.address -eq 'alice@example.com' } -StopOnMatch -TimeoutSeconds 600 -Action {
param($m)
"Graph from Alice: $($m.subject)"
}
Mailozaurr v2 includes a built‑in policy for Microsoft Graph sends that handles throttling and transient errors:
PowerShell
# Graph send with conservative retry/backoff and concurrency
$cred = ConvertTo-GraphCredential -ClientId $ClientId -SecretName 'graph-client-secret' -VaultName 'MailSecrets' -DirectoryId $TenantId
Send-EmailMessage -Graph -From 'sender@example.com' -To 'user@example.com' `
-Credential $cred -HTML '<b>Hello</b>' -Subject 'Graph policy demo' `
-RetryCount 4 -RetryDelayMilliseconds 1000 `
-JitterMilliseconds 500 -MaxDelayMilliseconds 30000 `
-GraphMaxConcurrency 2 -Verbose
# Optional: SMTP fallback when Graph keeps failing (configure once)
[Mailozaurr.MailozaurrOptions]::SmtpFallbackFactory = {
param($graph)
$s = [Mailozaurr.Smtp]::new()
$s.Connect('smtp.office365.com', 587)
$s.Authenticate([System.Net.NetworkCredential]::new('user','pass'))
$s
}
Send-EmailMessage -Graph -EnableSmtpFallback -From 'sender@example.com' -To 'user@example.com' `
-Credential $cred -HTML '<b>Hello via fallback</b>' -Subject 'Graph+SMTP fallback'
# Same jitter/max-delay knobs also apply to SMTP/SendGrid/Mailgun/SES
Send-EmailMessage -Server 'smtp.office365.com' -Port 587 -UseSsl `
-From 'sender@example.com' -To 'user@example.com' -Credential (Get-Credential) `
-RetryCount 4 -RetryDelayMilliseconds 2000 -JitterMilliseconds 400 -MaxDelayMilliseconds 30000
C# (Graph)
using Mailozaurr;
var policy = new GraphSendPolicy {
MaxConcurrency = 2,
MaxRetries = 4,
BaseDelayMs = 1000,
MaxDelayMs = 30000,
JitterMs = 500,
RetryOnTransient = true,
EnableSmtpFallback = true
};
var graph = new Graph()
.WithSendPolicy(policy)
.WithSmtpFallback(() => {
var s = new Smtp();
s.Connect("smtp.office365.com", 587);
s.Authenticate("user@example.com", "password");
return s;
});
graph.From = "sender@example.com";
graph.To = new object[] { "user@example.com" };
graph.Subject = "Graph policy demo";
graph.HTML = "<b>Hello</b>";
graph.Authenticate(new System.Net.NetworkCredential("clientid@tenant.onmicrosoft.com", "client-secret"));
await graph.ConnectO365GraphAsync();
await graph.SendMessageAsync();
Notes
MailozaurrOptions.DefaultGraphPolicy in code.Invoke‑MgGraphRequest scenarios, use -GraphMaxConcurrency to keep batch operations within Graph tenancy limits.$cred = Get-Credential
$client = Connect-POP3 -Server 'pop.example.com' -Credential $cred
Wait-POP3Message -Client $client -Until { $_.Message.From.Mailboxes.Address -contains 'alice@example.com' } -StopOnMatch -TimeoutSeconds 600 -Action {
param($m)
"POP3 from Alice: $($m.Message.Subject)"
}
PGP/MIME encryption allows securing messages using public and private keys. To sign and encrypt a message provide paths to the public and secret key files:
$pub = 'Examples/PGPKeys/mimekit.gpg.pub'
$sec = 'Examples/PGPKeys/mimekit.gpg.sec'
Send-EmailMessage -From 'mimekit@example.com' -To 'mimekit@example.com' \
-Server 'smtp.example.com' -Port 25 -Body 'Test' -Subject 'Test' \
-SignOrEncrypt PgpSignAndEncrypt -PublicKeyPath $pub -PrivateKeyPath $sec \
-PrivateKeyPassword 'no.secret'
While I didn't spent much time creating WIKI, working on Get-Help documentation, I did write blog articles that should help you get started.
You can also utilize Examples which should help to understand use cases. Of course it would be great having pretty help so if you can help me out feel free to submit PR's.
-Connection or -MgGraphRequest.-MgGraphRequest switch.Connect-EmailGraph and Disconnect-EmailGraph to authenticate and release application credentials for Microsoft Graph. The connection cmdlet supports both client secret and certificate authentication modes.Connect-EmailGraph, Connect-IMAP and Connect-POP3 store the last successful connection in module variables. Subsequent cmdlets use these defaults when -Connection or -Client is omitted.-Some useful examples:
Examples/Example-AcquireO365TokenInteractive.ps1 – demonstrates Connect-OAuthO365, ConvertFrom-OAuth2Credential, and using the token with Send-EmailMessage, IMAP, and POP3.Examples/Example-AcquireGoogleTokenInteractive.ps1 – demonstrates Connect-OAuthGoogle, ConvertFrom-OAuth2Credential, and using the token with Send-EmailMessage, IMAP, and POP3.Sources/Mailozaurr.Examples/AcquireO365TokenInteractive.cs – C# sample for OAuthHelpers.AcquireO365TokenInteractiveAsync.Sources/Mailozaurr.Examples/AcquireGoogleTokenInteractive.cs – C# sample for OAuthHelpers.AcquireGoogleTokenInteractiveAsync.Sources/Mailozaurr.Examples/SendEmailAttachments.cs – C# sample demonstrating attachments and inline resources.-Graph and -MgGraphRequestThe module supports two ways of calling Microsoft Graph. Use -Graph when you connect with Connect-EmailGraph and provide credentials created with ConvertTo-GraphCredential or ConvertTo-GraphCertificateCredential. The -MgGraphRequest switch is meant for scenarios where you authenticate through the Microsoft Graph PowerShell SDK using Connect-MgGraph.
| Parameter | Connect command | When to use |
|---|---|---|
-Graph |
Connect-EmailGraph |
Application or certificate authentication handled by Mailozaurr. |
-MgGraphRequest |
Connect-MgGraph |
Already authenticated via the Microsoft Graph PowerShell SDK. |
Example using -Graph
$cred = ConvertTo-GraphCredential -ClientId $ClientId -SecretName 'graph-client-secret' -VaultName 'MailSecrets' -DirectoryId $TenantId
Connect-EmailGraph -Credential $cred
Send-EmailMessage -From 'user@example.com' -To 'user@example.com' -Subject 'Graph Test' -Graph
Disconnect-EmailGraph
Example using -MgGraphRequest
Import-Module Microsoft.Graph.Authentication
Connect-MgGraph -Scopes Mail.Send -NoWelcome
Send-EmailMessage -From 'user@example.com' -To 'user@example.com' -Subject 'Graph Test' -MgGraphRequest
Get-EmailGraphMessage supports the -Filter parameter for raw OData queries. This value is passed directly to Microsoft Graph's $filter option.
Get-EmailGraphMessage -UserPrincipalName 'user@example.com' -Filter "receivedDateTime ge 2024-01-01T00:00:00Z and contains(subject,'Invoice')"
See the Microsoft Graph query parameters documentation for details.
Keep in mind PSSharedGoods is only required for development. When you use this module from PowerShellGallery it's not installed as everything is merged.
You can reuse SMTP connections by enabling the connection pool with the -UseConnectionPool switch of Send-EmailMessage. The -ConnectionPoolSize parameter controls how many connections are kept alive. Use Test-SmtpConnection to examine the banner and capabilities and to check whether the connection remains open after a NOOP command. If the returned object has Persistent set to True, you can safely enable pooling. Call Clear-SmtpConnectionPool whenever you need to discard existing pooled clients.
Microsoft Graph API requires Send.Mail permission to send emails. In some cases Mail.ReadWrite permission is also required when the size of email is above 4MB.
If the application is registered in Azure AD (Entra ID) without any additional configuration, it will have access to all mailboxes in the organization.
To limit access to specific mailboxes, you need to use Application Access Policy.
This is a feature that allows you to limit access to specific mailboxes. You can read more about it here.
Following permissions (as shown on the screenshot) are required to send emails using Microsoft Graph API.
The rest of the permissions is not required and is there for other features that Microsoft Graph provides.
Install-Module -Name Mailozaurr -AllowClobber -Force
Force and AllowClobber aren't necessary, but they do skip errors in case some appear.
Update-Module -Name Mailozaurr
That's it. Whenever there's a new version, you run the command, and you can enjoy it. Remember that you may need to close, reopen PowerShell session if you have already used module before updating it.
The essential thing is if something works for you on production, keep using it till you test the new version on a test computer. I do changes that may not be big, but big enough that auto-update may break your code. For example, a small rename to a parameter, and your code stops working! Be responsible!
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 was computed. |
| .NET Framework | net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 is compatible. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.