通过 Mailcore 2 获取 Gmail:线程 ID、消息 ID 和 UID

Posted

技术标签:

【中文标题】通过 Mailcore 2 获取 Gmail:线程 ID、消息 ID 和 UID【英文标题】:Fetching Gmails Via Mailcore 2: Thread ID vs Message ID vs UID 【发布时间】:2014-02-01 11:45:20 【问题描述】:

我有一个 iPad 应用程序,它允许用户使用 Mailcore2 访问他们的 Gmail 帐户。我以为我了解了 Gmail 的线程 ID、邮件 ID 和 UID 之间的区别,直到我仔细查看了执行邮件获取操作时 Mailcore2 返回给我的内容。我希望有人能澄清我的困惑。

以下是我从 Gmail 文档中了解到的信息:

1) 线程 ID 将属于同一对话的消息(具有自己的消息 ID 和 UID)组合在一起

2) UID 是特定于消息的,并且仅对包含它的文件夹是唯一的

3) 消息 ID 特定于消息,并且在帐户的所有文件夹中都是唯一的

我也做了以下假设:

1) 线程有一个线程 ID,是消息的集合。线程没有消息 ID 或 UID。

2) 消息具有消息ID、UID和线程ID(即使它是线程中唯一的消息)

3) 通过 UID 获取消息会获取 MESSAGES,这些消息的 UID 落在所请求的 UID 范围内。

4) 属于同一线程的消息将具有不同的 UID 和消息 ID,但线程 ID 相同。

好的,所以假设以上是正确的,我认为在通过 UID 获取 Mailcore2 中的典型消息期间,我会收到一组电子邮件,并且从这些电子邮件中我可以查看它们的线程 ID,例如并在客户端重建线程。 但是,我似乎收到的是线程而不是电子邮件。此外,我得到的每个线程不一定包含其所有“子”消息。

例如,如果我的收件箱中有两个线程,每个线程包含五封邮件,Mailcore 会以 MCOIMAPMessages 的形式向我返回一个包含 2 个“电子邮件”的数组。并且每个“电子邮件”都有一个线程 ID、一个消息 ID 和一个 UID。所以我不确定如何访问这两个线程上包含的电子邮件。我看到有一个引用数组......但是检查这个对象并没有发现任何有用的东西。当我记录每个线程的内容时,我只得到部分内容 - 比如说线程上的 5 条消息中的 4 条。由于我不完全了解这一切是如何工作的,因此不确定这是 Mailcore 还是我保存过程中的错误。

这是我获取消息的代码:

//创建获取操作以获取文件夹中的前(10)条消息(第一次获取通过序列号完成,后续提取通过UID完成

uint64_t location = MAX([info messageCount] - DefaultPageSize + 1, 1);
uint64_t size = serverMessageCount < DefaultPageSize ? serverMessageCount - 1 : DefaultPageSize - 1;

MCOIndexSet *numbers = [MCOIndexSet indexSetWithRange:MCORangeMake(location, size)];

MCOIMAPMessagesRequestKind kind =  MCOIMAPMessagesRequestKindUid |
      MCOIMAPMessagesRequestKindFullHeaders |
      MCOIMAPMessagesRequestKindFlags |
      MCOIMAPMessagesRequestKindHeaders |
      MCOIMAPMessagesRequestKindInternalDate;

if ([capabilities containsIndex:MCOIMAPCapabilityGmail]) 
        kind |= MCOIMAPMessagesRequestKindGmailLabels | MCOIMAPMessagesRequestKindGmailThreadID | MCOIMAPMessagesRequestKindGmailMessageID;
        self.gmailCapability = YES;
      

fetchLatestEmails ([self.imapSession fetchMessagesByNumberOperationWithFolder:folder.folderId requestKind:kind numbers:numbers]);

//执行抓取

