I want to retrieve all mails in a conversation when a user selects an email.
I know that I can use this - https://msdn.microsoft.com/en-us/library/office/ff869870(v=office.15).aspx, but for some microsoft exchange accounts, getrootitems returning zero.
So, is there any other way that works for microsoft exchange ?
More details:
My outlook showing "Online with microsoft exchange" at bottom right.
Below process is slow as I have 1000's of mails in inbox, so this wont help me.
IEnumerable mail =
folder.Items.OfType().Where(m => m.Subject == "Test").Select(m => m);
The GetRootItems method of the Conversation class has the following description in MSDN:
If all items are deleted from the conversation after the Conversation object has been obtained, GetRootItems returns a SimpleItems collection with zero objects. In this case, the Count property of the SimpleItems collection returns 0.
Try to use the cached exchange mode instead.
Related
I am using C# with the Exchange Web Service (EWS).
I have meetings that I need to forward and whenever I do they get stripped, but only from some accounts and not others. The link for the meeting is still there but it is not being recognised by the online Outlook as a meeting item, nor by Teams which is connected to the account.
This even happens if I manually forward, but again only if I forward emails that are from some accounts - some other accounts are fine!
I'm using this on incoming emails:
var fwdEmailArr = new EmailAddress[1];
fwdEmailArr [0] = fwdEmail;
MeetingRequest appointment = MeetingRequest.Bind(service, email.Id);
appointment.Forward("", fwdEmailArr);
This is the same issue if I use the email.forward as well, etc.
However, if I create a new appointment and send it, it doesn't get stripped - this is with the same addresses.
Appointment appt = new Appointment(service);
appt.Subject = email.Subject;
appt.Body = appointment.Body;
appt.Start = appointment.Start;
appt.End = appointment.End;
appt.Location = appointment.Location;
appt.RequiredAttendees.Add(fwdEmail);
foreach (var reqAtt in appt.RequiredAttendees)
{
appt.RequiredAttendees.Add(reqAtt);
}
foreach (var reqAtt in appt.OptionalAttendees)
{
appt.OptionalAttendees.Add(reqAtt);
}
appt.RequiredAttendees.Add(appointment.From.Address);
appt.Save(SendInvitationsMode.SendToAllAndSaveCopy);
So, I could do this but it means that they are no longer the same meeting and declining the original wont decline this. Unless there's a way I can connect the meetings or something?
Any ideas how I can stop the meeting being stripped?
Or alternatively just add another recipient to the current meeting, that will show on their calendar?
If anyone comes here with a similar issue, it turns out that, first of all you need to make sure you define the correct server version on the service declaration:
service = new ExchangeService(ExchangeVersion.Exchange2016){}
In addition, for some reason some images when attached to the forwarded email for some reason confuse EWS and make it think there's no meeting. I got around this by scanning the MIME content and just extracting the calendar block and deleting all other attachments.
This has been working flawlessly for about 5 months.
I'm working on buffer solution for MS Exchange server.
The buffer should store events and keep them in sync with Exchange server.
I code in C# and use Managed EWS.
The buffer queries Exchange for appointments changed in sequential intervals:
(t[1], t[2]), (t[2], t[3]), (t[3], t[4])
...
I use Appointment.LastModifiedTime field to filter out appointments changed in interval (t[x], t[x+1]). However I discovered, that this field takes it value from time of modification on client. What I need is some timestamp of modification on server.
Imagine the case: user X goes offline and adds appointment on t[Y] in his Outlook client. On t[Z] = t[Y] + 24h user X goes online. His Outlook client will sync with Exchange server and this new appoinment appears on it with LastModifiedDate = t[Y]. Is there some field to get t[Z] ?
For now I see full sync as a 100% working alternative to this, but it is a 'hammer solution' with obvious drawbacks. I will have to use it in case nobody can give an alternative :)
For my outlook addin I need to handle emails, calculate an unique hash and store this hash on a server/database. For example :
There are 4 users :
user1#company.com
user2#company.com
user3#company.com
randomperson#gmail.com
Case 1:
User1 sends a mail to User2 and User3. User2 wants to store the mailhash serverside, so he clicks an addin button. A hash is calculated with code like this
var accessor = mailItem.PropertyAccessor;
var subject = accessor.GetProperty(_PR_SUBJECT_W_TAG).ToString();
var messageId = accessor.GetProperty(_PR_INTERNET_MESSAGE_ID_W_TAG).ToString();
var hash = CalulateHash(subject + messageId);
This hash is stored on the server. If User3 tries to store the hash of the mail too, he gets the same hash (cause subject and messageid should be the same ==> rfc822) and the server knows, he got this hash already. This works very well.
Case 2:
User1 wants to send a mail to User2,User3 and randomperson. Cause randomperson doesn't belong to their company, User1 want to use the function SendAndStore(). Before the mail is send, a custom property is added to the new mail
mailItem.UserProperties.Add("HandleAfterSent", MSOutlook.OlUserPropertyType.olText);
var aasProp = mailItem.UserProperties.Find("HandleAfterSent");
if (aasProp != null)
{
aasProp.Value = "some_value";
}
mailItem.Save();
SendMailItem(mailItem);
Moreover, there is a possibility to get notified if a new item is added to a inboxfolder. So I observe the sent folder.
inbox = outlookNameSpace.GetDefaultFolder(MSOutlook.OlDefaultFolders.olFolderSentMail);
items = inbox.Items;
items.ItemAdd += OnInboxItemAdded;
If the mail is send via SendMailItem(mailItem);, the handler is called (works fine too). But unfortunately I have problems with calculating the hash of the send mail, cause this mail has no Message-ID. Does anyone have a idea, how to get the Message-ID of a mail, which was send just now.
I already tried to set the Message-ID on my own, but it is overriden from MS Exchange server.
EDIT :
Outlook is on cache mode. I need a possibility to get the Message-ID for this scenario too.
EDIT2 (in addition to comments) :
Case 3:
randomperson wants to send a mail to User1,User2 and User3. Cause randomperson doesn't belong to their company, User1 want to use the function StoreFromInbox(). Mails in the inbox of all three Users have the same Message-ID. But they have different _PR_SEARCH_KEY_ , so we can't use this property.
Try to use PR_SEARCH_KEY MAPI property - it should stay the same after the message is sent and moved to the Sent Items folder.
Is there a way to determine if a given email in the inbox has been answered (Reply to Sender)
Actually I am using the following code, which does not work correct
ExtendedPropertyDefinition pr_last_verb_executed = new ExtendedPropertyDefinition(0x1081, MapiPropertyType.Integer);
PropertySet psPropSet = new PropertySet(pr_last_verb_executed);
ItemId itemId = new ItemId("<PLACEHOLDER FOR AN Exchange EMail ID>");
EmailMessage serverMail = EmailMessage.Bind(exchangeService, itemId, psPropSet);
int lastState = 0; // should become 102 if email has been answered
serverMail.TryGetProperty(pr_last_verb_executed, out lastState); // does not return anything to variable lastState
As I found out updating Exchange Server to a newer version solves this problem. So this ia a bug in older versions of Microsoft Exchange Server.
The best thing to do would be to look at the messages in question with a MAPI editor like MFCMapi or OutlookSpy that will tell you if that property has been set or not (its an optional property set by the client). The property is just an indicator of the last action a client took https://msdn.microsoft.com/en-us/library/ee218425(v=exchg.80).aspx reply is one action but there are many others. PidTagIconIndex https://msdn.microsoft.com/en-us/library/office/cc815472.aspx is another indicator property you can use to do the same thing. EWS also have conversation operations https://msdn.microsoft.com/en-us/library/office/dn610351(v=exchg.150).aspx if you are looking to work with conversation.
Cheers
Glen
I am using Exchange Web Services trying to find the Organizer of the meeting's email address
I have tried using
Appoint.Organizer.Address
but some of the properties are null (see image).
How do I get the email address of the organizer?
Link to image (sorry not enough rep to embed)
http://i.stack.imgur.com/wSv2r.png
What operation are you using ? If you have just used FindItems then that's what you would expected because only the displayName of the Sender (which is the Organizer) is returned with FindItems. To get the Address property populated you would need to do a GetItem (or Load in the Managed API).Or if you really want to save a call you could try using the PidTagSenderSmtpAddress extended property http://msdn.microsoft.com/en-us/library/office/jj713594(v=office.15).aspx
Cheers
Glen
Do you know how this meeting came into the mailbox? Was it sent from a sender outside of Exchange, or another mailbox in that Exchange organization? What version of Exchange? Also how are you binding to the appointment? It would be good to see that code. I've tried this with a few meetings here and they all have the Address property populated. Your screenshot shows a MailboxType field of "OneOff", and I'm not sure off the top of my head how to make that happen.
Typically "OneOff" refers to a recipient that couldn't be resolved. In this case, you might try taking the information that is present (in this case the display name) and calling ResolveName to see if you can get the address that way.