【问题标题】:Unable to get payload.parts from certain mails无法从某些邮件中获取 payload.parts
【发布时间】:2019-08-09 18:12:55
【问题描述】:

我正在创建一个将邮件导入应用程序的 Windows 服务。该服务在 Windows Server 2012 R2 上运行。该服务应该能够将邮件导入另一个应用程序。它需要导入附件、主题、正文、发件人、收件人、更改标签等。我目前正在测试该服务。它几乎运作良好。

问题

少量邮件缺少数据。当我从 gmails api 请求有关邮件的其他信息时,api 无法获取payload.parts。 Payloads.parts 为空。

试过

由于公司的其他部门都依赖邮件,所以我尝试将有问题的邮件转发到我自己的 gmail 帐户。所以我可以调试它们。不幸的是,邮件在转发时似乎没有失败。

我已尝试重新启动服务。它总是在同一封邮件上失败。我能够调试的三种类型的邮件具有 mime 类型:“纯文本/文本”。不确定这是否会有所不同。

编辑:找到一个 mime 类型:“text/html”

代码

从 gmail api 中的标签同步消息的服务

 public async Task<IList<Message>> GetAllMessagesFromGoogleApi()
        {
            try
            {
                _logger.LogInformation("connecting to Gmail Api");
                var service = await _gmailMailFacade.InitializeConnectionAsync();

                _logger.LogInformation("Downloading gmail messages");
                var messages = _gmailMailFacade.GetAllMessagesWithFilter(service);
                if (messages == null)
                {
                    _logger.LogInformation("There were no messages to sync, import cancelled" + Environment.NewLine);
                    return null;
                }

                _logger.LogInformation("Downloading extra data to emails");
                var messageAdditionalData = _gmailMailFacade.GetMessageDataToMessages(messages, service);

                return messageAdditionalData;
            }
            catch (NullReferenceException e)
            {
                _logger.LogError($"Something from gmail api returned null: {e}");
                return null;
            }
            catch (Exception e)
            {
                _logger.LogError($"Unexpected exception in {nameof(GmailApiService)}. Method: {System.Reflection.MethodBase.GetCurrentMethod().Name}| e: {e.Message}");
                throw;
            }
        }

连接到 gmail 从 _gmailMailFacade.InitializeConnectionAsync() 运行

        public readonly string[] _scopes = { GmailService.Scope.GmailModify, GmailService.Scope.GmailLabels};
        private string _applicationName = "applicationName";
        private IOptions<GmailOptions> _options;

        public GmailConnectionUtility(IOptions<GmailOptions> options)
        {
            _options = options ?? throw new ArgumentNullException(nameof(options));
        }

        public async Task<UserCredential> GetUserCredential()
        {

            var credentialPath = Path.Combine(_options.Value.CredentialBasePath, _options.Value.ClientSecretName);
            using (var stream =
                new FileStream(credentialPath, FileMode.Open, FileAccess.Read))
            {
                // The file token.json stores the user's access and refresh tokens, and is created
                // automatically when the authorization flow completes for the first time.
                string credPath = Path.Combine(_options.Value.CredentialBasePath, "token.json");
                var credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    _scopes,
                    "user",
                    CancellationToken.None,
                    new FileDataStore(credPath, true));

                Console.WriteLine("Credential file saved to: " + credPath);

                return credential;
            }
        }

        public GmailService NewGMailService(UserCredential credential)
        {
            var service = new GmailService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = _applicationName,
            });


            return service;
        }

此方法从 gmail api 获取电子邮件_gmailOptions 包含带有标签 id 的字符串。 从 _gmailMailFacade.GetAllMessagesWithFilter(service) 运行;

        public IList<Message> GetEmailsWithLabels(GmailService service)
        {
            var emailByLabel = service.Users.Messages.List("Me");
            emailByLabel.LabelIds = _gmailOptions.LabelSyncFrom;
            emailByLabel.IncludeSpamTrash = false;
            var emailsResponse = emailByLabel.Execute().Messages;
            return emailsResponse;
        }

这些方法从 api 获取负载、标头

        public IList<Message> GetMailDataToMessages(IList<Message> messages, GmailService service)
        {
            return messages.Select(message => GetMailData(message, service)).ToList();
        }

        private Message GetMailData(Message message, GmailService service)
        {
            var logError = "";

            var debugMessage = message;
            try
            {
                logError = $"Unable to get extra data from gmail in {nameof(GmailApiUtility)}," +
                                 $" method: {System.Reflection.MethodBase.GetCurrentMethod().Name}," +
                                 $" on email with subject: {message?.Raw}";

                var request = service.Users.Messages.Get("me", message?.Id).Execute();

                if (request.Payload.Parts == null)
                {
                    _logger.LogError(logError);
                }

                return request;
            }
            catch (NullReferenceException e)
            {
                _logger.LogWarning($"{logError} Exception: {e}");
                return null;
            }
            catch (Exception e)
            {
                _logger.LogError($"Unexpected exception: {e}");
                throw;
            }
        }

【问题讨论】:

    标签: c# gmail-api payload


    【解决方案1】:

    对于具有带有信息的 payload.parts 属性的电子邮件,该电子邮件的有效负载 mime 类型必须为“multipart/*”。这就是为什么当负载 mime 类型为“text/plain”或“text/html”时,payload.parts 为空。

    例如,您可以在启用纯文本选项的情况下从 Gmail 用户界面发送邮件,这将使邮件负载 mime 类型为“text/plain”。对于这些情况,消息的完整信息将直接来自有效负载对象,不会使用parts属性。

    这是一个有一些例子的问题:

    Gmail API: where to find body of email depending of mimeType

    【讨论】:

    • 这对我有用。假设我总是必须进入“Payload.Parts”才能找到“body.data”。非常感谢
    猜你喜欢
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多