c# EWS 2007 Address from empty - c#

I'm working on a WinForms Application that uses EWS to read mails of our Exchange Server. The Exchange is at Version 2007. I could successfully read, move, delete and send emails through EWS. I'm using Autodiscover to authenticate and select the Mailbox. The only problem is that I never get any sender e-mail address. The only thing I get is the name of the sender but no address.
This is my code so far:
Service1 = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
Service1.Credentials = new WebCredentials(Properties.Settings.Default.Username, Properties.Settings.Default.Password);
Service1.Url = new Uri(Properties.Settings.Default.Serviceurl);
EmailMessage messageAtt = EmailMessage.Bind(Service1, item.Id, new PropertySet(BasePropertySet.IdOnly, ItemSchema.Attachments, ItemSchema.HasAttachments, EmailMessageSchema.IsRead));
EmailMessage messageData = (EmailMessage)item;
foreach (Attachment attachment in messageAtt.Attachments)
{
String from = messageData.Sender.Address.ToString();
}
This is what I get when I debug:
Can anyone give me a suggestion what I am mistaking here? Is there a Problem with what I wrote or could it even be a set up problem of the exchange Server?

The problem seems to be the definition of the EmailMessage object:
By defining the EmailMessage with explicit conversion not all attributes are geting transfered to the new object. If you try it with the upper EmailMessage object which gets defined by the .Bind() method, it wont work either. The reason that happens is due to the PropertySet passed as 3rd parameter. The only solution I found is to create a 3rd object:
EmailMessage messageInfo = EmailMessage.Bind(useService, item.Id);
The disadvantage of this Object is, that you won't be able to see if the item has an attachement or not.
Hope this helps anyone not wasing his time on a stupid mistake like that ;)

Related

How to stop meeting being stripped on forward (EWS)

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.

Getting display name from EWS when passing in just an email address

I've using a custom GetMailTips SOAP call (since the EWS for Core 2.0 doesn't support it) to get Out of Office info for a batch of email addresses.
How can I get the display names of the users that I am passing in the email address for?
I can call ResolveName of the managed API and that works but it has to be done one at a time and that is slow. I would like to ideally get this info out when I make my GetMailTips request and failing that make a call with all the email addresses to get the Display Names all at once. I read there is meant to be a ResolveNames method but that's not in the API either.
Any help appreciated
Autodiscover can return that for multiple users eg
AutodiscoverService adService = new AutodiscoverService(ExchangeVersion.Exchange2013_SP1);
adService.Credentials = new NetworkCredential("user#d.com", "pass");
adService.RedirectionUrlValidationCallback = adAutoDiscoCallBack;
List<String> Users = new List<string>();
Users.Add("user1#domain.com");
Users.Add("user2#domain.com");
GetUserSettingsResponseCollection usrSettings = adService.GetUsersSettings(Users, UserSettingName.UserDisplayName);
foreach(GetUserSettingsResponse usr in usrSettings)
{
Console.WriteLine(usr.Settings[UserSettingName.UserDisplayName]);
}
Another way would be to create a Message and add the email address as recipients then save it to the drafts folders and the address should get resolved against the GAL.

Mailkit: fetch messages and copying them to MySQL, attachments to drive

