How to get group detail from Required Attendees using EWS - c#

I'm trying to fetch detail of the email address from Attendees because of more addresses in the group, this is my code.
public List<Meeting> getAll(string email, string sDate, string eDate)
{
List<Meeting> res = new List<Meeting>();
ExchangeService es = new ExchangeService();
string username = Properties.Settings.Default.username;
string password = Properties.Settings.Default.password;
SecureString ssPassword = new SecureString();
foreach (char x in password)
ssPassword.AppendChar(x);
es.Credentials = new NetworkCredential(username, ssPassword);
es.Url = new Uri("https://outlook.office365.com/ews/exchange.asmx");
FolderId folderID = new FolderId(WellKnownFolderName.Calendar, "xxxxxx#xxxx.com");
DateTime startDate = DateTime.ParseExact(sDate + " 00:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
DateTime endDate = DateTime.ParseExact(eDate + " 23:59:59", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
CalendarView cView = new CalendarView(startDate, endDate);
//cView.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
FindItemsResults<Item> resultItem = es.FindItems(folderID, cView);
foreach (Item item in resultItem.Items)
{
ServiceResponseCollection<GetItemResponse> itemResponseCollection = es.BindToItems(new[] { new ItemId(item.Id.UniqueId) }, new PropertySet(BasePropertySet.FirstClassProperties));
foreach (GetItemResponse itemResponse in itemResponseCollection)
{
Appointment app = (Appointment)itemResponse.Item;
res.Add(GetClassFromAppointment(app));
}
}
return res;
}
obj.Attendees = {aaa#xxxx.com, bbb#xxxx.com, Group#xxxx.com}
"Group#xxxx.com" include more emaill address: ccc#xxxx.com, ddd#xxxx.com
How to fetch detail's addresses from the group?

You should be about just to use the EWS ExpandGroup operation https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-expand-distribution-groups-by-using-ews-in-exchange-2013. eg with your code something like
// Return the expanded group.
ExpandGroupResults myGroupMembers = es.ExpandGroup("Group#xxxx.com");
// Display the group members.
foreach (EmailAddress address in myGroupMembers.Members)
{
Console.WriteLine("Email Address: {0}", address);
}
Another approach is because you using Office365 is that you can get the Group members using the Microsoft Graph API https://learn.microsoft.com/en-us/graph/api/group-list-members?view=graph-rest-1.0&tabs=http

Related

c# using Google.Apis.Calendar.v3 create meeting for next month every weekday 30 min event

I want to create daily weekdays event for 30 minit. it seems there is something wrong in
Recurrence = new String[] { "RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;UNTIL=" + nextmonthlastdayString + "T040000Z" },
I am not able to find solution tried many things.
public async Task<ActionResult> NewEvent()
{
var credential = await GetCredentialForApiAsync();
var initializer = new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "ASP.NET MVC5 Calendar Sample",
};
var service = new CalendarService(initializer);
var today = DateTime.Now;
var nextmonth = today.AddMonths(1).AddDays(-today.Day + 1);
var nextmonthString = nextmonth.ToString("yyyyMMdd");
var nxtmonthLastDate= DateTime.DaysInMonth(nextmonth.Year, nextmonth.Month);
DateTime lastDayNextMonth = nextmonth.AddDays(-nextmonth.Day + nxtmonthLastDate);
var nextmonthlastdayString = lastDayNextMonth.ToString("yyyyMMdd");
var lastDayofMonthString = DateTime.DaysInMonth(nextmonth.Year, nextmonth.Month).ToString(nextmonth.Year + "" + nextmonth.Month + "" + nextmonth.Day);
DateTime start = DateTime.Now;
DateTime end = start + TimeSpan.FromMinutes(30);
//start = DateTime.SpecifyKind(start, DateTimeKind.Local);
//end = DateTime.SpecifyKind(end, DateTimeKind.Local);
Event newEvent = new Event()
{
Summary = " Dealer Meeting",
Location = "1600 Amphitheatre Parkway., Mountain View, CA 94043",
Description = "A chance to learn more about Google APIs.",
Start = new EventDateTime()
{
DateTime = nextmonth,
TimeZone = "Asia/Kolkata",
},
End = new EventDateTime()
{
DateTime = lastDayNextMonth,
TimeZone = "Asia/Kolkata",
},
//Recurrence = new String[] { "RRULE:FREQ=DAILY;COUNT=5" },
//Recurrence = new String[] { "RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;UNTIL="+ nextmonth + "T040000Z" },
Recurrence = new String[] { "RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;UNTIL=" + nextmonthlastdayString + "T040000Z" },
Attendees = new EventAttendee[] {
new EventAttendee() { Email = "test#test.com" },
},
Reminders = new Event.RemindersData()
{
UseDefault = false,
Overrides = new EventReminder[] {
new EventReminder() { Method = "email", Minutes = 24 * 60 },
new EventReminder() { Method = "sms", Minutes = 10 },
}
}
};
String calendarId = "primary";
EventsResource.InsertRequest request = service.Events.Insert(newEvent, calendarId);
Event createdEvent = request.Execute();
return View();
}
Your RRULE is correct, the problem is theend date
As per documentation:
end
The (exclusive) end time of the event. For a recurring event, this is the end time of the first instance.
This means that you should modify
{
DateTime = lastDayNextMonth,
TimeZone = "Asia/Kolkata",
}
to
End = new EventDateTime()
{
DateTime = start + TimeSpan.FromMinutes(30),
TimeZone = "Asia/Kolkata",
}
Sample:
Start = new EventDateTime()
{
DateTime = "2021-11-01T09:00:00",
TimeZone = "Asia/Kolkata",
}
End = new EventDateTime()
{
DateTime = "2021-11-01T09:30:00",
TimeZone = "Asia/Kolkata",
}

Deleting SharePoint calendar links In Exchange via EWS

Does anyone have examples of how to delete a user's SharePoint calendar link in Outlook/Exchange via EWS Managed API? I am able to successfully find the Calendar link item, however the item.Delete(DeleteMode.HardDelete) executes without actually removing the calendar link. Any help or guidance would be appreciated.
Edited to include code:
//Will target a specific user mailbox with parameter mbMailboxname
static Dictionary<string, Folder> GetSharedCalendarFolders(ExchangeService service, String mbMailboxname)
{
Dictionary<String, Folder> rtList = new System.Collections.Generic.Dictionary<string, Folder>();
DateTime startDate = new DateTime(2018, 8, 1);
DateTime endDate = new DateTime(2018, 8, 31);
CalendarView calView = new CalendarView(startDate, endDate);
Mailbox mb = new Mailbox(mbMailboxname);
FolderId rfRootFolderid = new FolderId(WellKnownFolderName.Root, mb);
FolderView fvFolderView = new FolderView(1000);
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Common Views");
FindFoldersResults ffoldres = service.FindFolders(rfRootFolderid, sfSearchFilter, fvFolderView);
if (ffoldres.Folders.Count == 1)
{
PropertySet psPropset = new PropertySet(BasePropertySet.FirstClassProperties);
ExtendedPropertyDefinition PidTagWlinkAddressBookEID = new ExtendedPropertyDefinition(0x6854, MapiPropertyType.Binary);
ExtendedPropertyDefinition PidTagWlinkGroupName = new ExtendedPropertyDefinition(0x6851, MapiPropertyType.String);
psPropset.Add(PidTagWlinkAddressBookEID);
ItemView iv = new ItemView(1000);
iv.PropertySet = psPropset;
iv.Traversal = ItemTraversal.Associated;
SearchFilter cntSearch = new SearchFilter.IsEqualTo(PidTagWlinkGroupName, "Other Calendars");
FindItemsResults<Item> fiResults = ffoldres.Folders[0].FindItems(cntSearch, iv);
foreach (Item itItem in fiResults.Items)
{
Microsoft.Exchange.WebServices.Data.Item foundItem = itItem;
if (foundItem.Subject.ToString().Trim().Contains("Company Group Calendar"))
{
Console.WriteLine("Deleting calendar..");
//Executing the delete command here does not delete the calendar
foundItem.Delete(DeleteMode.MoveToDeletedItems);
}
}
}
return rtList;
}

Grouping not working as expected returning more emails than should

I have a sales order table with 23 transaction they are assigned to either department 1 or 2 I have looked at the data and its has the right assigns to it based on the cateory name however the problem is in my exucuation of the loop as I am getting 23 emails instead of just 5 sales order emails which is what it should be
Say for Example The table is
SalesOrder Number Depart
1111 1
1111 2
2222 2
2222 2
I should be getting one email for sales order 1111 sent to department 1 and one sent to department 2 but in the 2222 case I should get one email including all 2222
I think the issue is the group by does not no how to batch and I am asking what is the best way of doing that.
public void ProcessTransactions(string csvFileName)
{
var engine = new FileHelperEngine<SalesOrderHeader>();
var SalesOrders = engine.ReadFile(csvFileName);
var engine2 = new FileHelperEngine<SalesOrdersLines>();
var OrderLines = engine2.ReadFile(csvFileName);
GetSalesOrdersForImport();
ImportTransActions(SalesOrders.ToList());
CreateSalesOrder(_salesOrders.ToList(), _salesOrders.ToList());
var groupedSalesOrders = SalesOrders.OrderBy(x => x.SalesOrderNumber)
.GroupBy(x => x.SalesOrderNumber);
foreach(var group in groupedSalesOrders)
{
foreach (var item in group)
{
GetEmailsFromDepartment(item.DepartmentId);
GetSalesOrdersByDepartment(item.DepartmentId);
SendEmailNotificationPerDepartments(item.SalesOrderNumber.ToString());
}
}
}
My Get Emails for Department function is as below
public List<EmailDepartMents> _emailListsByDepartment { get; set; }
public void GetEmailsFromDepartment(string departmentId )
{
string connectionString = ConfigurationManager.AppSettings["connectionString"];
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
string selectQuery = #"SELECT [Code]
,[Name]
,[U_DepartmentId] AS DepartmentId
,[U_CardCode] as CardCode
,[U_Email] As Email
FROM [NKCoatings].[dbo].[#FIT_DEPARTMENTS]
where [U_DepartmentId]='" + departmentId +"'";
_emailListsByDepartment = connection.Query<EmailDepartMents>(selectQuery).ToList();
}
}
}
Edit 2
To Show send email function in case there is a issue with it in it self.
public void SendEmailNotificationPerDepartments(List SalesOrders)
{
try
{
SAPbobsCOM.UserTable sboTable = (SAPbobsCOM.UserTable)company.UserTables.Item("DEPARTMENTS");
SAPbobsCOM.BusinessPartners sboBP = (SAPbobsCOM.BusinessPartners)company.GetBusinessObject(SAPbobsCOM.BoObjectTypes.oBusinessPartners);
string emailAddressCC = ConfigurationManager.AppSettings["EmailAddressTo"];
string body;
string stmpServer = ConfigurationManager.AppSettings["SmtpAddress"];
string EmailUserName = ConfigurationManager.AppSettings["EmailUserName"];
string EmailPassword = ConfigurationManager.AppSettings["EmailPassword"];
string SmtpPort = ConfigurationManager.AppSettings["SmtpPort"];
MailMessage Msg = new MailMessage();
Msg.From = new MailAddress("development#test.com");
Msg.IsBodyHtml = true;
Msg.Subject = "Sales Orders Created in SAP";
body = "Sales orders has been imported into sap";
StringBuilder sb = new StringBuilder();
using (Html.Table table = new Html.Table(sb, id: "some-id"))
{
table.StartHead();
using (var thead = table.AddRow())
{
thead.AddCell("Works Order Number");
thead.AddCell("Purchase Order Number");
thead.AddCell("Date Required");
thead.AddCell("Stock Item Code");
thead.AddCell("Stock Item Name");
thead.AddCell("Customer");
}
table.EndHead();
table.StartBody();
foreach (var order in SalesOrders.Where(w=>w.DepartmentId == DepartmentId && w.SalesOrderNumber ==salesOrderId).OrderBy(o=>o.SalesOrderNumber))
{
using (var tr = table.AddRow(classAttributes: "someattributes"))
{
tr.AddCell(order.WorksOrderNumber, "style:font-bold;");
tr.AddCell(order.PurchaseOrderNumber.ToString());
tr.AddCell(order.DateRequired.ToString());
tr.AddCell(order.ItemCode.ToString());
tr.AddCell(order.Description.ToString());
if(sboBP.GetByKey(order.CardCode))
{
sboBP.CardName.ToString();
}
}
}
}
foreach (var address in _emailListsByDepartment)
{
Msg.To.Add(address.Email);
}
foreach (var address in emailAddressCC.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
{
Msg.CC.Add(address);
}
body = body + Environment.NewLine + sb.ToString();
Msg.Body = body;
SmtpClient smtp = new SmtpClient(stmpServer);
smtp.Credentials = new NetworkCredential(EmailUserName, EmailPassword);
smtp.Host = stmpServer;
smtp.Port = Convert.ToInt16(SmtpPort);
smtp.Send(Msg);
}
catch (Exception ex)
{
log.Error("Error has occoured at the send email notification " + ex.ToString());
}
}
I think i am just having a saturday night black out here but I hope someone can help me out maybe I am doing something wrong.
It could look something like this:
var list = new List<Email>()
{
new Email() {SalesOrderNumber = 10, Depart = 1},
new Email() {SalesOrderNumber = 10, Depart = 2},
new Email() {SalesOrderNumber = 20, Depart = 2},
new Email() {SalesOrderNumber = 20, Depart = 2},
};
var groups = list.GroupBy(e => e.SalesOrderNumber) // sort all emails by SalesOrderNumber
.Select(g => g.GroupBy(e => e.Depart)) // sort groups by Depart
.Aggregate((l, r) => l.Concat(r)); // aggregate result to only one collection of groups
foreach (var group in groups)
{
Console.WriteLine($"Group of SalesOrderNumber: {group.First().SalesOrderNumber}, Depart: {group.Key}");
foreach (var email in group)
{
Console.WriteLine(email);
}
}

Yahoo Finance API csv Historical data

I am using Yahoo Finanace CSV API for fetching currency exchange
https://code.google.com/p/yahoo-finance-managed/wiki/CSVAPI
Currencies = new List<CurrencyModel>();
string[] rates = null;
StringBuilder codes = new StringBuilder();
codes.Append("s=USDUSD=X");
codes.Append(",USDAUD=X");
codes.Append(",USDEUR=X");
codes.Append(",USDCAD=X");
codes.Append(",USDGBP=X");
codes.Append(",USDJPY=X");
codes.Append(",USDCHF=X");
codes.Append(",USDILS=X");
WebClient wc = new WebClient();
var response = wc.DownloadString(string.Format("http://finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&{0}", codes));
rates = response.Replace(#"""", "").Replace("=X", "").Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string rate in rates)
{
var split = rate.Split(',');
Currencies.Add(new CurrencyModel
{
FromCurrency = split[0].Substring(0, 3),
ToCurrency = split[0].Substring(3, 3),
Rate = split[1],
Date = split[2],
Time = split[3]
});
}
return Currencies;
}
My Question is how can I get the perchance between today's currency to yesterday?
Do I need to fetch yesterday and to calculate it my self? how can this be done
Thanks

EWS get Contacts - CustomerID & Account

ExchangeService service = this.GetService();
FolderId folderID = GetPublicFolderID(service, "My Address Book");
ContactsFolder folder = ContactsFolder.Bind(service, folderID);
int folderCount = folder.TotalCount;
var guid = DefaultExtendedPropertySet.PublicStrings;
var epdCP = new ExtendedPropertyDefinition(guid, "CustomProp", MapiPropertyType.Boolean);
var epdAccount = new ExtendedPropertyDefinition(guid, "Account", MapiPropertyType.String);
var epdCID = new ExtendedPropertyDefinition(guid, "CustomerID", MapiPropertyType.Integer);
var view = new ItemView(folderCount);
view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
view.PropertySet.Add(epdCP);
view.PropertySet.Add(epdAccount);
view.PropertySet.Add(epdCID);
var contacts = service.FindItems(folderID, view);
foreach (Contact contact in contacts)
{
bool CP;
string Account;
int CID;
contact.GetLoadedPropertyDefinitions();
contact.TryGetProperty(epdCP, out CP);
contact.TryGetProperty(epdAccuont, out Account);
contact.TryGetProperty(epdCID, out CID);
Console.WriteLine(String.Format("{0, -20} - {1} - {2}"
, contact.DisplayName
, contact.EmailAddresses[EmailAddressKey.EmailAddress1]
, CP
, Account
, CID
));
}
Goal is to get the Contact information out of a Public Address Book so I can sync it with another program we have.
For each Contact in the Public Address Book, this prints out DisplayName, EmailAddress and my Custom Property. No issues there.
The problem I have is I can't seem to get the right incantation to pull certain properties. CustomerID and Account are two examples that I can't seem to get to pull/print. They aren't "Custom", in as much as I haven't created them.
How can I get CustomerID and Account out of a contact via EWS?
The GUID isn't needed for the Account and CustomerID.. and the name needs to be the Unique ID:
var guid = DefaultExtendedPropertySet.PublicStrings;
var epdAccount = new ExtendedPropertyDefinition(0x3A00, MapiPropertyType.String);
var epdCID = new ExtendedPropertyDefinition(0x3A4A, MapiPropertyType.String);
var epdCP = new ExtendedPropertyDefinition(guid, "CustomBln", MapiPropertyType.Boolean);
var epdCI = new ExtendedPropertyDefinition(guid, "CustomInt", MapiPropertyType.Integer);
Now if only I can figure out why MapiPropertyType.Integer isn't mapping correctly.... Custom Boolean pulls properly, but Custom Integers aren't.
edit: Found that double works, where Integer doesn't.
var epdCI = new ExtendedPropertyDefinition(guid, "CustomInt", MapiPropertyType.Double);
Edited Example:
ExchangeService service = this.GetService();
FolderId folderID = GetPublicFolderID(service, "My Address Book");
ContactsFolder folder = ContactsFolder.Bind(service, folderID);
int folderCount = folder.TotalCount;
var guid = DefaultExtendedPropertySet.PublicStrings;
var epdAccount = new ExtendedPropertyDefinition(0x3A00, MapiPropertyType.String);
var epdCID = new ExtendedPropertyDefinition(0x3A4A, MapiPropertyType.String);
var epdCBLN = new ExtendedPropertyDefinition(guid, "CustomBln", MapiPropertyType.Boolean);
var epdCDBL = new ExtendedPropertyDefinition(guid, "CustomDbl", MapiPropertyType.Double);
var view = new ItemView(folderCount);
view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
view.PropertySet.Add(epdAccount);
view.PropertySet.Add(epdCID);
view.PropertySet.Add(epdCBLN);
view.PropertySet.Add(epdCDBL);
//var searchOrFilterCollection = new List<SearchFilter>();
//searchOrFilterCollection.Add(new SearchFilter.IsEqualTo(epdCBLN, true));
//searchOrFilterCollection.Add(new SearchFilter.IsEqualTo(epdAccount, "user"));
//var filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, searchOrFilterCollection);
var filter = new SearchFilter.IsEqualTo(epdAccount, "user");
var contacts = service.FindItems(folderID, filter, view);
foreach (Contact contact in contacts)
{
string Account;
int CID;
bool CBLN;
double CDBL;
contact.GetLoadedPropertyDefinitions();
contact.TryGetProperty(epdAccuont, out Account);
contact.TryGetProperty(epdCID, out CID);
contact.TryGetProperty(epdCBLN, out CBLN);
contact.TryGetProperty(epdCDBL, out CDBL);
Console.WriteLine(String.Format("{0, -20} - {1} - {2} - {3} - {4}"
, contact.DisplayName
, contact.EmailAddresses[EmailAddressKey.EmailAddress1]
, Account
, CID
, CBLN
, CDBL
));
}

Categories