Author |
|
hmuscroft Groupie
Joined: 29 December 2009 Location: United Kingdom
Online Status: Offline Posts: 72
|
Posted: 25 October 2016 at 5:50am | IP Logged
|
|
|
Hi - a couple of years of ago I implemented a full email client into our software (C# WinForms) using your SMTP and POP components.
I'm now adding IMAP functionality. My goal is to approximate how Mozilla Thunderbird works with IMAP.
At the moment, I'm trying to find out the "best practice" for retrieving emails from IMAP.
As far as I can see, there are three routines for retrieving emails :-
- DownloadEnvelopes
- DownloadMessageHeaders
- DownloadEntireMessages
Do you have any guidelines/documention as to which method to use and also any suggestions for offline caching of emails when using the IMAP protocol?
Many thanks!
Kind Regards,
Hedley Muscroft
|
Back to Top |
|
|
Igor AfterLogic Support
Joined: 24 June 2008 Location: United States
Online Status: Offline Posts: 6104
|
Posted: 25 October 2016 at 6:53am | IP Logged
|
|
|
Out of the methods you mentioned, DownloadEnvelopes is the most universal one. Depending on parameters you supply, it can be used for fetching message flags, headers, message preview text, full message body, or any combination of those, see EnvelopeParts description for more info on available parts to download. Other methods listed are basically wrappers for DownloadEnvelopes used to download either just headers or full message bodies. One of the most typical approaches assumes that you download message headers (plus maybe flags and body preview additionally) to store message list in the database, and once you need to fetch the actual message, use DownloadEntireMessages for that.
Hope this helps.
--
Regards,
Igor, AfterLogic Support
|
Back to Top |
|
|
hmuscroft Groupie
Joined: 29 December 2009 Location: United Kingdom
Online Status: Offline Posts: 72
|
Posted: 25 October 2016 at 7:11am | IP Logged
|
|
|
That's really useful - thanks for the quick response.
Once I have the Envelope objects retrieved from...
Code:
m_imap.DownloadEnvelopes(UIDs, true, EnvelopeParts.All, -2); |
|
|
...please can you tell me how to determine if it has an attachment? I can't seem to find that property.
|
Back to Top |
|
|
Igor AfterLogic Support
Joined: 24 June 2008 Location: United States
Online Status: Offline Posts: 6104
|
Posted: 25 October 2016 at 7:29am | IP Logged
|
|
|
That method would download collection of entire messages including attachments, you can access each of the messages via Envelope.MessagePreview property. You are looking for HasAttachments property of that message, and Attachments would let you access the attachments themselves; you can find an example here.
--
Regards,
Igor, AfterLogic Support
|
Back to Top |
|
|
hmuscroft Groupie
Joined: 29 December 2009 Location: United Kingdom
Online Status: Offline Posts: 72
|
Posted: 26 October 2016 at 6:50am | IP Logged
|
|
|
Thanks for your continued help. I just re-read all the documentation and realised that the -2 is a 'magic value' for downloading the entire message but not setting the SEEN flag.
What I really want to be doing with my "DownloadEnvelopes" call is just getting the basic email details (to be cached locally) and then calling "DownloadEntireMessages" to get the full message.
I've adjusted call as follows :-
Code:
m_imap.DownloadEnvelopes(UIDs, true, EnvelopeParts.MailBeeEnvelope | EnvelopeParts.MessagePreview, 0); |
|
|
...and the good news that this is MUCH faster - which is what I wanted. However, I can no longer get the attachment count from 'anEnvelope.MessagePreview.Attachments.Count' as it always returns 0.
Please can you advise on how to get the attachment count while still downloading just the basic email data?
Many thanks!
|
Back to Top |
|
|
Igor AfterLogic Support
Joined: 24 June 2008 Location: United States
Online Status: Offline Posts: 6104
|
Posted: 26 October 2016 at 7:04am | IP Logged
|
|
|
Usually, if you aren't downloading an entire message and getting just the headers, there is no accurate way to get attachments count. But if you deal with IMAP envelopes, there's still a way - you need to work with EnvelopeParts.BodyStructure, a sample for that is found on ImapMail.Envelope documentation page.
On an unrelated note, there's no need to supply EnvelopeParts.MessagePreview in the method call if bodyPreviewSize is set to 0, as that means getting just the headers.
--
Regards,
Igor, AfterLogic Support
|
Back to Top |
|
|
hmuscroft Groupie
Joined: 29 December 2009 Location: United Kingdom
Online Status: Offline Posts: 72
|
Posted: 28 October 2016 at 3:27am | IP Logged
|
|
|
This is all working beautifully - thanks for the excellent support
I'm sure there'll be more questions from me in the future!
|
Back to Top |
|
|
hmuscroft Groupie
Joined: 29 December 2009 Location: United Kingdom
Online Status: Offline Posts: 72
|
Posted: 22 February 2017 at 8:20am | IP Logged
|
|
|
I'm just re-visiting the question: what is the best way to get the attachment count from an Envelope?
You kindly gave me a link to this page which provides an example.
Based on that example, my code looks like this :-
Code:
int att_count = 0;
foreach (MailBee.ImapMail.ImapBodyStructure part in env.BodyStructure.GetAllParts())
{
// Detect if this part is attachment...
if ((part.Disposition != null && part.Disposition.ToLower() == "attachment") ||
(part.Filename != null && part.Filename != string.Empty) ||
(part.ContentType != null && part.ContentType.ToLower() == "message/rfc822"))
{
att_count++;
}
}
|
|
|
So the problem with this is that it seems to be counting "inline" attachments as well as some of the weirder attachments like "winmail.dat" which sometimes show up in emails.
Once I've downloaded the entire email, I have no problem calculating the number of attachments like this :-
Code:
static public int GetAttachmentCount(MailMessage aMsg)
{
int res = 0;
foreach (Attachment att in aMsg.Attachments)
if (!att.IsInline && !IgnoreAttachment(att.Filename))
res++;
return res;
}
static public bool IgnoreAttachment(string AttName)
{
return (String.Compare(AttName, "richbody.rtf", true) == 0 || String.Compare(AttName, "winmail.dat", true) == 0);
}
|
|
|
So the question is... is there any why I can increase the accuracy of the first block of code (i.e. when getting the attachment count from the Envelope), so that it's consistent with the second block of code?
Kind Regards,
Hedley
PS: Many thanks for you continued (superb) support. Hopefully the questions and code snippets I'm posting on this forum are also helpful to other customers!
|
Back to Top |
|
|
Alex AfterLogic Support
Joined: 19 November 2003
Online Status: Offline Posts: 2206
|
Posted: 22 February 2017 at 8:36am | IP Logged
|
|
|
Treating whether an item is attachment or not is quite subjective. We just provided one "view" but you can have another. There is no "right" or "wrong" way to go. Your code is fine for some purposes and won't work for others.
For instance, you call winmail.dat "weird" but for someone else it can be fine. Inline attachments are also "blurry". For example, PDF file can be contained as inline attachment but it cannot often be displayed this way (it's not an image). So it can be neither attachment nor inline, and it's up to you to decide to which basket to put it.
From MIME, everything which has part.Disposition.ToLower=="attachment" (or attachment.AsMimePart.Disposition.ToLower=="attachment" equivalent for the second block) is attachment. Everything else is not. So if you need some rule, that's it. In real life, things can be more complex (like with winmail.dat) but again, it's the matter beyond the standard and it's up to your vision how to deal with them.
Regards,
Alex
|
Back to Top |
|
|
hmuscroft Groupie
Joined: 29 December 2009 Location: United Kingdom
Online Status: Offline Posts: 72
|
Posted: 22 February 2017 at 8:55am | IP Logged
|
|
|
OK - thanks for the detailed response. Is the an equivalent to "Attachment.IsInline" when looking at the Envelope parts?
|
Back to Top |
|
|
Alex AfterLogic Support
Joined: 19 November 2003
Online Status: Offline Posts: 2206
|
Posted: 23 February 2017 at 3:02pm | IP Logged
|
|
|
I believe it's something like
Code:
if (part.Disposition == null || part.Disposition.ToLower() != "attachment") |
|
|
part is ImapBodyStructure
Regards,
Alex
|
Back to Top |
|
|