Search code examples
azurevb.netemailmicrosoft-graph-apiclient-certificates

VB .NET Console App - Send Mail from shared Mailbox with MS Graph - 404 Mailbox is either inactive, soft-deleted, or is hosted on-premise


I am trying to send an E-Mail from a Shared Mail box (inside our organization) via MS Graph API with a VB .NET Console App. There is a fitting App registration in the Azure portal with Mail.Send Application Permissions for specific shared Mailboxes. For the connection I am using a proxy and a client certificate which is uploaded in the Azure App registration.

The code seems to work - but I am receiving a permission error for which I can't find sufficient information. Error: 404 - The mailbox is either inactive, soft-deleted, or is hosted on-premise.

Also I tried the code with different senders/users in order to compare the results and got the follwing:

  1. sender = shared mailbox in organization without Mail.Send permission -> Code: 403 Message: "Access is denied. Check credentials and try again." Source: Microsoft.Kiota.Http.HttpClientLibrary
  2. sender = shared mailbox in organization with Mail.Send permission -> Code: 404 Message: "The mailbox is either inactive, soft-deleted, or is hosted on-premise." Source: Microsoft.Kiota.Http.HttpClientLibrary
  3. sender = some existing mailadress outside organization -> Code: 404 Message: "The requested user '[email protected]' is invalid."
    Source: Microsoft.Kiota.Http.HttpClientLibrary

Imports Microsoft.Graph
Imports Azure.Identity
Imports System.Security.Cryptography.X509Certificates
Imports System.Net.Http
Imports System.Net
Imports Microsoft.Graph.Models
Imports Azure.Core.Pipeline


Module ModuleTest

    Public Sub Start()
        ' Information for MS Graph API Connection
        Dim tenantId As String = "inserttenantid"
        Dim clientId As String = "insertclientid"

        ' Certificate
        Dim certificatePath As String = "C:\...\insertcertificatepath.pfx"
        Dim certificatePassword As String = "insertpassword"

        ' Configure Proxy-Server
        Dim proxy As New WebProxy("http://insertproxyserverorganization.com:insertport/")
        proxy.Credentials = CredentialCache.DefaultNetworkCredentials

        ' Configure HttpClientHandler with Proxy-Server
        Dim handler As New HttpClientHandler() With {
            .Proxy = proxy,
            .UseProxy = True
        }

        ' Import Certificate
        Dim certificate As New X509Certificate2(certificatePath, certificatePassword)

        ' Create ClientCertificateCredential & GraphServiceClient
        Dim clientCertificateCredential As New ClientCertificateCredential(tenantId, clientId, certificate, New TokenCredentialOptions With {.Transport = New HttpClientTransport(handler)})
        Dim graphServiceClient As New GraphServiceClient(clientCertificateCredential)

        ' Send E-Mail
        Try
            'Dim strSender = "[email protected]" ' -> Access Denied
            Dim strSender = "[email protected]" ' -> 404 Error Mailbox inactive soft-deleted or hosted onprem
            'Dim strSender = "[email protected]"          ' -> E-Mail invalid

            SendEmail(strSender, "TestHeader", "TestContent", "[email protected]", graphServiceClient).Wait()
        Catch ex As Exception
            Console.WriteLine($"Error sending email: {ex.Message}")
        End Try

    End Sub

    Private Async Function SendEmail(sender As String, subject As String, content As String, recipient As String, graphServiceClient As GraphServiceClient) As Task

        Dim requestBody As New Microsoft.Graph.Users.Item.SendMail.SendMailPostRequestBody With {
            .Message = New Message With {
                .Subject = subject,
                .Body = New ItemBody With {
                    .ContentType = BodyType.Html,
                    .Content = content
                },
                .ToRecipients = New List(Of Recipient) From {
                    New Recipient With {
                        .EmailAddress = New EmailAddress With {
                            .Address = recipient
                        }
                    }
                }
        },
        .SaveToSentItems = True}

        ' Send E-Mail
        Await graphServiceClient.Users(sender).SendMail().PostAsync(requestBody)


    End Function

End Module

Solution

  • As you are making use of non-user interactive flow, you need to grant Mail.Send Application type API permission:

    enter image description here

    For sample, I generated access token by passing below parameters:

    https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
    
    client_id : ClientID
    client_secret : Secret
    scope : https://graph.microsoft.com/.default
    grant_type : client_credentials
    

    enter image description here

    Now I tried to send mail and got the same error:

    POST https://graph.microsoft.com/v1.0/users/UserID/sendMail
    Content-type: application/json
    
    {
      "message": {
        "subject": "Meet for lunch?",
        "body": {
          "contentType": "Text",
          "content": "The new cafeteria is open."
        },
        "toRecipients": [
          {
            "emailAddress": {
              "address": "[email protected]"
            }
          }
        ],
        "ccRecipients": [
          {
            "emailAddress": {
              "address": "[email protected]"
            }
          }
        ]
      },
      "saveToSentItems": "false"
    }
    

    enter image description here

    The error "The mailbox is either inactive, soft-deleted, or is hosted on-premise." usually occurs if the user is not assigned with active M365/O365 license.

    enter image description here

    After assigning license, I am able to send mail successfully:

    enter image description here

    • The error "Access is denied. Check credentials and try again." occurs if the application is not granted with Mail.Send API permission. Make sure to grant Mail.Send API permission to the application to resolve the error.

    The error "The requested user 'xxx' is invalid." usually occurs if you are using other tenant user or Microsoft personal account user to send mail and making use of Client credential flow.

    • To resolve error, you need to switch to delegated flow or user interactive flow and make use of /me endpoint.