I've been using this code of MailSystem.Net so far to get emails from an Imap INBOX and added options to retrieve mail using $"SENTSINCE {Date}".
string mailBox = "INBOX";
public IEnumerable<Message> GetMailsSince(string mailBox) {
return GetMails(mailBox, $"SENTSINCE {DateTime.Now.AddDays(-3).ToString("dd-MMM-yyyy")}").Cast<Message>();
}
private MessageCollection GetMails(string mailBox, string searchPhrase) {
Mailbox mails = Client.SelectMailbox(mailBox);
MessageCollection messages = mails.SearchParse(searchPhrase);
return messages;
}
But even after studying mailkit for hours I can't seem to distill out how to do the same thing. My goal is to get a list of message object whose properties I can then map to another class I created which writes it into a mysql database. I also want to save the attachments to disk. All this works fine so far but performance is an issue. I'm hoping mailkit will greatly improve that.
My main source has been the sample here but because I'm not familiar with async programming yet and treeviews it's hard to see through it.
How can I hard code that I want "INBOX" as ´IMailFolder´?
Where or how can I use the "SENTSINCE {Date}" filter in Mailkit?
How do I get an ´IEnumerable´ of Mailkits equivalent to the Message object in mailsystem (´IMessageSummary´ maybe)?
If you can point me to some code or even convert the linked MailSystem.Net example to Mailkit that would be fantastic.
MimeMessage is the equivalent of MailSystem.NET's Message object, but that's not what you want. What you want is MailKit's IMessageSummary which will allow you to download individual MIME parts (aka "attachments").
It also allows you to get summary information about the message (flags, received date (aka "InternalDate") pre-parsed/decoded common header values (such as subject, sender, recipients, etc) really quickly because the IMAP server has those pieces of information cached in its database for quick retrieval.
using (var client = new ImapClient ()) {
client.Connect ("imap.mail-server.com", 993, SecureSocketOptions.SslOnConnect);
client.Authenticate ("username", "password");
// if you don't care about modifying message flags or deleting
// messages, you can open the INBOX in read-only mode...
client.Inbox.Open (FolderAccess.ReadOnly);
// search for messages sent since a particular date
var uids = client.Inbox.Search (SearchQuery.SentAfter (date));
// using the uids of the matching messages, fetch the BODYSTRUCTUREs
// of each message so that we can figure out which MIME parts to
// download individually.
foreach (var item in client.Inbox.Fetch (uids, MessageSummaryItems.BodyStructure MessageSummaryItems.UniqueId)) {
foreach (var attachment in item.Attachments.OfType<BodyPartBasic> ()) {
var part = (MimePart) client.Inbox.GetBodyPart (item.UniqueId, attachment);
using (var stream = File.Create (part.FileName))
part.ContentObject.DecodeTo (stream);
}
}
}
Note: Each property on IMessageSummary has a corresponding MessageSummaryItems enum value that you will need to use in order to have that property populated.
For example, if you want to use IMessageSummary.Envelope, you will need to include MessageSummaryItems.Envelope in your Fetch() request.
Since MessageSummaryItems is marked with the [Flags] attribute, you can bitwise-or enum values together like this:
MessageSummaryItems.BodyStructure | MessageSummaryItems.Envelope and both pieces of information will be fetched.
Update:
Here's the inefficient way that is closer to how MailSystem.NET does it.
using (var client = new ImapClient ()) {
client.Connect ("imap.mail-server.com", 993, SecureSocketOptions.SslOnConnect);
client.Authenticate ("username", "password");
// if you don't care about modifying message flags or deleting
// messages, you can open the INBOX in read-only mode...
client.Inbox.Open (FolderAccess.ReadOnly);
// search for messages sent since a particular date
var uids = client.Inbox.Search (SearchQuery.SentAfter (date));
// using the uids of the matching messages, fetch the BODYSTRUCTUREs
// of each message so that we can figure out which MIME parts to
// download individually.
foreach (var uid in uids) {
var message = client.Inbox.GetMessage (uid);
foreach (var attachment in message.Attachments.OfType<MimePart> ()) {
using (var stream = File.Create (attachment.FileName))
attachment.ContentObject.DecodeTo (stream);
}
}
}
Note: if you care about saving message/rfc822 attachments, then take a look at this StackOverflow answer: MailKit save Attachments
The "Inbox" folder is always available on an IMAP mail acccount. With MailKit it is available as ImapClient.Inbox. For the date filtering you could use the DateSearchQuery class. The getting started page of MailKit pretty much covers all your questions.

Internet Message ID FROM EWS Managed API Send Email c#

I am trying to discover if there is a way to determine the internet message ID after sending an email using the EWS Managed API. I understand you can go in there and get the results from the sent box, but the server that is sending these emails is sending multiple emails at a time from different services.
No you can't, basically because EWS sends message Asynchronously the Id isn't available see https://social.msdn.microsoft.com/Forums/azure/en-US/dd034b8c-ffa1-4ae0-9025-45fcf520c9e5/updateitem-does-not-return-itemid?forum=exchangesvrdevelopment
As a work around you might want to consider setting the Internet messageId on the Message before you send it. As long as it valid and unique it should work okay eg
ExtendedPropertyDefinition PidTagInternetMessageId = new ExtendedPropertyDefinition(4149, MapiPropertyType.String);
EmailMessage ema = new EmailMessage(service);
ema.Subject ="test from ews";
ema.Body = new MessageBody("test<br>Rgds<>");
ema.ToRecipients.Add("gscales#domain.com");
ema.SetExtendedProperty(PidTagInternetMessageId,("<" +Guid.NewGuid().ToString() + "#domain.com>"));
ema.SendAndSaveCopy();
Also if you save the message first as a draft before sending it the server will assign the MessageId property which which should then be able to read back using Load.
Cheers
Glen

EWS get Email Message Body from replied from Thunderbird

I am using EWS (Exchange 2010 SP1) and I am working with emails (subject,recipients,body).
My problem is that when I am asking these information's everything is fine except the body of the email, because I need only the newly added message (for example if I reply for a past email) but I am getting back the whole body of the email.
PropertySet propSet = new PropertySet(new[] { ItemSchema.UniqueBody, ItemSchema.Subject, ItemSchema.DateTimeReceived, EmailMessageSchema.From, EmailMessageSchema.CcRecipients, EmailMessageSchema.ToRecipients });
propSet.RequestedBodyType = BodyType.Text;
email.Load(propSet);
This is important for me because i need to insert each email reply to DB.
If is use the webmail client everything is fine, but when I`m using Thunderbird this issue occurs.
Any suggestions??

Categories

Resources