You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET使用OAuth2发送Exchange邮件时提示Id属性必须设置

问题:EWS发送邮件时触发"The Id property must be set"错误

近期尝试通过Exchange Online发送邮件,触发操作后立即收到错误提示,无法定位原因。已确认ClientSecret有效期至2025年中,邮件需无用户交互自动发送。

错误信息

System.ArgumentException
  HResult=0x80070057
  Nachricht = The Id property must be set.
  Quelle = Microsoft.Exchange.WebServices
  Stapelüberwachung:
   bei Microsoft.Exchange.WebServices.Data.ImpersonatedUserId.WriteToXml(EwsServiceXmlWriter writer)
   bei Microsoft.Exchange.WebServices.Data.ServiceRequestBase.WriteToXml(EwsServiceXmlWriter writer)
   bei Microsoft.Exchange.WebServices.Data.ServiceRequestBase.EmitRequest(IEwsHttpWebRequest request)
   bei Microsoft.Exchange.WebServices.Data.ServiceRequestBase.BuildEwsHttpWebRequest()
   bei Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest(IEwsHttpWebRequest& request)
   bei Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute()
   bei Microsoft.Exchange.WebServices.Data.ExchangeService.InternalCreateItems(IEnumerable`1 items, FolderId parentFolderId, Nullable`1 messageDisposition, Nullable`1 sendInvitationsMode, ServiceErrorHandling errorHandling)
   bei Microsoft.Exchange.WebServices.Data.Item.InternalCreate(FolderId parentFolderId, Nullable`1 messageDisposition, Nullable`1 sendInvitationsMode)
   bei Microsoft.Exchange.WebServices.Data.EmailMessage.InternalSend(FolderId parentFolderId, MessageDisposition messageDisposition)
   bei Test.MyEws.MailSend(MimeMessage Mail, List`1 Attachments) in C:\Users\maurice.rothmann\source\repos\Test\MailCl.vb: Zeile254
   bei Test.MyEws.SendMail(MimeMessage Mail) in C:\Users\maurice.rothmann\source\repos\Test\MailCl.vb: Zeile210
   bei Test.Form2.KryptonButton1_Click(Object sender, EventArgs e) in C:\Users\maurice.rothmann\source\repos\Test\Form2.vb: Zeile35
   bei System.Windows.Forms.Control.OnClick(EventArgs e)
   bei Krypton.Toolkit.KryptonButton.OnClick(EventArgs e)
   bei Krypton.Toolkit.KryptonButton.OnButtonClick(Object sender, MouseEventArgs e)
   bei Krypton.Toolkit.ButtonController.MouseUp(Control c, Point pt, MouseButtons button)
   bei Krypton.Toolkit.ViewManager.MouseUp(MouseEventArgs e, Point rawPt)
   bei Krypton.Toolkit.VisualControlBase.OnMouseUp(MouseEventArgs e)
   bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   bei System.Windows.Forms.Control.WndProc(Message& m)
   bei Krypton.Toolkit.VisualControlBase.WndProc(Message& m)
   bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   bei System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
   bei Test.Form1.Button3_Click(Object sender, EventArgs e) in C:\Users\maurice.rothmann\source\repos\Test\Form1.vb: Zeile9
   bei System.Windows.Forms.Control.OnClick(EventArgs e)
   bei System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   bei System.Windows.Forms.Control.WndProc(Message& m)
   bei System.Windows.Forms.ButtonBase.WndProc(Message& m)
   bei System.Windows.Forms.Button.WndProc(Message& m)
   bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
   bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
   bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
   bei Test.My.MyApplication.Main(String[] Args) in : Zeile83

相关VB.NET代码

Public Class MyEws
    Private _ClientSecret As String, _MailBoxAdress As String
    Private ReadOnly AppId As String = "1234-5841-1A242-aaaa-Test", TenantId As String = "Test-8544-321-Test-12dbcf"

    Public WriteOnly Property ClientSecret As String
        Set
            _ClientSecret = Value
        End Set
    End Property

    Public Property MailBoxAdress As String
        Get
            Return _MailBoxAdress
        End Get
        Set
            _MailBoxAdress = Value
        End Set
    End Property

    Public Sub New(ClientSecret As String, MailBoxAdress As String)
        Me.ClientSecret = ClientSecret
        Me.MailBoxAdress = MailBoxAdress
    End Sub

    Public Sub New(ClientSecret As String)
        Me.ClientSecret = ClientSecret
    End Sub

    Public Function CreateAuthenticateExchangeService() As ExchangeService
        Dim Ccab As IConfidentialClientApplication
        Dim EwsScopes = {"https://outlook.office365.com/.default"}
        Dim Result As AuthenticationResult, EwsClient As ExchangeService
        Dim ClientOptions As New ConfidentialClientApplicationOptions With {.ClientId = Me.AppId, .ClientSecret = _ClientSecret, .TenantId = Me.TenantId}
        Try
            Ccab = ConfidentialClientApplicationBuilder.CreateWithApplicationOptions(ClientOptions).Build()
            Dim t = Ccab.AcquireTokenForClient(EwsScopes).ExecuteAsync
            t.Wait()
            Result = t.Result
            EwsClient = New ExchangeService(ExchangeVersion.Exchange2013_SP1) With {
            .Url = New Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
            .Credentials = New OAuthCredentials(Result.AccessToken),
            .ImpersonatedUserId = New ImpersonatedUserId(ConnectingIdType.SmtpAddress, MailBoxAdress)}
            Return EwsClient
        Catch ex As Exception
            Dim t = String.Join(Environment.NewLine, Date.Now.ToString("F", ciDE), "Folgender Fehler ist im EwsExportMailAttachment - OAuth2 aufgetreten:", "Fehlernummer: " & ex.HResult, "Fehlerbeschreibung: " & ex.Message, "Stacktrace: " & ex.StackTrace)
            Dim t2 As New MyFile(Path.Combine(Application.StartupPath, "Log.txt"))
            t2.Write(t, True)
            Return Nothing
        End Try
    End Function
    
