How to retrieve the extendedProperties associated with emails in the sent folder from exchange - outlook

We have created extendedProperties on emails using
val uId = getUniqueId();
val emailExtendedPropDef = new ExtendedPropertyDefinition(uId,"uniqueId", MapiPropertyType.String)
try {
email.setExtendedProperty(emailExtendedPropDef, uId.toString)
email.sendAndSaveCopy()
} catch {
case e: Exception =>
error(s"Exception in setting extended property for user $from", e)
throw e
}
Now we want to iterate over the emails in sent folder and go over the extendedProperties for the emails that have been set
val view = new ItemView(1000)
var extendedPropertyIndex = 0
var bodyList = new ListBuffer[String]()
val propertySet = new PropertySet(BasePropertySet.FirstClassProperties
try {
val findResults = service.findItems(WellKnownFolderName.SentItems, view)
if (findResults.getTotalCount > 0) {
val iterator = findResults.getItems().iterator()
while(iterator.hasNext) {
val item = iterator.next()
val extendedPropertyCollection = item.getExtendedProperties()
println("count is "+extendedPropertyCollection.getCount())
if (extendedPropertyCollection.getCount() > 0)
{
//do some processing
}
}
}
}
We are able to successfully retrieve the items but not their extended properties not sure why
We have been getting the count as 0 eventhough we know for these items we have set the extendedProperty using the above logic ......
It will be of great help if someone could point us in the right direction on why we are receiving 0 count for the extended properties and also our requirement is to retrieve all the emails with extendedProperties set
Update : tried with these options
val emailIdPropDef = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings,"uniqueId", MapiPropertyType.String)
val propertySet = new PropertySet(BasePropertySet.FirstClassProperties, emailIdPropDef)
view.setPropertySet(propertySet)
But still no luck any pointer in the right direction will be of great help

Exchange will only return the extended properties you request it to return. So you need to add the extended property to the PropertySet your using in the FindItems operation and it will then get returned if it has been set on any objects that FindItem returns.eg this property
val emailExtendedPropDef = new ExtendedPropertyDefinition(uId,"uniqueId", MapiPropertyType.String)
needs to be added to this Propertyset
val propertySet = new PropertySet(BasePropertySet.FirstClassProperties)
and that property set should be used on this ItemView
val view = new ItemView(1000)
val.PropertySet = propertySet

Related

Populate SQLite database from generic "list of items"

I use a SQLite database to populate a listview with a generic list of TodoItems:
ListView.ItemsSource = await App.Database.GetItemsAsync("SELECT * FROM [TodoItem]");
I can read data of the same kind from a database source using the HttpClient class as well via
public async Task<List<TodoItem>> ReadDataAsync ()
....
Items = new List<TodoItem> ();
....
var content = await response.Content.ReadAsStringAsync ();
Items = JsonConvert.DeserializeObject <List<TodoItem>> (content);
....
return Items;
whereafter I can use this as a data source as well:
ListView.ItemsSource = await App.ReadDataAsync();
Both ways work well.
What I want now is combine both routines to accomplish a code which checks whether we have an online connection, if yes, drop the database and populate it using the result of ReadDataAsync from above, if no, leave the database alone.
I found no way to directly assign a List to my database, overwriting the whole contents, I think of something like:
App.Database.Items = await App.ReadDataAsync();
but SQLite doesn't seem to expose the data store directly. How can I accomplish this?
For android for example, you could try: There's no need to drop the database.
//Check for internet connection
var connectivityManager =
(ConnectivityManager)this.GetSystemService("connectivity");
var activeConnection = connectivityManager.ActiveNetworkInfo;
if ((activeConnection != null) && activeConnection.IsConnected)
{
//Make call to the API
var list = await App.ReadDataAsync();
//Update or Insert local records
foreach (var item in list)
{
var success = UpdateOrInsert(item);
//Do something after - like retry incase of failure
}
}
The UpdatedOrInsert method can look like:
private bool UpdateOrInsert(TodoItem item)
{
var rowsAffected = App.Database.Update(item);
if (rowsAffected == 0)
{
// The item doesn't exist in the database, therefore insert it
rowsAffected = App.Database.Insert(item);
}
var success = rowsAffected > 0;
return success;
}

