3

Outlook から受信トレイと送信済みアイテムを取得できるソフトウェアに取り組んでいます。私がやりたいことは、受信トレイのメールを返信に関連付けることです (誰かがそのメールに返信を送信した場合)。リストはこの順序で表示されるべきです

Sender@abc.com 着信 件名 受信時刻 senter@abc.com 返信 件名 送信時刻

私が計画しているのは、あるデータテーブルで受信トレイアイテムを取得し、別のデータテーブルで送信済みアイテムを取得することです。送信者の電子メールと件名に基づいて電子メールを 1 つずつ読み取り、送信済みアイテムでその送信者と電子メールを検索し、一致する場合はそれを 3 番目のデータテーブルにマージします。

そうする他の良い方法はありますか?

コードは次のとおりです。

 private DataTable GetInboxItems()

    {
        DataTable inboxTable;
        //try
        //{
        filter = "[ReceivedTime] >= '" + dtpStartDate.Value.ToString("dd/MM/yyyy 12:00 AM") + "' and [ReceivedTime] <= '" + dtpEndDate.Value.ToString("dd/MM/yyyy  11:59 PM") + "'";
        Outlook.Application outlookApp = GetApplicationObject();
        Outlook.Folder root = outlookApp.Session.DefaultStore.GetRootFolder() as Outlook.Folder;
        EnumerateFolders(root);
        //string filter = "[ReceivedTime] > '" + dtpStartDate.Value.ToString("dd/MM/yyyy") + "'";

        //inbox
        Outlook.MAPIFolder inboxFolder = outlookApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
        inboxTable = CreateTable();
        int count = 0;


        if (inboxFolder.Items.Count > 0)
        {

            var restrictedItems = inboxFolder.Items.Restrict(filter);
            restrictedItems.Sort("[ReceivedTime]", true); //descending
            //foreach (var item in inboxFolder.Items)
            foreach (var item in restrictedItems)
            {
                var mail = item as Outlook.MailItem;
                if (mail != null)
                {
                    //try
                    //{
                    DataRow row = inboxTable.NewRow();
                    //row["sn"] = (++count).ToString();
                    row["sn"] = mail.EntryID + " " + mail.ReceivedByEntryID;
                    row["MailType"] = "Inbox";
                    row["SenderName"] = mail.SenderName;
                    row["SenderEmail"] = mail.SenderEmailAddress;
                    row["ReceivedDate"] = mail.ReceivedTime;
                    row["Subject"] = mail.Subject;
                    row["Body"] = mail.Body != null ? (mail.Body.Length > 25 ? mail.Body.Substring(0, 25) : mail.Body) : null;
                    //row["Body"] = mail.Body != null ? mail.Body : "";
                    row["MailSize"] = mail.Size.ToString();
                    string attachments = null;
                    if (mail.Attachments.Count > 0)
                    {
                        foreach (var attachment in mail.Attachments)
                        {
                            if (((Outlook.Attachment)attachment) != null)
                                //attachments = ((Outlook.Attachment)attachment).FileName + " " + ((Outlook.Attachment)attachment).Size.ToString() + ", ";
                                attachments += (((Outlook.Attachment)attachment).Size / 1024).ToString() + " KB, ";
                        }
                    }


                    row["AttachmentCount"] = mail.Attachments.Count;
                    if (attachments != null)
                        row["AttachmentSize"] = attachments.Substring(0, attachments.Length - 2);

                    inboxTable.Rows.Add(row);
                }
                //catch (Exception ex)
                //{

                //    return null;
                //}

            }
        }

        return inboxTable;
    }
4

1 に答える 1

0

Outlook アドインでこのようなものを作成しました

100% 作成する方法はありません...
問題は、会話 ID が他のソフトウェアによって常に保持されているとは限らないことです。そのため、一連のデータを使用して電子メールを回答にリンクする必要があります。
- メッセージ ID: これは電子メール ヘッダーで使用できます。送信済みアイテムにはこれはありません:/
- In-Reply-To: これは電子メールのヘッダーにもあります
- トピック ID

トピック ID については、次の順序で値を取得します (利用可能な最初のものを取得します):
- MailItem.ConversationIndex: 各返信は会話インデックスにバイトを追加します
- 参照ヘッダー

次に、topicID を使用してメールを返信にリンクします。メールの最初の X 文字は返信と同じです。例 元のメールのトピック id = abc, reply = abcdef 会話 ID を使用してリンクできないすべてのメールについて、Message-ID と In-Reply-To ID を使用してリンクを試みます

問題は特に、outlook (メッセージ ID なし) から送信された電子メールから発生し、ユーザーは Reference/ConversationIndex ヘッダーなしで返信します...両方のメールをリンクする方法はありません。

それが役に立てば幸い

編集:ここにいくつかのコードがあります。別のクラス/メソッドからコードをコピーして貼り付けて単一のメソッドを作成したため、コンパイルできない場合があります。もっと疑似コードとして考えてください。

public SimpleTree<MailData> CreateTree(List<MailData> mails)
{
    mails.Sort((m1, m2) => m1.TopicId == m2.TopicId ? m2.CreationDate.CompareTo(m1.CreationDate) : m1.TopicId.CompareTo(m2.TopicId));

    var tree = new SimpleTree<MailData>();

    var i = 0;
    while (i < mails.Count)
    {
        var node = tree.Children.Add(mails[i]);
        var topicId = mails[i].TopicId;
        var start = i + 1;
        while (start < mails.Count 
            && !string.IsNullOrEmpty(topicId) 
            && !string.IsNullOrEmpty(mails[start].TopicId) 
            && mails[start].TopicId.StartsWith(topicId))
        {
            node.Children.Add(mails[start]);
            start++;
        }
        i = start;
    }

    // Handle email where TopicId are different, but ParentId is filled with correct value
    for (int j = tree.Children.Count - 1; j >= 0; j--)
    {
        var child = tree.Children[j];
        if (child.Children.Count == 0 && !string.IsNullOrEmpty(child.Value.ParentId))
        {
            var parentNode = tree.FindNode(s => s != null && s.MessageId == child.Value.ParentId);
            if (parentNode != null && parentNode != child)
                parentNode.Children.Add(child);
        }
    }

    return tree;
}

MailData は、前に説明したように必要な 3 つのフィールドを持つクラスです。

  • MessageID (Message-ID ヘッダーから)
  • ParentId (In-Reply-To ヘッダーから)
  • TopicId (ConversationIndex または Reference ヘッダーから)

SimpleTree<> はツリーを作成するクラスで、実際には子を持つノードです。ここでは、特別なことや電子メールに関連することは何もありません。.Value プロパティは、ノードに関連付けられたデータを参照します (ここでは MailData)。

目標は、1 つのループでツリーを構築できるように、TopicId でソートすることです。次に、ツリー ルート内のすべてのメールをチェックして、MessageId/ParentId を使用して別のメールの下に移動できるかどうかを確認します。

次のような 1 レベルのツリーが作成されることを覚えておいてください。

  • メールA
    • 返信 AA
    • 返信 AAA
  • メールB
    • 返信 BB
    • 返信 BBB

ただし、次のようなものが必要です。

  • メールA
    • 返信 AA
      • 返信 AAA
  • メールB
    • 返信 BB
      • 返信 BBB
于 2013-04-08T19:30:57.423 に答える