i am using ImapX 2 and i wanted to get messages and attachments from all folders
That is my code, i can get all folders, but messages not. How to get messages?
if (client.Login(login, pass))
{
// login successful
FolderCollection folders = client.Folders;
foreach (Folder myfolder in folders)
{
var messages = myfolder.Messages;
foreach (var message in messages)
{
MessageBox.Show(message.Subject);
var attachments = message.Attachments;
if (attachments.Count() > 0)
foreach (var attachment in attachments)
{
MessageBox.Show(attachment.FileName);
}
}
}
}
Before you can access message you need to download them
myfolder.Messages.Download();
foreach (var message in messages)
{//your code}
You can use parameter’s, here what documentation said
public void Download([string query = "ALL"], [ImapX.Enums.MessageFetchMode mode = ImapX.Enums.MessageFetchMode.ClientDefault], [int count = -1])
Member of ImapX.Collections.MessageCollection
Summary:
Downloads messages from server using default or given mode.
Parameters:
query: The search query to filter messages. ALL by default
mode: The message fetch mode, allows to select which parts of the message will be requested.
count: The maximum number of messages that will be requested. Set count to -1 will request all messages which match the given query.
Related
we send emails with attachments by the ews-service with the follwing code...
EmailMessage message = new EmailMessage(ExchangeServiceController);
EmailAddress sender = new EmailAddress
{
MailboxType = MailboxType.Mailbox,
Address = senderAdress
};
message.From = sender;
message.ToRecipients.AddRange(email.SendTo.GetEmailAdressRange());
message.Subject = email.Subject;
message.Body = new MessageBody(BodyType.HTML, emailText);
string[] fileEntries = SignatureController.GetSignatureImagesFiles();
int i = 0;
foreach (string fileName in fileEntries.Where(f => f.Contains("image")))
{
FileInfo info = new FileInfo(fileName);
message.Attachments.AddFileAttachment(info.Name, fileName);
message.Attachments[i].IsInline = true;
message.Attachments[i].ContentId = info.Name;
i++;
}
foreach (string filename in GetAttachmentsAsFilePathList())
{
message.Attachments.AddFileAttachment(filename);
}
var mailbox = new Mailbox(sender.Address);
var folderIdDrafts = new FolderId(WellKnownFolderName.Drafts, mailbox);
var folderIdSent = new FolderId(WellKnownFolderName.SentItems, mailbox);
// save email at draft to get the mime-content
message.Save(folderIdDrafts);
message.Load(new PropertySet(ItemSchema.MimeContent));
email.EmlContent = message.MimeContent;
if (template.SaveMessageOnSend)
{
message.SendAndSaveCopy(folderIdSent);
}
else
{
message.Send();
}
The email saved in draft. After this we get sometimes an follwoing error...
Type: Microsoft.Exchange.WebServices.Data.ServiceResponseException
Source: Microsoft.Exchange.WebServices
Message: The operation can't be performed because the item is out of date. Reload the item and try again.
HResult: -2146233088 (0x80131500)
InnerException: null
HashedSignature: 49E2BF981546C920B6A4BC0B27476A40
StackTrace:
bei Microsoft.Exchange.WebServices.Data.ServiceResponse.InternalThrowIfNecessary()
bei Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute()
bei Microsoft.Exchange.WebServices.Data.ExchangeService.SendItem(Item item, FolderId savedCopyDestinationFolderId)
bei Microsoft.Exchange.WebServices.Data.EmailMessage.InternalSend(FolderId parentFolderId, MessageDisposition messageDisposition)
It happens often with attachment over 6 MB.
The timeout is over 1 minute and the error becomes before this time.
The maxsize is over 10 MB
When i take this email at outlook and send it from the draft it works fine.
Have anybody an idea to solve this problem?
best regards steve
The reason you get the error is because the changekey is stale at the time you submit the message. This can happen if another client makes a modification on the message or Store level AV can do it see changekey in https://learn.microsoft.com/en-us/exchange/client-developer/web-service-reference/itemid?redirectedfrom=MSDN. With the line
message.Load(new PropertySet(ItemSchema.MimeContent));
This will be forcing the Exchange Store to do an one the fly conversion of the Message to Mime. I'd would try doing another load before sending the message and just ask for the IdOnly
message.Load(new PropertySet(ItemSchema.MimeContent));
email.EmlContent = message.MimeContent;
message.Load(new PropertySet(BasePropertySet.IdOnly));
That should ensure you have the latest changekey before send, otherwise you could probably just build the MIME message with something like MailKit and send it in one operation rather then saving the draft.
I am trying to get all Files and Folders from My Google Drive but it always returns 100 items. I am also unable to understand the nextPageToken and PageSize which is set to 1000 but record returns is 100. I am doing something wrong but don't know. if someone answer then plz explain nextpageToken with Example.
public static List<GoogleDriveFiles> GetDriveFiles(string nextPageToken)
{
Google.Apis.Drive.v3.DriveService service = GetService_v3(); // Getting Services
// Define parameters of request.
Google.Apis.Drive.v3.FilesResource.ListRequest FileListRequest = service.Files.List();
FileListRequest.Fields = "nextPageToken, files(*)";
FileListRequest.PageSize = 1000;
// FileListRequest.Q = "mimeType='application/vnd.google-apps.folder'";
// List files.
IList<Google.Apis.Drive.v3.Data.File> files = FileListRequest.Execute().Files;
List<GoogleDriveFiles> FileList = new List<GoogleDriveFiles>();
//files = files.Where(x => x.MimeType == "application/vnd.google-apps.folder").ToList();
if (files != null && files.Count > 0)
{
foreach (var file in files)
{
GoogleDriveFiles File = new GoogleDriveFiles
{
Id = file.Id,
Name = file.Name,
Size = file.Size,
Version = file.Version,
CreatedTime = file.CreatedTime,
discription = file.Description,
Parents = file.Parents,
WebContentLink = file.WebContentLink,
webLink = file.WebContentLink,
MimiTypes = file.MimeType
};
FileList.Add(File);
}
}
return FileList;
}
The code which is commented i also tried to get folders but still no use
Try using the Try this API! of files: list there you can check if the request you are making is correct.
I have been able to get 1000 files returned.
The nextPageToken is a token you have to save and then do another request using this token as the field pageToken, see all the request fields on Files: list parameters
Using this nextPageToken on the next request will get you the extra files the first request could not get.
I am trying to get the sent folders to display but it shows that the folder has no children in it. All folders are empty except inbox. I am using the following code.
using (var client = new ImapClient())
{
client.Connect(credentials.incoming_host, (int)credentials.incoming_port, credentials.incoming_ssl); //for SSL
client.Authenticate(credentials.email, credentials.password);
client.Inbox.Open(FolderAccess.ReadOnly);
var sentFolder= client.GetFolder(MailKit.SpecialFolder.Sent);
var Folders = client.GetFolders(client.PersonalNamespaces[0]);
client.Disconnect(true);
}
I tried sending an email using the same folder, and then append it like:
var sentFolder = imapclient.GetFolder(SpecialFolder.Sent);
sentFolder.Append(message);
My outlook did detect it and added into the sent folder.
From the MailKit README:
If the IMAP server supports the SPECIAL-USE or the XLIST (GMail) extension, you can get ahold of the pre-defined All, Drafts, Flagged (aka Important), Junk, Sent, Trash, etc folders like this:
if ((client.Capabilities & (ImapCapabilities.SpecialUse | ImapCapabilities.XList)) != 0) {
var drafts = client.GetFolder (SpecialFolder.Drafts);
} else {
// maybe check the user's preferences for the Drafts folder?
}
In cases where the IMAP server does not support the SPECIAL-USE or XLIST extensions, you'll have to come up with your own heuristics for getting the Sent, Drafts, Trash, etc folders. For example, you might use logic similar to this:
static string[] CommonSentFolderNames = { "Sent Items", "Sent Mail", "Sent Messages", /* maybe add some translated names */ };
static IFolder GetSentFolder (ImapClient client, CancellationToken cancellationToken)
{
var personal = client.GetFolder (client.PersonalNamespaces[0]);
foreach (var folder in personal.GetSubfolders (false, cancellationToken)) {
foreach (var name in CommonSentFolderNames) {
if (folder.Name == name)
return folder;
}
}
return null;
}
Using LINQ, you could simplify this down to something more like this:
static string[] CommonSentFolderNames = { "Sent Items", "Sent Mail", "Sent Messages", /* maybe add some translated names */ };
static IFolder GetSentFolder (ImapClient client, CancellationToken cancellationToken)
{
var personal = client.GetFolder (client.PersonalNamespaces[0]);
return personal.GetSubfolders (false, cancellationToken).FirstOrDefault (x => CommonSentFolderNames.Contains (x.Name));
}
Another option might be to allow the user of your application to configure which folder he or she wants to use as their Sent folder, Drafts folder, Trash folder, etc.
How you handle this is up to you.
It is necessary to open the folder otherwise it will appear empty.
IMailFolder personal = client.GetFolder(client.PersonalNamespaces[0]);
foreach (IMailFolder folder in personal.GetSubfolders(false, cancellationToken))
{
folder.Open(FolderAccess.ReadOnly);
Console.WriteLine($"folder.Name = {folder.Name}");
Console.WriteLine($"{folder.Name} messages : {folder.Count}");
}
I'm using EWS in order to retrieve emails, but when I want to retrieve the attachments I have to call the following function for each:
fileAttachment.Load();
Everytime I do that, it goes to the server. Is it possible to retrieve all the attachments at once? Also, is it possible to retrieve all the attachments for several mail items?
The ExchangeService object has a GetAttachments method which basically allows you to do a batch GetAttachment request. So if you want to load the attachments on several messages at once you need to do something like (first call loadpropertiesforitems which does a batch GetItem to get the AttachmentIds)
FindItemsResults<Item> fItems = service.FindItems(WellKnownFolderName.Inbox,new ItemView(10));
PropertySet psSet = new PropertySet(BasePropertySet.FirstClassProperties);
service.LoadPropertiesForItems(fItems.Items, psSet);
List<Attachment> atAttachmentsList = new List<Attachment>();
foreach(Item ibItem in fItems.Items){
foreach(Attachment at in ibItem.Attachments){
atAttachmentsList.Add(at);
}
}
ServiceResponseCollection<GetAttachmentResponse> gaResponses = service.GetAttachments(atAttachmentsList.ToArray(), BodyType.HTML, null);
foreach (GetAttachmentResponse gaResp in gaResponses)
{
if (gaResp.Result == ServiceResult.Success)
{
if (gaResp.Attachment is FileAttachment)
{
Console.WriteLine("File Attachment");
}
if (gaResp.Attachment is ItemAttachment)
{
Console.WriteLine("Item Attachment");
}
}
}
Cheers
Glen
I currently want to download all email messages (regardless in which folder they're in) to my SQL Server database.
Now while I know how to search for email messages or subscribe to streaming notifications, I've yet to learn on how to synchronize all messages from EWS to my database.
var emailMessages = GetItems<MSEmailMessage>(WellKnownFolderName.MsgFolderRoot);
foreach (var emailMessage in emailMessages)
{
Debug.WriteLine(emailMessage.Subject);
}
private IList<T> GetItems<T>(WellKnownFolderName wellKnownFolderName) where T : Item
{
IList<T> result = new List<T>();
Folder folder = Folder.Bind(_exchangeService, wellKnownFolderName);
if (folder.TotalCount > 0)
{
ItemView view = new ItemView(folder.TotalCount);
FindItemsResults<Item> items = _exchangeService.FindItems(wellKnownFolderName, view);
foreach (var resultItem in items.OfType<T>())
{
result.Add(resultItem);
}
}
return result;
}
This returns 0 email messages (it even threw an exception before checking for the folder.TotalCount before initializing a new ItemView...).
While checking for WellKnownFolderName.Inbox returns the email messages from the inbox, it does not allow me to query for sub folders to synchronize the entirety of the messages.
What am I missing?
You can build up a list of folders to search for mail in. Then iterate through each folder and get all the emails in that folder.
In the code snippet below we can create a folderSearchFilter with FolderTraversal set to Deep which will scan all sub folders of the target folder. We can then apply this filter to the two main well-known folders Inbox and SentItems
Once you have a list of folders to index, then you can use your own code to retrieve all the mails from that folder.
var view = new FolderView(int.MaxValue)
{
PropertySet = new PropertySet(BasePropertySet.FirstClassProperties) { FolderSchema.DisplayName }
};
SearchFilter foldersearchFilter = new SearchFilter.IsGreaterThan(FolderSchema.TotalCount, 0);
view.Traversal = FolderTraversal.Deep;
List<Folder> searchFolders;
try
{
searchFolders = new List<Folder>
{
Folder.Bind(ExchangeService, WellKnownFolderName.Inbox),
Folder.Bind(ExchangeService, WellKnownFolderName.SentItems)
};
}
catch (ServiceResponseException e) {}
searchFolders.AddRange(ExchangeService.FindFolders(WellKnownFolderName.Inbox, foldersearchFilter, view).Folders);
searchFolders.AddRange(ExchangeService.FindFolders(WellKnownFolderName.SentItems, foldersearchFilter, view).Folders);
var results = new List<Item>();
foreach (var searchFolder in searchFolders)
{
//Get all emails in this folder
}
Right, the root folder likely has 0 messages in it. When you do FindItems in a folder, the results don't bubble up from subfolders. You need to iterate over every folder if you want to get to their messages.