CRM SDK 2013 Activity doesn't exist just after creating it

I have a custom comment activity which I'm updating in code and this used to work but has started failing recently. It creates the activity but when I try to retrieve it or execute SetStateResponse on it, I get "tk_comment With Id = 9a1686d1-7d9d-e611-80e3-00155d001104 Does Not Exist" - which doesn't make sense as I've just created it! The activity record shows up against the account but I can't click on it there or do anything (Record is unavailable - The requested record was not found or you do not have sufficient permissions to view it.).
This is the code I'm using. I'd love you to tell me I've made some simple mistake :)
using (_serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig))
{
_serviceProxy.EnableProxyTypes();
try
{
tk_comment comment = new tk_comment();
int maxLength = 190; //subject has a max length of 200 characters
if (subject.Length > maxLength)
{
comment.Subject = subject.Substring(0, maxLength);
comment.Description = subject.Substring(maxLength, subject.Length - maxLength);
}
else
{
comment.Subject = subject;
}
comment.RegardingObjectId = entity.ToEntityReference();
comment.ActualStart = CommentDate;
comment.ActualEnd = CommentDate;
comment.ScheduledStart = CommentDate;
comment.ScheduledEnd = CommentDate;
Guid commentID = _serviceProxy.Create(comment);
try
{
tk_comment aComment = (tk_comment)_serviceProxy.Retrieve(tk_comment.EntityLogicalName, commentID, new ColumnSet(allColumns: true));
}
catch (Exception ex)
{
SingletonLogger.Instance.Error("Always an error here " + ex.Message);
}
Account test = (Account) _serviceProxy.Retrieve(Account.EntityLogicalName, entity.Id, new ColumnSet(allColumns: true));
// tk_comment newComment = (tk_comment)_serviceProxy.Retrieve(tk_comment.EntityLogicalName, commentID, new ColumnSet(allColumns: true));
SetStateRequest request = new SetStateRequest();
request.EntityMoniker = new EntityReference(tk_comment.EntityLogicalName, commentID);
request.State = new OptionSetValue((int) tk_commentState.Completed); //completed
request.Status = new OptionSetValue(2); //completed
SetStateResponse response = (SetStateResponse)_serviceProxy.Execute(request); //always an error here too
}
Appreciate any suggestions
Cheers, Mick
It seems like you don't have proper read permission of this custom activity entity.
OR You need to validate all the permissions of this custom entity.

How to retrieve all contacts from Microsoft Exchange using EWS Managed API?

all I need to do is to retrieve all contacts from Microsoft Exchange. I did some research and the best possible option for me should be to use EWS Managed API. I am using Visual Studio and C# programming leanguage.
I think I am able to connect to Office365 account, because I am able to send a message in a program to specific email. But I am not able to retrieve the contacts.
If I create a contact directly in source code, the contact will be created in Office365->People aplication. But I don't know why! I thought I was working with Exchange aplication.
Summarize:
Is there any possibility how to get all contacts from Office365->Admin->Exchange->Acceptencers->Contacts ?
Here is my code:
class Program
{
static void Main(string[] args)
{
// connecting to my Exchange account
ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials("office365email#test.com", "password123");
/*
// debugging
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
*/
service.AutodiscoverUrl("office365email#test.com", RedirectionUrlValidationCallback);
// send a message works good
EmailMessage email = new EmailMessage(service);
email.ToRecipients.Add("matoskok1#gmail.com");
email.Subject = "HelloWorld";
email.Body = new MessageBody("Toto je testovaci mail");
email.Send();
// Create the contact creates a contact in Office365 -> People application..Don't know why there and not in Office365 -> Exchange
/*Contact contact = new Contact(service);
// Specify the name and how the contact should be filed.
contact.GivenName = "Brian";
contact.MiddleName = "David";
contact.Surname = "Johnson";
contact.FileAsMapping = FileAsMapping.SurnameCommaGivenName;
// Specify the company name.
contact.CompanyName = "Contoso";
// Specify the business, home, and car phone numbers.
contact.PhoneNumbers[PhoneNumberKey.BusinessPhone] = "425-555-0110";
contact.PhoneNumbers[PhoneNumberKey.HomePhone] = "425-555-0120";
contact.PhoneNumbers[PhoneNumberKey.CarPhone] = "425-555-0130";
// Specify two email addresses.
contact.EmailAddresses[EmailAddressKey.EmailAddress1] = new EmailAddress("brian_1#contoso.com");
contact.EmailAddresses[EmailAddressKey.EmailAddress2] = new EmailAddress("brian_2#contoso.com");
// Specify two IM addresses.
contact.ImAddresses[ImAddressKey.ImAddress1] = "brianIM1#contoso.com";
contact.ImAddresses[ImAddressKey.ImAddress2] = " brianIM2#contoso.com";
// Specify the home address.
PhysicalAddressEntry paEntry1 = new PhysicalAddressEntry();
paEntry1.Street = "123 Main Street";
paEntry1.City = "Seattle";
paEntry1.State = "WA";
paEntry1.PostalCode = "11111";
paEntry1.CountryOrRegion = "United States";
contact.PhysicalAddresses[PhysicalAddressKey.Home] = paEntry1;
// Specify the business address.
PhysicalAddressEntry paEntry2 = new PhysicalAddressEntry();
paEntry2.Street = "456 Corp Avenue";
paEntry2.City = "Seattle";
paEntry2.State = "WA";
paEntry2.PostalCode = "11111";
paEntry2.CountryOrRegion = "United States";
contact.PhysicalAddresses[PhysicalAddressKey.Business] = paEntry2;
// Save the contact.
contact.Save();
*/
// msdn.microsoft.com/en-us/library/office/jj220498(v=exchg.80).aspx
// Get the number of items in the Contacts folder.
ContactsFolder contactsfolder = ContactsFolder.Bind(service, WellKnownFolderName.Contacts);
Console.WriteLine(contactsfolder.TotalCount);
// Set the number of items to the number of items in the Contacts folder or 50, whichever is smaller.
int numItems = contactsfolder.TotalCount < 50 ? contactsfolder.TotalCount : 50;
// Instantiate the item view with the number of items to retrieve from the Contacts folder.
ItemView view = new ItemView(numItems);
// To keep the request smaller, request only the display name property.
view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ContactSchema.DisplayName);
// Retrieve the items in the Contacts folder that have the properties that you selected.
FindItemsResults<Item> contactItems = service.FindItems(WellKnownFolderName.Contacts, view);
// Display the list of contacts.
foreach (Item item in contactItems)
{
if (item is Contact)
{
Contact contact1 = item as Contact;
Console.WriteLine(contact1.DisplayName);
}
}
Console.ReadLine();
} // end of Main() method
/*===========================================================================================================*/
private static bool CertificateValidationCallBack(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
// If the certificate is a valid, signed certificate, return true.
if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
return true;
}
// If there are errors in the certificate chain, look at each error to determine the cause.
if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
if (chain != null && chain.ChainStatus != null)
{
foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
{
if ((certificate.Subject == certificate.Issuer) &&
(status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
{
// Self-signed certificates with an untrusted root are valid.
continue;
}
else
{
if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
{
// If there are any other errors in the certificate chain, the certificate is invalid,
// so the method returns false.
return false;
}
}
}
}
// When processing reaches this line, the only errors in the certificate chain are
// untrusted root errors for self-signed certificates. These certificates are valid
// for default Exchange server installations, so return true.
return true;
}
else
{
// In all other cases, return false.
return false;
}
}
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;
}
}
seems like you are already doing a good job doing a FindItems() method.
In order to get all contacts all you need to add is a SearchFilter, in this case I'd recommend doing the Exists() filter as you can simply say Find All contacts with an id.
See my example below if you need an example of a Full Windows Application dealing with contacts see my github page github.com/rojobo
Dim oFilter As New SearchFilter.Exists(ItemSchema.Id)
Dim oResults As FindItemsResults(Of Item) = Nothing
Dim oContact As Contact
Dim blnMoreAvailable As Boolean = True
Dim intSearchOffset As Integer = 0
Dim oView As New ItemView(conMaxChangesReturned, intSearchOffset, OffsetBasePoint.Beginning)
oView.PropertySet = BasePropertySet.IdOnly
Do While blnMoreAvailable
oResults = pService.FindItems(WellKnownFolderName.Contacts, oFilter, oView)
blnMoreAvailable = oResults.MoreAvailable
If Not IsNothing(oResults) AndAlso oResults.Items.Count > 0 Then
For Each oExchangeItem As Item In oResults.Items
Dim oExchangeContactId As ItemId = oExchangeItem.Id
//do something else
Next
If blnMoreAvailable Then oView.Offset = oView.Offset + conMaxChangesReturned
End If
Loop
How to retrieve all contacts from Microsoft Exchange using EWS Managed API?
If your question is how to retrieve the Exchange Contacts using EWS, you're already done with it.
Office365->People is just the right app to manipulate your Exchange contacts. If you check out the People app URL, it's something similar to https://outlook.office365.com/owa/?realm=xxxxxx#exsvurl=1&ll-cc=1033&modurl=2, owa is the synonym for outlook web app.

