Model
public class Mail
{
public int Id { get; set; }
public string Tema { get; set; }
public string Note { get; set; }
public string Date { get; set; }
public string Email { get; set; }
}
Client IMAP
using (var client = new ImapClient())
{
var Emails = _context.Settings.FirstOrDefault();
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(Emails.Imap,Convert.ToInt32(Emails.ImapPort), true);
client.Authenticate(Emails.Login, Emails.Password);
client.Inbox.Open(FolderAccess.ReadOnly);
var inbox = client.Inbox;
var messages = inbox.Fetch(0, -1, MessageSummaryItems.All | MessageSummaryItems.Full | MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure);
if (messages.Where(c => c.Flags.Value.HasFlag(MessageFlags.Seen) != true).Count() > 0)
{
foreach (var message in messages.Where(c => c.Flags.Value.HasFlag(MessageFlags.Seen) != true))
{
var mime = inbox.GetBodyPart(message.UniqueId, message.HtmlBody);
Mail mail = new Mail();
mail.Date = DateTime.Now;
mail.Note = Convert.ToString(mime);
mail.Tema = message.Envelope.Subject.ToString();
mail.Email = Convert.ToString(message.Date);
_context.Add(mail);
await _context.SaveChangesAsync();
break;
}
}
client.Disconnect(true);
}
as a result, I get an unreadable string in the Note
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: base64
PGh0bWw+PGhlYWQ+PG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50
PSJ0ZXh0L2h0bWw7Ij48dGl0bGU+0JzQldCU0JjQkNCb0J7Qk9CY0K88L3RpdGxlPjxz
dHlsZT4uYmR7Zm9udDogMTI1JS8xMTUlIGFyaWFsLCBzYW5zLXNlcmlmOyBjb2xvcjog
IzAwM0U1MDsgbWFyZ2luLXRvcDogMTJweH0gcHtmb250OiAxMDAlIGFyaWFsLCBzYW5z
LXNlcmlmOyBjb2xvcjogIzAwM0U1MDsgbWFyZ2luLXRvcDogMTJweH0gdGR7Zm9udDog
ODAlLzExNSUgYXJpYWwsIHNhbnMtc2VyaWY7IGNvbG9yOiAjMDAzRTUwOyBtYXJnaW4t
dG9wOiAxMnB4fSB0ZC5oZHJ7Zm9udDogYm9sZCAxMXB4LzE0cHggYXJpYWwsIHNhbnMt
c2VyaWY7IGNvbG9yOiAjMWIxYjU2OyBtYXJnaW4tdG9wOiAxMnB4OyBsaW5lLWhlaWdo
dDoxNXB4O30gLnNlYXJjaF9obHtjb2xvcjogI2ZmZmZmZjtiYWNrZ3JvdW5kLWNvbG9y
OiAjMDAzODQ4O308L3N0eWxlPjwvaGVhZD48Ym9keSBiZ2NvbG9yPSNGRkZGRkY+PHRh
......
after "Content-Transfer-Encoding: base64" we see the html file in bass64. Is there any way MileKit will record only the file data itself.
You are essentially calling MimePart.ToString()... and, well, as far as MimeKit knows, you want the MIME as a string.
But that's not what you actually want.
What you want is the actual text content.
Here's what you need to do in your loop:
var html = (TextPart) inbox.GetBodyPart (message.UniqueId, message.HtmlBody);
Mail mail = new Mail();
mail.Date = DateTime.Now;
mail.Note = html.Text;
...
A TextPart is a subclass of MimePart that represents text/* MIME parts (including text/html) and has a few nice convenient API's that can be used to get (or set) the textual content of the MimePart as a string rather than having to deal with streams - most notably, the .Text property.
That should answer your question, but I'm not done because your code could use a few more changes.
Instead of asking MailKit to Fetch() the metadata for every single message in your inbox, why not request only what you need?
Since you clearly don't care about messages that have already been seen, you could take advantage of IMAP's SEARCH functionality, like so:
var uids = inbox.Search (SearchQuery.NotSeen);
if (uids.Count > 0)
{
var messages = inbox.Fetch (uids, MessageSummaryItems.UniqueId | MessageSummaryItems.Envelope | MessageSummaryItems.Flags | MessageSummaryItems.BodyStructure);
foreach (var message in messages.Where (c => !c.Flags.Value.HasFlag (MessageFlags.Seen))
{
// ...
}
}
Note: You still need to use the Where() filter because it's possible for message flags to change (by another client) between the Search() and the Fetch(). I also changed the MessageSummaryItems to be only the fields that you are actually using.
You can also get rid of your if (messages.Where(c => c.Flags.Value.HasFlag(MessageFlags.Seen) != true).Count() > 0) statement because it is redundant and requires a full pass at the returned data when the very next thing you do is to loop over the data anyway.
And since you break; out of the loop as soon as you find the very first message that hasn't been seen, why not do this instead?
var message = messages.FirstOrDefault (x => !x.Flags.Value.HasFlag (MessageFlags.Seen));
if (message != null)
{
var html = (TextPart) inbox.GetBodyPart(message.UniqueId, message.HtmlBody);
Mail mail = new Mail();
mail.Date = DateTime.Now;
mail.Note = html.Text;
mail.Tema = message.Envelope.Subject;
mail.Email = Convert.ToString(message.Envelope.Date);
_context.Add(mail);
await _context.SaveChangesAsync();
}
The end result is:
using (var client = new ImapClient())
{
var Emails = _context.Settings.FirstOrDefault();
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(Emails.Imap,Convert.ToInt32(Emails.ImapPort), true);
client.Authenticate(Emails.Login, Emails.Password);
client.Inbox.Open(FolderAccess.ReadOnly);
var inbox = client.Inbox;
var uids = inbox.Search (SearchQuery.NotSeen);
if (uids.Count > 0)
{
var messages = inbox.Fetch (uids, MessageSummaryItems.UniqueId | MessageSummaryItems.Envelope | MessageSummaryItems.Flags | MessageSummaryItems.BodyStructure);
var message = messages.FirstOrDefault (x => !x.Flags.Value.HasFlag (MessageFlags.Seen));
if (message != null)
{
var html = (TextPart) inbox.GetBodyPart(message.UniqueId, message.HtmlBody);
Mail mail = new Mail();
mail.Date = DateTime.Now;
mail.Note = html.Text;
mail.Tema = message.Envelope.Subject;
mail.Email = Convert.ToString(message.Envelope.Date);
_context.Add(mail);
await _context.SaveChangesAsync();
}
}
client.Disconnect(true);
}
The last change you'll need to make to the above code is what to do if the message doesn't have an HTML body. What if the message only has a text/plain body? Or what if it doesn't contain any text/* parts at all?
You'll need to figure out what you want to do when that happens...
Related
This is my batch class. I am facing a problem in the test class.
So please give me some solution on it. How to write this condition into class or how to write a test class for this.
I have this batch class created:
public class processBatch implements database.Batchable<object>, Database.AllowsCallouts, Scheduable{
public string AccountURL;
public String ProcessURL;
Public String Key;
private class JsonUpsertResult
{
List<Database.Error> Error {get;set;}
string SFDCId{get;set;}
String visibleID{get;set;}
Boolean is Created {get;set;}
Boolean isSuccess {get;set;}
}
public ProcessBatch(){
SAP_Details__c SAP = SAP_Details__c. getOrgDefaults();
AccountURL =SAP.Account_API_URL__c;
ProcessURL =SAP.process_API_URL__c;
Key =SAP.API_Key__c;
system.debug('API:' + ProcessURL + '-' + Key);
}
public Iterable<Object> start (Database.BatchableContext BC) {
List<Object> results =new List <Object>();
http http = new http();
httpRequest request =new HttpRequest();
system.debug('API:' '+ ProcessURL+' -' + Key);
request.setEndpoint(ProcessURL);
request.setMethod('POST');
request.setHeader('Authorization', Key);
request.setHeader('Accept', '*/*');
request.setHeader ('content-type', 'application/json');
}';
request.setBody(filters);
HttpResponse response =http.send(request);
if(responce.getStatusCode() == 200){
SAPProcessJsonApex2 gt = {SAPProcessJSON2Apex2) JSON.deserialize(response.getBody(), SAPProcessJSON2Apex.class);
List<SAPProcessJson2Apex.Result> res =gt.result;
system.debug('Size of Result: ' + res.size());
results = res;
}
return results;
}
public void execute (Database. BatchableContext BC, List<object> scope){
List<JSON2Apex.Results) accountResults = new List<JSON2Apex.Results>;
List<Process__c> ProcessToUpsert = new List<Process__c> ();
List<Process_Agent__c> CollectivesToupsert = new List<Process_Agent__c> ();
List<Department__c> departmentToupdate = new List<Department__c> ();
List<JSON2Apex.Results) revisedAccRes = new List JSON2Apex.Results> ();
List<SAPprocessJSON2Apex2.Results res = (List<SAPprocessJSO2Apex2.Results>) scope();
List<SAPprocessJSON2Apex2.Results revisedRes = nen List<SAPprocessJSONApex2.Results> ();
for (SAPprocessJSON2Apex2.Results r: res) {
SAPprocessJSON2Apex2.Document doc = r. document: List<SAPprocessJSON2 Apex2. Companies) comp = doc.companies;
List<SAPprocessJSON2Apex2.Companies> comp = doc.companies;
List<String> processTypes = doc.processTypes;
Lisk<String> categories = doc.categories;
Process__c pr = new Process__c ();
pr.Visibleprocess_No__c = doc.processId;
pr.Visible_method__c = 'SAP';
pr.process_Description__c = doc.description;
pr.Amount__c = doc.Amount;
pr.Construction_Type__c = doc.constructionType;
if(doc.phase == 'First planning'){
pr.Division=='First planning!';
} else if(doc.phase == 'Quotation'){
pr.Division == 'Main Step Quotation;
} else if(doc.phase = 'Contract Get') {
pr. Division== ' Main Step Agricultural';
}
pr.process_Full Name = doc.title;
pr.Name = doc.title.left (80);
if (categories.size() > 0){
if(categories [0] == 'Factory' || categories [0] = 'Storage' ){
pr.Sector__c = 'Industrial';
}else if(categories [0] == 'Packaging/Storage') {
pr. Type_of_Sector_c = 'Warehouse';
}else if(categories[0] == 'Shops and Retail' || categories [0]=='Any Showrooms') {
pr.Sector__c = 'Commercial';
}
if(pr.Sector__c != null && doc.Amount >= 50000){
ProcessToUpsert.ada (p);
revisedRes.ada (r);
} } }
public void finish (Database.BatchableContext BC) {
}
public void execute (SchedulableContext sc) {
database.executeBatch (new ProcessBatch (), 30);
}
}
&& d.Amount__c>= 50000 Whenever I write this condition in my class then my test class covers only 35%, and when I remove this condition it covers 80%. This condition is correct according to the requirement.
Test Class
#isIest (SeeAllData = true)
public class ProcessBatchTest {
#isTest public static void processBatchTest () {
Test.setMock (HttpCalloutMock.class, new HttpMock());
ProcessBatch pb = new ProcessBatch();
Test.startTest();
database.executeBatch (pb,30);
Test.stopTest();
You control the HttpMock class that pretends it returns results from SAP callout in the test. Nothing stops you from going there and making it return 2 records (1 with amount below 50K, 1 with amount above), or multiple statuses or whatever else you need.
I created for Windows Phone 8.0 Silverlight App an async method GetStreetName
string streetname;
private async Task<string> GetStreetName(int i)
{
MapAddress address;
ReverseGeocodeQuery query = new ReverseGeocodeQuery();
query.GeoCoordinate = Route[i].Item1;
query.QueryCompleted += (s, e) =>
{
if (e.Error != null)
return;
address = e.Result[0].Information.Address;
streetname = address.Street;
};
query.QueryAsync();
return streetname;
}
and I call it using the await operator inside of a for loop:
for (int i = 0; i < Route.Count; i++)
{
ListBox.Items.Add(await GetStreetName(i));
}
but I always get only the street name of the first loaded geoposition back and I have no idea why (I thought the await operator is waiting until the async method is finished).
Additional info: i just saw that this is not 100% clear at this short snippet, streetname and Route are global "variables", Route is a tuple list where the first item is a geocoordinate.
How can I fix this issue?
You are returning from GetStreetName before the results are ready becayse query.QueryAsync(); just starts the query and doesn't wait for it to be complete.
On top of that, you're writing all results to the same global streetname.
You need to use a TaskCompletionSource.
Try something like this:
private async Task<string> GetStreetNameAsync(int i)
{
var tcs = new TaskCompletionSource<IEnumerable<string>>();
EventHandler<QueryCompletedEventArgs<IList<MapLocation>>> handler = (s, e) =>
{
if (e.Error != null)
{
tcs.TrySetException(e.Error);
return;
}
if (e.Cancelled)
{
tcs.TrySetCanceled();
return;
}
tcs.TrySetResult(e.Result[0].Information.Address.Street);
};
var query = new ReverseGeocodeQuery();
query.GeoCoordinate = Route[i].Item1;
try
{
query.QueryCompleted += handler;
query.QueryAsync();
return await tcs.Task;
}
finally
{
query.QueryCompleted -= handler;
}
}
I have hundreds of different random URLs coming in, all documents in libs, without any other parameters from different farms and different site collections and sites, goal is to download a file as a binary array from SharePoint.
So e.g. incoming url = http://a.b.c.d.e/f.g/h.i/j/k/l/m.docx .
So how to get the (a) correct site collection root url (b) site root url (c) library root url from this? The only way I now think of is slowly stripping off each part of the url until e.g. .Rootfolder no longer gives an exception... or the other way around slowly adding bits by the first part of the url until rootfolder nog longers gives an exception then query for subwebs etc..
The point is that ClientContext constructor accepts the url of web/site only.
But if the url will be specified in the following format:
http://site/web/documents/file.docx
then the exception System.Net.WebException will occur.
The following example demonstrates how to resolve ClientContext from request Url:
public static class ClientContextUtilities
{
/// <summary>
/// Resolve client context
/// </summary>
/// <param name="requestUri"></param>
/// <param name="context"></param>
/// <param name="credentials"></param>
/// <returns></returns>
public static bool TryResolveClientContext(Uri requestUri, out ClientContext context, ICredentials credentials)
{
context = null;
var baseUrl = requestUri.GetLeftPart(UriPartial.Authority);
for (int i = requestUri.Segments.Length; i >= 0; i--)
{
var path = string.Join(string.Empty, requestUri.Segments.Take(i));
string url = string.Format("{0}{1}", baseUrl, path);
try
{
context = new ClientContext(url);
if (credentials != null)
context.Credentials = credentials;
context.ExecuteQuery();
return true;
}
catch (Exception ex) {}
}
return false;
}
}
Usage
ClientContext context;
if (ClientContextUtilities.TryResolveClientContext(requestUri, out context, null))
{
using (context)
{
var baseUrl = requestUri.GetLeftPart(UriPartial.Authority);
var fileServerRelativeUrl = requestUri.ToString().Replace(baseUrl, string.Empty);
var file = context.Web.GetFileByServerRelativeUrl(fileServerRelativeUrl);
context.Load(file);
context.Load(context.Web);
context.Load(context.Site);
context.ExecuteQuery();
}
}
Since your goal is to download a file, there is pretty straightforward way to accomplish it without parsing url parts.
For example, using WebClient.DownloadFile Method:
private static void DownloadFile(Uri fileUri, ICredentials credentials, string localFileName)
{
using(var client = new WebClient())
{
client.Credentials = credentials;
client.DownloadFile(fileUri, localFileName);
}
}
I have made a working method but it seems elaborate, so any suggestions for improvement are welcome just to "download file if one of the specific columns has value "yes":
public void getDocument(Document doc)
{
// get the filename
Uri uri = new Uri(doc.uri);
doc.filename = "";
doc.filename = System.IO.Path.GetFileName(uri.LocalPath);
//string fullPathWithoutFileName = docUri.Replace(filename, "");
// would also include ?a&b so:
string[] splitDocUri = doc.uri.Split('/');
string fullPathWithoutFileName = "";
for (int i = 0; i < splitDocUri.Length -1; i++)
{
fullPathWithoutFileName += (splitDocUri[i] + '/');
}
// get via "_api/contextinfo" the context info
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(fullPathWithoutFileName + "_api/contextinfo");
req.Method = "POST";
req.Accept = "application/json; odata=verbose";
req.Credentials = new NetworkCredential(doc.username, doc.password, doc.domain);
req.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED","f");
req.ContentLength = 0;
BypassCertificateError();
HttpWebResponse rp = (HttpWebResponse)req.GetResponse();
Stream postStream = rp.GetResponseStream();
StreamReader postReader = new StreamReader(postStream);
string results = postReader.ReadToEnd();
// Now parse out some values needs system.web.extensions
JavaScriptSerializer jss = new JavaScriptSerializer();
var d = jss.Deserialize<dynamic>(results);
string formDigestValue = d["d"]["GetContextWebInformation"]["FormDigestValue"];
// the full url to the website e.g. "http://server:7777/level1/level 2"
string webFullUrl = d["d"]["GetContextWebInformation"]["WebFullUrl"];
// the full url to the site collection e.g. "http://server:7777"
string siteFullUrl = d["d"]["GetContextWebInformation"]["SiteFullUrl"];
// now we can create a context
ClientContext ctx = new ClientContext(webFullUrl);
ctx.ExecutingWebRequest +=
new EventHandler<WebRequestEventArgs>(ctx_MixedAuthRequest);
BypassCertificateError();
ctx.AuthenticationMode = ClientAuthenticationMode.Default;
ctx.Credentials = new NetworkCredential(doc.username, doc.password, doc.domain);
// Get the List
Microsoft.SharePoint.Client.File file = ctx.Web.GetFileByServerRelativeUrl(uri.AbsolutePath);
List list = file.ListItemAllFields.ParentList;
ctx.Load(list);
ctx.ExecuteQuery();
// execute a CAML query against it
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml =
"<View><Query><Where><Eq><FieldRef Name='FileLeafRef'/>" +
"<Value Type='Text'>" + doc.filename + "</Value></Eq></Where>" +
"<RowLimit>1</RowLimit></Query></View>";
ListItemCollection listItems = list.GetItems(camlQuery);
ctx.Load(listItems);
try {
ctx.ExecuteQuery();
}
catch
{
// e.g. : no access or the listname as incorrectly deduced
throw;
}
// and now retrieve the items needed
if (listItems.Count == 1)
{
ListItem item = listItems[0];
// some more checking from testColumn to decide if to download yes/no
string testColumn;
if (item.IsPropertyAvailable("testColumn")) {
testColumn = (string)item["testColumn"];
}
FileInformation fileInformation =
Microsoft.SharePoint.Client.File.OpenBinaryDirect(ctx,
(string)item["FileRef"]);
doc.bytes = ReadFully(fileInformation.Stream);
}
else
{
doc.errormessage = "Error: No document found";
}
}
I have a HTTP Post action whereby I am posting a HttpPostedFileBase and a FormCollection as my parameters
My controller action is as follows:
[HttpPost]
public ActionResult NewContent(HttpPostedFileBase postedFile,string username, FormCollection form)
{
if (postedFile != null)
{
HttpPostedFileBase postedFileCopy = postedFile;
postedFileCopy.InputStream.Position = 0;
Stream stream = postedFile.InputStream;
//avm.AddContent(postedFile, stream, "jpmcfeely");
string[] name = form.GetValues("name");
string[] author = form.GetValues("author");
string[] description = form.GetValues("description");
DateTime uploaddate = DateTime.Today;//form.GetValues("uploaddate");
DateTime expirydate = DateTime.Today.AddMonths(1);//form.GetValues("expirydate");
string[] participationpoints = form.GetValues("participationpoints");
string[] contenttypeid = form.GetValues("contenttypeid");
try
{
avm.AddContent(postedFile, stream, "jpmcfeely", name.ToString(), author.ToString(), description.ToString(), uploaddate, expirydate, Convert.ToInt32(participationpoints), Convert.ToInt32(contenttypeid));
}
catch (Exception ex)
{
return RedirectToAction("Index", "Admin");
}
}
I then have a method in my ViewModel which adds the details of the form collection to my sql storage table as follows:
public void AddContent(HttpPostedFileBase content, System.IO.Stream stream, string userName, string name, string author, string description, string uploadDate, string expiryDate, int participationPoints, int contentType)
{
string contentUri = "";
Content newContent = new Content();
contentUri = Helpers.ContentUtils.AddContentToBlob(content, stream, "useravatar", content.FileName);
newContent.Name = name;
newContent.Author = author;
newContent.Description = description;
newContent.UploadDate = DateTime.Today;
newContent.ExpiryDate = DateTime.Today.AddMonths(1);
newContent.ParticipationPoints = 50;
newContent.ContentBlobURL = contentUri;
newContent.ContentTypeID = contentType;
this.contentRepository.Add(newContent);
this.contentRepository.SaveChanges();
}
If I build the solution it compiles without error but on save of the content inside the try block on the controller I am getting the following error:
Unable to cast object of type 'System.String[]' to type 'System.IConvertible'
If I just pass the string values in by hardcoding then the method saves as expected so my problem is simply converting these to the appropriate format. What is best approach to do this or am I missing a step?
Change this snippet
Convert.ToInt32(participationpoints), Convert.ToInt32(contenttypeid)
to this
Convert.ToInt32(participationpoints[0]), Convert.ToInt32(contenttypeid[0])
How do I update a list of different Telephone, IPPhone using this
static void Main(string[] args)
{
Console.Write("Enter userid : "); // I would pass this in from the first
//Field in the .csv file 2439009
String username = Console.ReadLine();
try
{
DirectoryEntry myLdapConnection = createDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(myLdapConnection);
search.Filter = "(cn=" + uid + ")";
search.PropertiesToLoad.Add("Telephone","IPPhone");
SearchResult result = search.FindOne();
if (result != null)
{
// create new object from search result
DirectoryEntry entryToUpdate = result.GetDirectoryEntry();
// show existing title
Console.WriteLine("Current title : " + entryToUpdate.Properties["Telephone][0].ToString());
Console.Write("\n\nEnter new title : ");
// get new title and write to AD
String newTitle = Console.ReadLine();
entryToUpdate.Properties["Telephone"].Value = newTelePhone;
entryToUpdate.Properties["IPPhone"].Value = newIPPhone;
entryToUpdate.CommitChanges();
Console.WriteLine("\n\n...new title saved");
}
else Console.WriteLine("User not found!");
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
}
static DirectoryEntry createDirectoryEntry()
{
// create and return new LDAP connection with desired settings
DirectoryEntry ldapConnection = new DirectoryEntry("mydomain.dm.com");
ldapConnection.Path = "LDAP://OU=myusers,DC=sales,DC=US,DC=US";
ldapConnection.AuthenticationType = AuthenticationTypes.Secure;
return ldapConnection;
}
I'm guessing you've grabbed someone else's code and don't know how to use it?
You should understand that this code can (will?) cause serious server problems as the DirectoryEntry resources are not closed correctly.
Every DirectoryEntry variable in your Main method should be wrapped in a using(){} statement.
Try something like this:
You define a class CSVRecord which holds your data from the CSV - read that in using FileHelpers. The class looks like this:
public class CSVRecord
{
public string EmployeeNumber { get; set; }
public string TelephoneNumber { get; set; }
public string IPPhoneNumber { get; set; }
}
Once you've read that class in, you need to iterate over its elements, and do the update for each of them.
CSVRecord[] listOfEmployees = (read in via FileHelpers)
// define root for searching your user accounts
using (DirectoryEntry root = new DirectoryEntry("LDAP://dc=yourcompany,dc=com"))
{
// set up directory searcher to find users by employeeId
using (DirectorySearcher searcher = new DirectorySearcher(root))
{
searcher.SearchScope = SearchScope.Subtree;
// iterate over all entries in your list of employees
foreach (CSVRecord csvEntry in listOfEmployees)
{
searcher.Filter = string.Format("(&(objectCategory=user)(employeeId={0}))", csvEntry.EmployeeNumber);
// search for that employee
SearchResult result = searcher.FindOne();
// if found - access the DirectoryEntry
if (result != null)
{
DirectoryEntry foundUser = result.GetDirectoryEntry();
// update properties from values in CSV
foundUser.Properties["telephoneNumber"].Value = csvEntry.TelephoneNumber;
foundUser.Properties["ipPhone"].Value = csvEntry.IPPhoneNumber;
// save changes back to directory
foundUser.CommitChanges();
}
}
}
}
Does that work for you??