I'm using the EWS to download mails. As the mailbox is quite large, I'd like to filter the mails with the querystring. I found a method to only download mails of a specified date using Received:20/11/2019 but
This is not returning all the mails from this date (why - it seems, that only unread mails with attachments are part of the results)
I'd like to get all mails from 20 Nov. 2019 and later
Here is my code:
Microsoft.Exchange.WebServices.Data.ExchangeService exchange = new Microsoft.Exchange.WebServices.Data.ExchangeService(Microsoft.Exchange.WebServices.Data.ExchangeVersion.Exchange2013);
exchange.Credentials = new Microsoft.Exchange.WebServices.Data.WebCredentials("User", "********", "Domain");
exchange.AutodiscoverUrl("Name#domain.com");
string QString = "Recieved:20/11/2019";
if (exchange != null)
{
Microsoft.Exchange.WebServices.Data.FindItemsResults<Microsoft.Exchange.WebServices.Data.Item> Results = exchange.FindItems(Microsoft.Exchange.WebServices.Data.WellKnownFolderName.Inbox, QString, new Microsoft.Exchange.WebServices.Data.ItemView(100));
foreach(Microsoft.Exchange.WebServices.Data.Item MI in Results)
{
/*Print subject to command window*/
System.Console.WriteLine(MI.Subject);
}
}
I found an answer here, but its PHP and I'm not really skilled in it:
Getting emails after a specific date with php-ews (Exchange Web Services)
Ah, SearchFilter does work well for me:
Microsoft.Exchange.WebServices.Data.SearchFilter SF = new Microsoft.Exchange.WebServices.Data.SearchFilter.IsGreaterThanOrEqualTo(Microsoft.Exchange.WebServices.Data.ItemSchema.DateTimeReceived, new System.DateTime(2019,11,20));
Microsoft.Exchange.WebServices.Data.FindItemsResults<Microsoft.Exchange.WebServices.Data.Item> Results = exchange.FindItems(Microsoft.Exchange.WebServices.Data.WellKnownFolderName.Inbox, SF, new Microsoft.Exchange.WebServices.Data.ItemView(100));
Related
I'm using the MailKit client librairy to use their IMAP protocol in order to read my mails and search in it for a specific mail. It does work well for recent mail (less than a month and a half). But when I'm trying to search for an email that contains "myWordToSearch" from a long time (6 months old or stuff like that) it tells me that it does not exist, because it does not go that deep into the mails. Is there a way to retrieve/read ALL emails in order to filter them (like the search bar on gmail or stuff like that) ?
Here is my code :
using (var client = new ImapClient())
{
using (var cancel = new CancellationTokenSource())
{
client.Connect("imap." + provider , 993, true, cancel.Token);
client.Authenticate(myMail, myPassword, cancel.Token);
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadOnly, cancel.Token);
var mail = (SearchQuery.SubjectContains(myWordToSearch));
foreach (var uid in inbox.Search(mail, cancel.Token))
{
var message = inbox.GetMessage(uid, cancel.Token);
}
}
}
I am using this below code but unable to read my office 365 Inbox emails from C# code. Once I get this working then later I would need to read emails from shared mailbox.
I’d really appreciate if someone could please help me in fixing this issue or guide me what am I missing here ?
If I use Url as Office365 one then getting this error: "The request failed. The remote server returned an error 401. Unauthorized "
If I use Url as casx16 one (found this in company's Q/A portal) then getting this error: " No mailbox with such GUID "
using Microsoft.Exchange.WebServices.Data;
public static void ReadMyMailbox_2()
{
ExchangeService exchangeService = new ExchangeService();
exchangeService.Credentials = new WebCredentials("ajain", "password ", "MS"); /// ajain is my MSID
// exchangeService.AutodiscoverUrl("a_jain#xyz.com", RedirectionUrlValidationCallback);
exchangeService.Url = new Uri("https://casx16.xyz.com/ews/exchange.asmx");
// exchangeService.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
FolderId mailbox = new FolderId(WellKnownFolderName.Inbox, "a_jain#xyz.com");
ItemView itemView = new ItemView(10);
FindItemsResults<Item> result = exchangeService.FindItems(mailbox, itemView);
foreach (var msg in result)
{
EmailMessage message = EmailMessage.Bind(exchangeService, msg.Id);
Console.WriteLine(message.Subject);
}
}
It looks like you're setting up the ExchangeService object correctly. A couple things to try:
Try passing the full email (a_jain#xyz.com) to WebCredentials
Make sure your the domain you're passing to WebCredentials is correct
Try the WebCredentials constructor that only takes username and password.
Note: I don't think autodiscover will work with O365
I was able to succeed via a package I found called EAGetMail. Unfortunately, I realized soon after that they have a token system and this is not a free approach.
There are a couple other choices available, like using Outlook Mail REST API, and MimeKit, but I'm lost on how to achieve my end result because no "start to finish" code is available on either of these references that demonstrates how to parse an Inbox for an account.
I've started to write this with the help of Mimekit, but am not sure if this is the proper way at all.
I must imagine it looks something like:
using (var client = new SmtpClient ())
{
client.Connect("outlook.office365.com", 587);
client.Authenticate("myemail#office365account.com", "mypassword");
var message = MimeMessage.Load(stream);
}
I don't know how to setup the stream mentioned above, and I don't know if it's possible to do this with Mimekit and Office 365.
I'm open to seeing a solution for this in any other approach that's not through EAGetMail. If anyone has a lightweight solution ranging from actual establishing a connection, to pulling messages from the inbox, would be great to see!
I've got it using EWS (Exchange Web Services). Here's my code:
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
static void Main(string[] args)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.Credentials = new WebCredentials("email#myemail.com", "myPassword");
service.AutodiscoverUrl("email#myemail.com", RedirectionUrlValidationCallback);
//creates an object that will represent the desired mailbox
Mailbox mb = new Mailbox(#"email#myemail.com");
//creates a folder object that will point to inbox folder
FolderId fid = new FolderId(WellKnownFolderName.Inbox, mb);
//this will bind the mailbox you're looking for using your service instance
Folder inbox = Folder.Bind(service, fid);
//load items from mailbox inbox folder
if (inbox != null)
{
FindItemsResults<Item> items = inbox.FindItems(new ItemView(100));
foreach (var item in items)
{
item.Load();
Console.WriteLine("Subject: " + item.Subject);
}
}
}
I'm currently using Exchange Web Services in C#. I basically have a small application that reads emails from an inbox and process them.
I would like to forward those emails I receive as an attachment of an email. This attachment will be an outlook email that will include the original email (including its own attachments if any).
Any ideas?
Thanks!
EDIT:
Not sure why I'm getting the down votes but it seems this is not possible as the EWS API does not provide such functionality
You can create an ItemAttachment with EWS but you can't replicate fully what is possible in Outlook with MAPI. Eg with EWS you can create an ItemAttachment and then use the MIMEContent to create an attachment based on a current message as a workaround eg
FolderId Inboxid = new FolderId(WellKnownFolderName.Inbox, "target#domain.com");
ItemView InboxItemView = new ItemView(1);
FindItemsResults<Item> inFiResuls = service.FindItems(Inboxid,InboxItemView);
if(inFiResuls.Items.Count == 1){
EmailMessage fwdMail = new EmailMessage(service);
EmailMessage orgMail = (EmailMessage)inFiResuls.Items[0];
PropertySet psPropSet = new PropertySet(BasePropertySet.FirstClassProperties);
psPropSet.Add(ItemSchema.MimeContent);
orgMail.Load(psPropSet);
ItemAttachment emAttach = fwdMail.Attachments.AddItemAttachment<EmailMessage>();
emAttach.Item.MimeContent = orgMail.MimeContent;
ExtendedPropertyDefinition pr_flags = new ExtendedPropertyDefinition(3591,MapiPropertyType.Integer);
emAttach.Item.SetExtendedProperty(pr_flags,"1");
emAttach.Name = orgMail.Subject;
fwdMail.Subject = "see Attached";
fwdMail.ToRecipients.Add("user#domain.com");
fwdMail.Send();
}
This however doesn't give full fidelity of all the mapi properties associated with a particular message as the MIMEContent is just that, for most normal email messages this isn't an issue however for a message with an attached Outlook Task or other TNEF attachment then you would loose these of attachments or for other properties like categories,flags you would loose these also (you could copy these manually if needed).
Cheers
Glen
you can forward your email using this way. It first loads and reads the each emails with attachment who has "msg" extension. then forwards it to given address. see the below code
FindItemsResults<Item> findResults = exchange.FindItems(WellKnownFolderName.Inbox, newItemView(50,50));
Item[] msgItems = findResults.Where(msgItem => msgItem.HasAttachments).ToArray();
EmailMessage msgInfo = null;
var fileExtensions = new List<string> { "msg", "MSG", "Msg" };
foreach (MSEWS.Item msgItem in msgItems )
{
msgInfo = EmailMessage.Bind(exchange, msgItem.Id);
FileAttachment fa = msgInfo.Attachments[0] asFileAttachment;
if (fileExtensions.Any(ext => ext.Contains(fa.Name.Substring(fa.Name.Length - 3))))
{
fa.Load();
ResponseMessage responseMessage = msgInfo.CreateForward();
responseMessage.BodyPrefix = "messageBody";
responseMessage.ToRecipients.Add("toAddress");
responseMessage.Subject = "subject";
responseMessage.SendAndSaveCopy();
}
}
I'm currently pulling emails from an exchange inbox like so...
var exchangeService = new ExchangeService(ExchangeVersion.Exchange2007_SP1)
{
Credentials = new NetworkCredential("user", "password", "domain")
};
exchangeService.AutodiscoverUrl("user#domain.com");
var emails = exchangeService.FindItems(WellKnownFolderName.Inbox, new ItemView(5));
foreach (var email in emails)
{
//var senderEmail = email.???
}
The email object doesn't seem to have any property for getting the sender's email address. How do I get that?
Here's some quick source I pulled from a working project example.
Basically, you can get minor details just by casting your result to an EmailMessage. However if you want to get richer details about the sender (display name, etc.) then you have to make a specific, additional bind (Web service request) against the message.
findResults = exchangeService.FindItems(folder.Id, messageFilter, view);
foreach (Item item in findResults)
{
if (item is EmailMessage)
{
EmailMessage message;
if (!toFromDetails)
message = (EmailMessage)item;
else
message = EmailMessage.Bind(exchangeService, item.Id);
As you can see in this code, I have an option to perform the additional bind, because it can take awhile, and I'm often dealing with thousands of results from hundreds of mailboxes. Sometimes the additional time may not be worth it to a particular customer.