Entity Framework cycle of data

I have an Account object, which has many Transactions related to it.
In one method, I get all transactions for a particular account.
var transactionlines = (from p in Context.account_transaction
.Include("account_transaction_line")
// .Include("Account")
.Include("account.z_account_type")
.Include("account.institution")
.Include("third_party")
.Include("third_party.z_third_party_type")
.Include("z_account_transaction_type")
.Include("account_transaction_line.transaction_sub_category")
.Include("account_transaction_line.transaction_sub_category.transaction_category")
.Include("z_account_transaction_entry_type")
.Include("account_transaction_line.cost_centre")
where p.account_id == accountId
&& p.deleted == null
select p).ToList();
This is meant to return me a list of transactions, with their related objects. I then pass each object to a Translator, which translates them into data transfer objects, which are then passed back to my main application.
public TransactionDto TranslateTransaction(account_transaction source)
{
LogUserActivity("in TranslateTransaction");
var result = new TransactionDto
{
Id = source.id,
Version = source.version,
AccountId = source.account_id,
// Account = TranslateAccount(source.account, false),
ThirdPartyId = source.third_party_id,
ThirdParty = TranslateThirdParty(source.third_party),
Amount = source.transaction_amount,
EntryTypeId = source.account_transaction_entry_type_id,
EntryType = new ReferenceItemDto
{
Id = source.account_transaction_entry_type_id,
Description = source.z_account_transaction_entry_type.description,
Deleted = source.z_account_transaction_entry_type.deleted != null
},
Notes = source.notes,
TransactionDate = source.transaction_date,
TransactionTypeId = source.account_transaction_type_id,
TransactionType = new ReferenceItemDto
{
Id = source.z_account_transaction_type.id,
Description = source.z_account_transaction_type.description,
Deleted = source.z_account_transaction_type.deleted != null
}
};
... return my object
}
The problem is:
An account has Transactions, and a Transaction therefore belongs to an Account. It seems my translators are being called way too much, and reloading a lot of data because of this.
When I load my transaction object, it's 'account' property has a'transactions' propery, which has a list of all the transactions associated to that account. Each transaction then has an account property... and those account peroprties again, have a list of all the transactions... and on and on it goes.
Is there a way I can limit the loading to one level or something?
I have this set:
Context.Configuration.LazyLoadingEnabled = false;
I was hoping my 'Includes' would be all that is loaded... Don't load 'un-included' related data?
As requested, here is my TranslateAccount method:
public AccountDto TranslateAccount(account p, bool includeCardsInterestRateDataAndBalance)
{
LogUserActivity("in TranslateAccount");
if (p == null)
return null;
var result =
new AccountDto
{
Id = p.id,
Description = p.description,
PortfolioId = p.institution.account_portfolio_id,
AccountNumber = p.account_number,
Institution = TranslateInstitution(p.institution),
AccountType = new ReferenceItemDto
{
Id = p.account_type_id,
Description = p.z_account_type.description
},
AccountTypeId = p.account_type_id,
InstitutionId = p.institution_id,
MinimumBalance = p.min_balance,
OpeningBalance = p.opening_balance,
OpeningDate = p.opening_date
};
if (includeCardsInterestRateDataAndBalance)
{
// Add the assigned cards collection
foreach (var card in p.account_card)
{
result.Cards.Add(new AccountCardDto
{
Id = card.id,
AccountId = card.account_id,
Active = card.active,
CardHolderName = card.card_holder_name,
CardNumber = card.card_number,
ExpiryDate = card.expiry
});
}
// Populate the current interest rate
result.CurrentRate = GetCurrentInterestRate(result.Id);
// Add all rates to the account
foreach (var rate in p.account_rate)
{
result.Rates.Add(
new AccountRateDto
{
Id = rate.id,
Description = rate.description,
Deleted = rate.deleted != null,
AccountId = rate.account_id,
EndDate = rate.end_date,
Rate = rate.rate,
StartDate = rate.start_date
});
}
result.CurrentBalance = CurrentBalance(result.Id);
}
LogUserActivity("out TranslateAccount");
return result;
}
The entity framework context maintains a cache of data that has been pulled out of the database. Regardless of lazy loading being enabled/disabled, you can call Transaction.Account.Transactions[0].Account.Transactions[0]... as much as you want without loading anything else from the database.
The problem is not in the cyclical nature of entity framework objects - it is somewhere in the logic of your translation objects.

