使用Microsoft Graph API发送邮件遇空引用错误求助
问题排查:Microsoft Graph API发送邮件时出现“Object reference not set to an instance of an object”错误
使用Microsoft Graph API发送邮件,Message部分内容完整,但执行Task.Delay后调用发送接口时抛出“Object reference not set to an instance of an object”错误,无法定位问题。
完整代码
try { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; //var url = GetMailConfig(configGroup: "EWS", configName: "EwsUrl"); var username = GetMailConfig(configGroup: "EWS", configName: "Email"); var password = GetMailConfig(configGroup: "EWS", configName: "Password"); var fromAddress = GetMailConfig(configGroup: "SMTP", configName: "From"); //var traceEnabled = GetMailConfig(configGroup: "EWS", configName: "TraceEnabled"); var tenantId = GetMailConfig(configGroup: "EWS", configName: "TenantId"); var clientId = GetMailConfig(configGroup: "EWS", configName: "ClientId"); var access_token = ""; var redirect_uri = "https://example.example.com/"; var clienSecretId = "This is secret key"; //var scopes = new[] { "https://outlook.office365.com/SMTP.Send" }; var scopes = new[] {"https://graph.microsoft.com/.default" }; var pca = ConfidentialClientApplicationBuilder .Create(clientId) .WithClientSecret(clienSecretId) .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}")) .Build(); var authProvider = new DelegateAuthenticationProvider(async (request) => { try { var result = await pca.AcquireTokenForClient(scopes).ExecuteAsync(); request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result.AccessToken); } catch (Exception exp) { // 吞掉了身份验证异常 } }); GraphServiceClient graphClient = new GraphServiceClient(authProvider); var message = new Message { Subject = mailTemplate.Subject, From = new Recipient() { EmailAddress = new Microsoft.Graph.EmailAddress { Address = "example@example.com" } }, Body = new ItemBody { ContentType = Microsoft.Graph.BodyType.Html, Content = mailTemplate.Body }, }; MailMessage mail = new MailMessage(); var attachments = new MessageAttachmentsCollectionPage(); if (mailTemplate.Cc != null && mailTemplate.Cc.Any()) message.CcRecipients = mailTemplate.Cc.Select(x => new Recipient() { EmailAddress = new Microsoft.Graph.EmailAddress { Address = x } }); if (mailTemplate.To != null && mailTemplate.To.Any()) message.ToRecipients = mailTemplate.To.Select(x => new Recipient() { EmailAddress = new Microsoft.Graph.EmailAddress { Address = x } }); var saveToSentItems = false; System.Threading.Tasks.Task.Run(async () => { try { await Task.Delay(TimeSpan.FromSeconds(5)); await graphClient.Me .SendMail(message, saveToSentItems) .Request() .PostAsync(); } catch (Exception ex) { // 吞掉了发送异常 } }); } catch (Exception exp) { isSentMailSuccess = false; } return isSentMailSuccess;
异常发生代码段
await Task.Delay(TimeSpan.FromSeconds(5)); await graphClient.Me .SendMail(message, saveToSentItems) .Request() .PostAsync();
排查关键点
- 身份验证异常被吞:委托认证提供者内部的try/catch没有处理或记录异常,可能获取token失败导致后续请求无有效授权,引发空引用。需移除内部catch或添加日志,确认token是否正常获取。
graphClient.Me使用错误:当前采用客户端凭据模式(应用权限),该模式下没有用户上下文,不能使用Me指代当前用户,需替换为具体用户邮箱,例如graphClient.Users["指定用户邮箱"].SendMail(...)。- 收件人集合赋值问题:
Select返回的是IEnumerable<Recipient>,而Message的ToRecipients/CcRecipients要求是IList<Recipient>,直接赋值可能导致序列化时出现空引用,需转换为List:message.ToRecipients = mailTemplate.To.Select(...).ToList();。 - 异步任务未等待:外层函数直接返回
isSentMailSuccess,但异步发送任务可能还未执行完成,虽不是空引用直接原因,但会导致返回结果不准确,需改为await Task.Run(...)并将外层方法标记为async。 - 对象生命周期风险:异步任务中的
graphClient、message可能被外层代码提前释放,需确保这些对象在异步执行期间始终有效。
内容的提问来源于stack exchange,提问作者Esra
相关产品推荐
相关产品推荐