Public Sub SendMail(Mail As MimeMessage)
        MailSend(Mail, Nothing)
End Sub

Public Sub SendMail(Mail As MimeMessage, Attachment As MyFile)
        Dim MyAttachments As New List(Of MyFile) From {Attachment}
        MailSend(Mail, MyAttachments)
End Sub

    Public Sub SendMail(Mail As MimeMessage, Attachment As List(Of MyFile))
        MailSend(Mail, Attachment)
    End Sub
    Private Sub MailSend(Mail As MimeMessage, Attachments As List(Of MyFile))
        Dim Ews = CreateAuthenticateExchangeService()
        Dim Message = New EmailMessage(Ews)
        With Message
            .Sender = New EmailAddress(Mail.Sender.Name, Mail.Sender.Address)
            .From = .Sender
            .Subject = Mail.Subject
            Dim Recipients = Mail.GetRecipients(True)
            For i = 0 To Recipients.Count - 1
                Dim Receiver = Recipients(i)
                .ToRecipients.Add(New EmailAddress(Receiver.Name, Receiver.Address))
            Next
            If Mail.Cc IsNot Nothing Then
                For i = 0 To Mail.Cc.Count - 1
                    Dim CC = DirectCast(Mail.Cc(i), MailboxAddress)
                    .CcRecipients.Add(New EmailAddress(CC.Name, CC.Address))
                Next
            End If
            If Mail.Bcc IsNot Nothing Then
                For i = 0 To Mail.Bcc.Count - 1
                    Dim BCC = DirectCast(Mail.Bcc(i), MailboxAddress)
                    .BccRecipients.Add(New EmailAddress(BCC.Name, BCC.Address))
                Next
            End If
            If Mail.Body.ContentType.MimeType = "text/html" Then
                .Body = New MessageBody(BodyType.HTML, Mail.GetTextBody(Text.TextFormat.Html))
            Else
                .Body = New MessageBody(BodyType.Text, If(Mail.GetTextBody(Text.TextFormat.Plain), String.Empty))
            End If
            If Attachments IsNot Nothing Then
                For i = 0 To Attachments.Count - 1
                    .Attachments.AddFileAttachment(Attachments(i).FileName & Attachments(i).Extension, Attachments(i).FullPath)
                Next
            End If
        End With
        Message.SendAndSaveCopy()
    End Sub
End Class

排查与解决方案

错误堆栈指向ImpersonatedUserId.WriteToXml,说明ImpersonatedUserId的Id未正确设置,根源在于:

若使用仅传入ClientSecret的构造函数初始化MyEws实例,MailBoxAdress会为空字符串,创建ImpersonatedUserId时传入空值触发错误。

修复措施:

  1. 确保传入邮箱地址:始终使用带MailBoxAdress参数的构造函数初始化MyEws实例,避免MailBoxAdress为空。
  2. 添加空值判断:修改CreateAuthenticateExchangeService方法,仅当MailBoxAdress不为空时才设置ImpersonatedUserId:
    EwsClient = New ExchangeService(ExchangeVersion.Exchange2013_SP1) With {
        .Url = New Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
        .Credentials = New OAuthCredentials(Result.AccessToken)
    }
    ' 仅当邮箱地址有效时设置模拟用户
    If Not String.IsNullOrEmpty(MailBoxAdress) Then
        EwsClient.ImpersonatedUserId = New ImpersonatedUserId(ConnectingIdType.SmtpAddress, MailBoxAdress)
    End If
    Return EwsClient
    
  3. 验证应用权限:确认M365应用已配置Exchange.ManageAsApp权限,且目标邮箱已授予应用访问权限。

内容的提问来源于stack exchange,提问作者Numbfumble

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 03:17:02