How to read extended properties from Outlook contacts using EWS

I'm currently attempting to read certain properties from Outlook Contact objects through Microsoft's EWS managed API. I retrieve these Contact objects from the FindItems() function. Some of these fields are extended properties such as the Title or User1 field and I'm having difficulty reading them. At the moment, I have:
Guid propertySetId = new Guid("{00062004-0000-0000-C000-000000000046}");
ExtendedPropertyDefinition titleProp = new ExtendedPropertyDefinition(propertySetId, 0x3A45, MapiPropertyType.String);
ExtendedPropertyDefinition user1Prop = new ExtendedPropertyDefinition(propertySetId, 0x804F, MapiPropertyType.String);
string title, user1;
contact.TryGetProperty(titleProp, out title);
contact.TryGetProperty(user1Prop, out user1);
When running this, TryGetProperty always returns false. I have verified that these fields are populated in Outlook for the contacts that I am searching for.
Edit: This is how I retrieve the contact objects.
ExchangeService service = //...
Mailbox userMailbox = new Mailbox(emailAddress);
FolderId folderId = new FolderId(WellKnownFolderName.Contacts, userMailbox);
FindItemsResults<Item> results;
const string AQS = "Category:~>\"CategoryTag\"";
ItemView view = new ItemView(200);
results = service.FindItems(folderId, AQS, view);
foreach (var result in results)
{
Contact contact = result as Contact;
//...Try to read fields
}
You need to change the ItemView to include the properties (PropertySet) you wish to access.
var user1Val = string.Empty;
var user1Prop = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Address, 0x804F, MapiPropertyType.String);
ExtendedPropertyDefinition[] extendedFields = new ExtendedPropertyDefinition[] { user1Prop };
PropertySet extendedPropertySet = new PropertySet(BasePropertySet.FirstClassProperties, extendedFields);
ItemView view = new ItemView(200) { PropertySet = extendedPropertySet };
// ...
var title = contact.CompleteName.Title; // Title value
contact.TryGetProperty(user1Prop, out user1Val); // user field 1 value

Resources