使用 Gmail 的 .NET api 阅读大尺寸电子邮件

Posted

技术标签:

【中文标题】使用 Gmail 的 .NET api 阅读大尺寸电子邮件【英文标题】:Reading large size emails using .NET api for Gmail 【发布时间】:2019-04-24 17:24:51 【问题描述】:

我正在尝试使用 Gmail API 获取邮件。我能够获取较小的消息。但是当尝试获取大尺寸消息时,它会抛出异常,因为“任务被取消”。 根据谷歌documentation,我尝试获取原始格式和完整格式的消息。我也尝试增加请求的超时时间。 但结果相同。

有没有其他方法可以阅读大邮件?

这是我的示例代码:

try 

    GmailServiceObj = new GmailService(new BaseClientService.Initializer()
                                
                                    ApplicationName = _appname,
                                    HttpClientInitializer = _userCredentials
                                ); 
    UsersResource.MessagesResource.GetRequest MessageGetRequestObj;
    MessageGetRequestObj= GmailServiceObj.Users.Messages.Get(UserEmailID, ItemID);        
    MessageGetRequestObj.Service.HttpClient.Timeout = new TimeSpan(0, 5, 0);        
    MessageGetRequestObj.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Raw;        
    var _message = MessageGetRequestObj.Execute(); // throws exception

catch(Exception e)
   //The request was aborted: The request was canceled.
    // trying to read same message in parts
    MessageGetRequestObj.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Full;
    var _message = MessageGetRequestObj.Execute();
    string res = Readparts(Emailobj.Payload.Parts, ItemID);



private String Readparts(IList<MessagePart> parts, string msgid)

    StringBuilder mime = new StringBuilder();
    try
    
        foreach (var part in parts)
        

            try
            
                if (part != null && part.Body != null)
                    mime.Append(part.Body.Data);
                if (part.Body != null && part.Body.AttachmentId != null)
                
                    var resource = GmailServiceObj.Users.Messages.Attachments.Get("me", msgid, part.Body.AttachmentId);
                    MessagePartBody attachPart = resource.Execute(); // Throws exception 

                    // Converting from RFC 4648 base64 to base64url encoding
                    // see http://en.wikipedia.org/wiki/Base64#Implementations_and_history
                    String attachData = attachPart.Data.Replace('-', '+');
                    attachData = attachData.Replace('_', '/');
                    mime.Append(attachData);
                
                if (part.Parts != null && part.Parts.Count > 0)
                
                    mime.Append(Readparts(part.Parts, msgid));
                
            
            catch (Exception er)  
        
    
    catch (Exception ex)
    
    return mime.ToString();

提前致谢。

编辑:完成日志

----------------------------------- ------------------------------主要例外------ ----------------------------------------------

将内容复制到流时出错。

在 System.Net.Http.HttpContent.d__49.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Net.Http.HttpClient.d__58.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 Google.Apis.Requests.ClientServiceRequest1.<ExecuteUnparsedAsync>d__33.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Google.Apis.Requests.ClientServiceRequest1.Execute()

----------------------------------- ------------------------------内部例外------ ----------------------------------------------

从传输流中接收到意外的 EOF 或 0 字节。

在 System.Net.GZipWrapperStream.EndRead(IAsyncResult asyncResult) 在 System.IO.Stream.c.b__43_1(流流, IAsyncResult asyncResult) 在 System.Threading.Tasks.TaskFactory1.FromAsyncTrimPromise1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean 需要同步) --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.IO.Stream.d__27.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Net.Http.StreamToStreamCopy.c.b__1_0(任务 完成,对象内部源)在 System.Threading.Tasks.ContinuationTaskFromTask.InnerInvoke() 在 System.Threading.Tasks.Task.Execute() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在 System.Net.Http.HttpContent.d__49.MoveNext()

【问题讨论】:

请编辑您的问题并包含您的完整错误消息,并请定义大。 @DalmTo 大型电子邮件的大小超过 5MB。如果消息大小以 KB 为单位,则它能够获取数据 @Mayuresh - 您是否尝试通过邮件发送任何媒体(.png、.jpg 或视频)或任何文件。或者只是简单的文本 我不想发送消息。我正在尝试读取消息数据。并且邮件包含的附件​​可以是任何文件格式。 尝试使用 Fiddler 检查原始响应。您可能需要使用 HttpClientHandler 为 GZip 启用自动解压缩,或者您应该在读取标头后开始处理请求 【参考方案1】:
MessageGetRequestObj.Service.HttpClient.Timeout = new TimeSpan(0, 5, 0);

这可能是您的问题。看起来您将 HTTP 客户端设置为在 5(秒?)不活动后超时。您应该显着增加超时或完全禁用超时。

【讨论】:

以上是关于使用 Gmail 的 .NET api 阅读大尺寸电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

使用 Gmail API 阅读其他用户的电子邮件

使用 gmail API 阅读独特的邮件

收到来自 gmail users.watch API 的推送通知后如何阅读用户 gmail?

我可以使用gmail api和c#从gmail中读取消息吗?

检查邮件是不是被阅读,gmail api

如何在 asp.net 中使用 gmail api [重复]