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时传入空值触发错误。
修复措施:
- 确保传入邮箱地址:始终使用带
MailBoxAdress参数的构造函数初始化MyEws实例,避免MailBoxAdress为空。 - 添加空值判断:修改
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 - 验证应用权限:确认M365应用已配置
Exchange.ManageAsApp权限,且目标邮箱已授予应用访问权限。
内容的提问来源于stack exchange,提问作者Numbfumble
相关产品推荐
相关产品推荐