void (^fetchLatestEmails)(MCOIMAPFetchMessagesOperation *) = ^(MCOIMAPFetchMessagesOperation *fetchOperation) 

  [fetchOperation start:^(NSError *error, NSArray *emails,  MCOIndexSet *vanishedMessages) 

    if (nil != error) 
      failure(error);
      NSLog(@"the fetch error is %@", error);
      return;
    

    [self.dataManager performBatchedChanges:^
      if ([emails count] !=0) 

        MCOIndexSet *savedThreadIds = [[MCOIndexSet alloc]init];

        for (MCOIMAPMessage *email in emails) 

           //do stuff with emails

          Thread *thread = [self.dataManager fetchOrInsertNewThreadForFolder:folder threadId:email.gmailThreadID ?: email.gmailMessageID ?: email.uid error:nil];

          if (nil != thread) 

            [savedThreadIds addIndex:thread.threadId];

            [self.dataManager updateOrInsertNewEmailForThread:thread uid:email.uid messageId:email.gmailMessageID date:email.header.receivedDate subject:email.header.subject from:email.header.from.mailbox to:[email.header.to valueForKey:@"mailbox"] cc:[email.header.cc valueForKey:@"mailbox"] labels:labels flags:flags error:nil];

          

          if (nil != error) 
            failure(error);
            return;
          

        

        [savedThreadIds enumerateIndexes:^(uint64_t threadId) 
          [self.dataManager updateFlagsForThreadWithThreadId:threadId inFolder:folder];
        ];

      

      NSError *folderUpdateError;
      [self.dataManager updateFolder:folder withMessageCount:serverMessageCount error:&folderUpdateError];

     error:&error];

    if (nil == error) 

      [self refreshFolder:folder success:^
        success();
      failure:^(NSError *error) 

      ];

     else 
      failure(error);
    
  ];
;

就我对 Gmail 或 Mailcore2 的理解而言,这里显然有些问题。如果有人能指出我的误解,我将不胜感激。

【问题讨论】:

【参考方案1】:

在使用 Mailcore 提出问题并进行一些研究后,我找到了自己问题的答案。

首先,我上面关于 UID、gmailMessageID 和 gmailThreadID 的假设是正确的。困惑在于我在网络上查看我的电子邮件帐户的 Gmail 对话视图,并期望我的 Mailcore 获取与它匹配。这不会发生,因为会话视图,顾名思义,将会话的所有消息拼接在一起,即使是那些对收件箱中传入消息的回复 - 通常此类消息会在“已发送”或“所有邮件”中找到' 文件夹。换句话说,从 Mailcore 获取的内容看起来不完整,只是因为它正在获取实际在您的收件箱(或您从中获取消息的任何文件夹)中的内容。这不包括对传入消息的回复。为了包含此类邮件(即重新创建 Gmail 的对话视图),我了解必须通过使用邮件的 gmailThreadID 进行搜索操作来从“所有邮件”(或者我想是“已发送”邮件)中获取已发送邮件兴趣。

在测试我的 Mailcore 提取操作时,将网络上的 Gmail 帐户的对话视图切换为“关闭”可以让测试更加清晰。

【讨论】:

告诉我一些想法,我想在单个邮件中获取所有邮件对话。现在我在单独的邮件中收到每一个对话。 我已经有一段时间没有这样做了,但据我回忆,您将分别收到所有消息,然后您必须将具有相同线程 ID 的消息连接在一起以重新创建对话。 感谢您的 cmets。你能给我示例代码吗?对我来说会更好。 嗨@user1697845 我将使用相同的逻辑,但是当我尝试使用类似 NSLog(@"thread ID %llu",message.gmailThreadID);然后总是得到 0。请让我知道我错在哪里。【参考方案2】:

找到答案 要获取 gmailThreadID,我们需要添加 MCOIMAPMessagesRequestKindGmailThreadID。在 Fetch 请求中,如下例所示。

   MCOIMAPMessagesRequestKind requestKind = (MCOIMAPMessagesRequestKind)
    (MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure |
     MCOIMAPMessagesRequestKindInternalDate | MCOIMAPMessagesRequestKindHeaderSubject |
     MCOIMAPMessagesRequestKindFlags | MCOIMAPMessagesRequestKindGmailThreadID);

【讨论】:

以上是关于通过 Mailcore 2 获取 Gmail:线程 ID、消息 ID 和 UID的主要内容,如果未能解决你的问题,请参考以下文章

Mailcore 2 无法访问除收件箱文件夹以外的 gmail 邮件

带有 Gmail 和 OAuth2 的 MailCore2 仅在完全访问范围内发送,即 https://mail.google.com

使用 Gmail 在 Mailcore2 中创建子文件夹

如何使用mailcore2获取邮件的发件人资料图片

如何在mailcore2中获取邮件正文和最后一封电子邮件?

MailCore2 - 在不下载图像或附件的情况下获取邮件内容?