Rebex IMAP functionality in lightweight style.

0 votes
asked May 31, 2011 by _Oz_ (360 points)
edited Jun 11, 2011

Hello. Trying to work with Rebex Imap, I was surprised not finding easy way to get mail message lightweight objects.

I want to get from server side some info about emails without donwload all heavy emails data. The lightweight data I need are subject, received date, "is seen" flag, and priority. ImapMessageInfo class contains most of needed items, but priority.

MailMessage class contains priority, but does not contains "is seen" and some others flag. Besides, if I'm understand correct, MailMessage is "heavy" object containing all data.

So, what is the easiest way to get email "lightweight" info list including priority, using Rebex IMAP?

Thank you in advance.

Applies to: Rebex Secure Mail

5 Answers

+1 vote
answered May 31, 2011 by Jan Sotola (17,670 points)
edited Jun 1, 2011
 
Best answer

Hello,

You are understanding it right - ImapMessageInfo is a "lightweight" object since it does not download the whole message from server.

You can even control the "lightness" of the object by setting ImapListFields flags when retrieving data into ImapMessageInfo object(s). For example retrieving with ImapListFields.Envelope only is faster than retrieving with ImapListFields.FullHeaders.

The MailMessage is really a "heavy" object that needs loading the whole message (including attachment) from IMAP server to the client.

The ImapMessageInfo does contain a Priority field, although it is not directly accessible using a property. However, you can retrieve it yourself using the following method:

public static MailPriority GetPriority(ImapMessageInfo msg)
{
  MimeHeaderCollection headers = msg.Headers;
  MimeHeader h = headers["X-Priority"];
  if (h == null)
        h = headers["Priority"];
  if (h == null)
        return MailPriority.Normal;

  string s = h.Raw.ToLower(CultureInfo.InvariantCulture);

  if ((s.IndexOf("low") >= 0) || (s.IndexOf("non-urgent") >= 0))
        return MailPriority.Low;

  if ((s.IndexOf("hi") >= 0) || (s.IndexOf("urgent") >= 0))
        return MailPriority.High;

  if (s.IndexOf("med") >= 0)
        return MailPriority.Normal;

  if (s.Length == 1)
  {
        int p = s[0]-'0';
        if (p >= 0 && p <= 2)
              return MailPriority.High;
        if (p >= 4 && p <= 9)
              return MailPriority.Low;
  }

  return MailPriority.Normal;
}

Please note that this only works if ImapListFields.FullHeaders is used.

commented May 31, 2011 by _Oz_ (360 points)
edited May 31, 2011

Thank you for the fast and clear answer. Good support style.

0 votes
answered Jun 1, 2011 by _Oz_ (360 points)
edited Jun 1, 2011

Small adjustments ImapMessageInfo has no msg.Headers.Headers member (but MailMessage has :) ) So, more correct and compilable code listed below

internal static MailPriority GetPriority(this ImapMessageInfo imapMessageInfo)
    {
        const string PriorityHeaderA = "X-Priority";
        const string PriorityHeaderB = "Priority";

        MimeHeader header = imapMessageInfo.Headers[PriorityHeaderA] ?? imapMessageInfo.Headers[PriorityHeaderB];

        if (header == null)
        {
            return MailPriority.Normal;
        }

        string rawHeader = header.Raw.ToLower(CultureInfo.InvariantCulture);

        const string LowPriorityValueA = "low";
        const string LowPriorityValueB = "non-urgent";

        if (rawHeader.IndexOf(LowPriorityValueA) >= 0 || rawHeader.IndexOf(LowPriorityValueB) >= 0)
        {
            return MailPriority.Low;
        }

        const string HiPriorityValueA = "hi";
        const string HiPriorityValueB = "urgent";

        if ((rawHeader.IndexOf(HiPriorityValueA) >= 0) || (rawHeader.IndexOf(HiPriorityValueB) >= 0))
        {
            return MailPriority.High;
        }

        const string MediumPriorityValue = "med";

        if (rawHeader.IndexOf(MediumPriorityValue) >= 0)
        {
            return MailPriority.Normal;
        }

        if (rawHeader.Length != 1)
        {
            return MailPriority.Normal;
        }

        int num = rawHeader[0] - '0';

        if ((num >= 0) && (num <= 2))
        {
            return MailPriority.High;
        }

        if ((num >= 4) && (num <= 9))
        {
            return MailPriority.Low;
        }

        return MailPriority.Normal;
    }
commented Jun 1, 2011 by Lukas Matyska (60,690 points)
edited Jun 1, 2011

Oh, it was a mistake. Instead of headers.Headers["X-Priority"] only the headers["X-Priority"] have to be used.
I edited the code and fixed this mistake.

0 votes
answered Jun 2, 2011 by _Oz_ (360 points)
edited Jun 2, 2011

Hello again. Could you provide me some info related thing above. Is there any way to get UniqueId and IsSeen properties from MailMessage instance? Thank you in advance.

0 votes
answered Jun 2, 2011 by Jan Sotola (17,670 points)
edited Jun 2, 2011

You have to get the IsSeen and UniqueId properties from the ImapMessageInfo object. However, MailMessage object does not know anything about a protocol specific object (e.g. ImapMessageInfo).

I'd recommended you to retrieve or search your messages first as ImapMessageInfos and then create a MailMessage object for each of them.

// get a sample collection of message infos
ImapMessageCollection messageInfos = 
    client.Search(ImapSearchParameter.Arrived(new DateTime(2011, 6, 2)));

// process each message
foreach (ImapMessageInfo messageInfo in messageInfos)
{
    // get MailMessage for a MessageInfo
    MailMessage message = client.GetMailMessage(messageInfo.SequenceNumber);
    //alternative retrieval if you cannot rely on SequenceNumber (*)  
    //MailMessage message = client.GetMailMessage(messageInfo.UniqueId);

    // use both properties of MessageInfo and MailMessage
    Console.WriteLine("-------------------------------------");
    Console.WriteLine("SUBJ.:\t{0}", messageInfo.Subject);  
    Console.WriteLine("READ:\t{0}", messageInfo.IsSeen);    // MessageInfo specific property
    Console.WriteLine("BODY:\r\n{0}", message.BodyText);    // MailMessage specific property
}

*Retrieving MessageInfo by SequenceNumber can be faster than getting by UniqueId, but you cannot use SequenceNumber if you are deleting messages in the same session.

If you cannot use the procedure described above, you can try to find a ImapMessageInfo for each MailMessage object using search for an MessageId field:

MailMessage message;

// ...

ImapMessageCollection messageInfos = 
    client.Search(ImapSearchParameter.Header("Message-Id", message.MessageId.Id));
ImapMessageInfo messageInfo = messageInfos[0];

Be aware that searching by MessageId will be probably more time-consuming than retrieving messages by UniqueId or SequenceNumber.

0 votes
answered Jun 2, 2011 by _Oz_ (360 points)
edited Jun 2, 2011

Got it, thank you.

...