Skip to content

Sending Email from a Microsoft 365 Shared Mailbox Using C# and Microsoft Graph

A Complete Guide for Developers (Shared Mailbox + Azure App Registration + Graph API)
Sending email from a shared mailbox (e.g., no-reply@yourdomain.com) through a backend application is a very common requirement in modern systems — especially for automated notification systems, workflows, and customer-facing apps.

But getting all the Microsoft 365 configuration correct can be tricky.

This guide gives you one clear, end-to-end setup that works reliably in .NET 8/10 Web APIs, Azure-hosted services, microservices, and on-prem systems.

We will cover:

  1. Why send email using a shared mailbox
  2. Creating the shared mailbox
  3. Setting up an Azure App Registration
  4. Granting Graph API permissions
  5. Creating a Distribution Group
  6. Creating an Application Access Policy
  7. Setting mailbox permissions for users
  8. C# implementation using Microsoft Graph SDK
  9. Advantages of this approach

Let’s get started.

Why Use a Shared Mailbox Instead of a Regular User Account?

A shared mailbox is ideal for system emails:

  • No license required
  • Not tied to a specific employee
  • Centralized and auditable
  • Can be managed by admins
  • Supports “Send As” and “Send on Behalf”
  • Works perfectly with Microsoft Graph

By combining a shared mailbox with an Azure App Registration, your backend app can send emails without storing passwords, without SMTP, and without MFA issues.

Step 1 — Create a Shared Mailbox

In the Microsoft 365 Admin Center:
Teams & Groups → Shared Mailboxes → Add a shared mailbox

Example:

  • Name: No Reply
  • Email: no-reply@yourdomain.com

Shared mailboxes do not have passwords or logins.


Step 2 — Create an App Registration in Azure

Go to Azure Portal → Azure Active Directory → App registrations → New registration

  • Name: MindAurora Email Service
  • Type: Accounts in this organization directory only
  • No redirect URI needed

After creation, save:

  • Client ID
  • Tenant ID

Generate a Client Secret:
Azure AD → App → Certificates & Secrets → New client secret

Store securely (KeyVault recommended). Make sure you store the secret somewhere as you can only see it once in the Azure Portal.


Step 3 — Add Graph API Application Permissions

Go to:
Azure AD → App → API Permissions → Add permission → Microsoft Graph → Application

Add:

  • Mail.Send

Click Grant admin consent.

❗Important
Use Application permissions, not delegated.
Backend services should not impersonate a logged-in user.


Step 4 — Create a Mail-Enabled Security Group

Application Access Policies cannot be assigned directly to mailboxes.
They must target a mail-enabled security group.
In Microsoft 365 Admin Center:

Teams & Groups → Add group

  • Type: Security
  • Name: MailSenders
  • Email: mailsenders@yourdomain.com
  • Enable “Mail Enabled”

Then add the shared mailbox as a member:
no-reply@yourdomain.com


Step 5 — Create an Application Access Policy

This step tells Exchange:
“This App Registration is allowed to access only the mailboxes in this group.”

Open PowerShell:

Install-Module ExchangeOnlineManagement
Connect-ExchangeOnline


Create policy:
Where ‘PolicyScoreGroupId’ is the name of the Mail-Enabled Security group/

New-ApplicationAccessPolicy `
    -AppId "<CLIENT-ID>" `
    -PolicyScopeGroupId "mailsenders@yourdomain.com" `
    -AccessRight RestrictAccess `
    -Description "Allow app to send mail via no-reply shared mailbox"

Test:

Test-ApplicationAccessPolicy `
    -Identity no-reply@yourdomain.com `
    -AppId "<CLIENT-ID>"

Expected:

AccessCheckResult : Granted

Step 6 — (Optional) Grant Mailbox Permissions to Users

If people also need to send from this mailbox manually, or see the mailbox, you need to use powershell to give acces.
❗Important: Never do this via Microsoft Portal, always use PowerShell. If you use the Microsoft Portal you can break the permissions for your App Registration.

PowerShell:

Add-MailboxPermission -Identity sharedmailbox@yourdomain.com -User UserIdFromPortal -AccessRights FullAccess

Step 7 — C# Integration Using Microsoft Graph SDK

Install package:

dotnet add package Microsoft.Graph
dotnet add package Azure.Identity

Code:

using Azure.Identity;
using Microsoft.Graph;

public class EmailService
{
    private readonly GraphServiceClient _graph;

    public EmailService(string tenantId, string clientId, string clientSecret)
    {
        var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);

        _graph = new GraphServiceClient(credential);
    }

    public async Task SendEmailAsync()
    {
        var message = new Message
        {
            Subject = "Hello from the shared mailbox",
            Body = new ItemBody
            {
                ContentType = BodyType.Html,
                Content = "<h1>Hello World!</h1><p>This email was sent from a .NET 10 API.</p>"
            },
            ToRecipients =
            [
                new Recipient
                {
                    EmailAddress = new EmailAddress
                    {
                        Address = "recipient@example.com"
                    }
                }
            ]
        };

        await _graph.Users["no-reply@yourdomain.com"]
            .SendMail
            .PostAsync(new Microsoft.Graph.Users.Item.SendMail.SendMailPostRequestBody
            {
                Message = message,
                SaveToSentItems = true
            });
    }
}

This sends an email as the shared mailbox, using only the App Registration credentials.
No passwords.
No SMTP.
No MFA issues.
No local Outlook profiles.

Advantages of This Approach

✔ 1. No passwords — ever

Using the Graph API + App Registration avoids storing or emailing credentials.

✔ 2. MFA safe

MFA breaks SMTP, but Application Permissions with Graph are fully compatible.

✔ 3. Secure and compliant

Application Access Policies enforce least privilege, limiting mailbox access.

✔ 4. Works from any environment

Docker, Azure Functions, Kubernetes, IIS, Windows services — all supported.

✔ 5. Centralized identity and auditing

Shared mailbox activity is trackable in Microsoft 365 compliance logs.

✔ 6. No user dependency

If an employee leaves, your app still works.

✔ 7. Future-proof

SMTP AUTH is being phased out; Graph API is the modern replacement.