Sonntag, März 30, 2008

Rings um Oster(n)wochen

Sorry, für die wenigen Posts, aber irgendwie habe ich grad keine Peilung, was ich am besten schreiben soll. Technisch fitze ich mich gerade mal wieder in das Thema Workflow Foundation tiefer rein, ansonsten habe ich nicht viel Zeit nebenbei. Ich schaff es nicht mal meine Technology Review zu lesen.

In den letzten 2 Wochen war ich mal wieder auf Dienstreise, das Gute ist diesmal, dass ich nur 2h weg bin. Das Thema finde ich alles andere als spannend oder interessant, aber eine begrenzte Zeit werde ich das überleben.

Die Osterfeiertage habe ich auch gut überstanden, wobei ich sagen muss, dass es teilweise schon richtig langweilig war. Zum Glück haben wir, meine Freunde und ich, wenigstens 2 Tage zu gebracht. Das Osterfeuer war dieses Jahr ganz schön feucht und kalt und dass ohne meine gute Jacke. Bei Jacke fällt mir ein, dass ich jetzt wieder eine neue Jacke habe. Ich glaube, dieses Ostern war das erste, an dem die ganze Familie Eier gefärbt hat. Ergebnis waren wirklich schöne bunte Eier.

Zu meiner Ex-Beziehung kann ich nur eins sagen, mir fehlt Sie immer noch sehr, meine Motivation ist immer noch äußerst gering und richtig glücklich bin ich auch fast nie, dafür habe ich aber einen größeren Sarkasmus.

Montag, März 24, 2008

Über ein Halbes Jahr Jabber

Diesen Post wollte ich schon vor einer Zeit machen, allerdings hatte ich immer mal wieder was anderes im Kopf. Wir nutzen nun schon über ein halbes Jahr Jabber/XMPP. Jabber war im letzten und auch vorletzten Jahr der Hype, es scheint so als kann sich keiner mehr so richtig vor IM schützen. Nach dem im letzten Jahr auch AIM/ICQ erste Versuche mit XMPP-Server gemacht haben, so bin ich guter Dinge, dass es noch weitere Fortschritte machen wird. Außer der immer größeren Verbreitung wurde letztes Jahr auch endlich die Jingle-Erweiterung für Voice-/Audio-Chat beschlossen. Die Implementierungen für die Funktionalität wird bestimmt sehr schnell Einzug halten. Google-Talk-Nutzer kennen Jingle schon lange. In Deutschland wird Jabber durch große Provider wie web.de und gmx gepuscht, beide bieten jedem Nutzer auch einen Jabber-Zugang an.

Bei uns in der Firma nutzen nicht alle die Funktionalität, da es momentan noch keine Kopplung an unser AD gibt und User momentan erst eingerichtet werden müssen, außerdem mag nicht jeder IM, bzw. kann es wegen Beschränkungen bei Kunden nicht nutzen. Einige Probleme gibt es mit unserem DNS-Provider Hosteurope, offensichtlich sind die SRV-Records nicht immer abfragbar. Allerdings sind die SRV-Records auch das einzige Problem, was momentan mit unserem XMPP-Server existiert. Bei den Clients herrscht immer noch Vielfalt, wobei meistens ein einfacher Client mit wenigen Optionen ausreicht um weniger zu verwirren. Ansonsten ist es recht praktisch eine Hersteller unabhängige Kommunikationslösung zu besitzen, die möglichst universelle Schnittstellen hat. (Transports) Alles in allem ist Jabber praktisch, einfach, universell und hilfreich!

Ich hoffe, dass IM endlich in den deutschen Unternehmen als Ergänzung der Kommunikationsmittel verwendet wird. Leider sehen viele es eher als Ablenkung der Mitarbeiter und Spielerei, nur diese Leute nutzen diese Sachen am wenigsten. Kollegen, die beim Kunden unterwegs sind, haben erhebliche Probleme sich mit dem Server zu verbinden auf Grund der verschiedenen Restriktionen von Unternehmen.

Aus meiner Sicht ist Jabber/XMPP das Protokoll für Messaging die nächsten Jahre, demnächst werden vermutlich auch die Großen (AIM/ICQ/MSN/YAHOO) ihre Pforten öffnen.

Sonntag, März 16, 2008

Die letzten Wochen / Schöne Ostern

Ich hatte in den letzten Wochen das Blogging bisschen vernachlässigt, zumindest habe ich wenig/nix privates geschrieben. In der vorletzten Woche hatte ich einen kleinen Fahrradunfall (siehe Bilder), danach war es etwas anstrengend sich in Berlin fortzubewegen, da die BVG mehr Geld will und Streikt. Ich hatte mir bei Freunden ein Fahrrad ausgeliehen, zum abholen musste ich dann die Skates benutzen, die Wohnen ein Stück von der S-Bahn weg. Zu dem Zeitpunkt sollte am Montag auch noch der S-Bahn Streik beginnen. Nach einer Woche in der Fahrrad-Werkstatt ist mein Fahrrad nun wieder fertig. Lenker, Gabel, Laufrad und Bremsscheibe mussten gewechselt werden.

Für meine Gefühle gehen momentan hin und her, es ist nicht so katastrophal wie noch vor einem Monat, aber gut fühlt sich anders an. Zu erzählen habe ich nicht viel Neues, daher schweige ich und schlucke es einfach herunter. Es gab einen gemeinsamen Bowling-Abend mit Ex-Kollegen in der letzten Woche. Es ist schön mit Freunden oder Kollegen etwas zu unternehmen und etwas abzuschalten von der Arbeit.

Auf Arbeit ist es momentan nicht so spannend, ich soll zwar einen POC machen, aber die Thematik reizt mich irgendwie überhaupt nicht, zumindest momentan. Ich werde die kommende Woche mit einem Kollegen beim Kunden Vorort verbringen und wir versuchen dort die erwünschten Ergebnisse zu erzielen. Auf geht’s in die brandenburgische Pampa, nicht weit wohnt auch ein Kollege.

In der Woche kann ich mich dann hoffentlich gut auf Workflow Foundation und vielleicht auch BizTalk-Zertifizierung vorbereiten. Aber das Zweite hat eine geringere Priorität, ist nur wichtig für mein Geld. Am meisten freue ich mich momentan auf Ostern, wenn ich auch noch nicht weiß, ob ich alle Freunde sehe. Ich muss mir noch überlegen, wie und wann ich zu meinen Eltern fahre. Ich könnte Donnerstag von der Dienstreise durchfahren, muss dann aber viel mitschleppen, ich könnte Donnerstag noch nach Hause und dann weiter oder ich fahre erst am Freitag. Wie es auch immer kommt, ich werde es schon schaffen.

Allen ein schönes Osterfest mit viel Sonne!

Exchange 2007 Webservice Zugriff, GetItem macht ärger!

Dieses Wochenende bin ich noch mal das Thema Exchange Webservices angegangen. So richtig steige ich nicht durch die Webservices, zumindest verstehe ich das Verhalten nicht so ganz, oder in der Implementierung sind Fehler. Mein letzter Versuch ging auf die Distributionlists, nun sollen es endlich Emails sein!

Auf jeden Fall wollte ich nun diesmal endlich alle Emails der letzten X-Tage oder sonst was abrufen. Ich hatte mir mehrere Beispiele angeschaut, unter anderem von Stephen Griffin und den Eintrag auf Jive into Messaging world, natürlich gab es noch viele andere Artikel. Der letzte Eintrag diente als Vorlage für meine Anpassungen. Beim Abrufen von Daten kommt bei der FindItem-Methode nur ein Teil der Informationen mit und maximal eine Zusammenfassung des Inhalts. Durch die zusätzliche Eigenschaften fiFindItemRequest.ItemShape.AdditionalProperties kann der Menge an Informationen noch verändert werden. Für mich war das aber nicht so wichtig, ich wollte den gesamten Inhalt, dafür soll man die GetItem-Methde aufrufen. Allerdings wenn ein Extra aufruft gemacht werden muss für die Einträge, so reicht es nur die IDs für den zweiten Aufruf zu sammeln. Alle Anpassungen sind in meinem Code zu sehen.

    85   const double MessageWindow = 2;

   86   private static void GetLastEmails()

   87  {

   88      ExchangeServicePortTypeClient exchange = new ExchangeServicePortTypeClient ();

   89      exchange.ClientCredentials.Windows.ClientCredential = System.Net. CredentialCache .DefaultNetworkCredentials;

   90      ExchangeImpersonationType exExchangeImpersonation = new ExchangeImpersonationType ();

   91      ConnectingSIDType csConnectingSid = new ConnectingSIDType ();

   92      csConnectingSid.PrimarySmtpAddress = "<email>@capevision.de" ;

   93      exExchangeImpersonation.ConnectingSID = csConnectingSid;

   94      FindItemType fiFindItemRequest = new FindItemType ();

   95      fiFindItemRequest.Traversal = ItemQueryTraversalType .Shallow;

   96      ItemResponseShapeType ipItemProperties = new ItemResponseShapeType ();

   97      //Load only the message ids for better performance (second request for details required)

   98      ipItemProperties.BaseShape = DefaultShapeNamesType .IdOnly; //AllProperties

   99      fiFindItemRequest.ItemShape = ipItemProperties;

  100  

  101      //The next 3 blocks load some additional properties with first request

  102      PathToExtendedFieldType ptItemURI = new PathToExtendedFieldType ();

  103      ptItemURI.PropertyTag = "0x10F3" ;

  104      ptItemURI.PropertyType = MapiPropertyTypeType .String;

  105  

  106      PathToExtendedFieldType ptFromEmailDisplay = new PathToExtendedFieldType ();

  107      ptFromEmailDisplay.PropertyTag = "0x0C1A" ;

  108      ptFromEmailDisplay.PropertyType = MapiPropertyTypeType .String;

   109  

  110      PathToExtendedFieldType ptBodySum = new PathToExtendedFieldType ();

  111      ptBodySum.PropertyTag = "0x3FD9" ;

  112      ptBodySum.PropertyType = MapiPropertyTypeType .String;

  113  

  114  

  115      //Limit items to be received

  116      PathToUnindexedFieldType StartDateReceivedField = new PathToUnindexedFieldType ();

  117      StartDateReceivedField.FieldURI = UnindexedFieldURIType .itemDateTimeReceived;

  118      ConstantValueType StartDateReceivedToGet = new ConstantValueType ();

  119      StartDateReceivedToGet.Value = DateTime .Now.Subtract( TimeSpan .FromDays(MessageWindow)).ToUniversalTime().ToString( "u" );

  120      FieldURIOrConstantType StartDateReceivedConstant = new FieldURIOrConstantType ();

  121      StartDateReceivedConstant.Item = StartDateReceivedToGet;

  122      IsGreaterThanOrEqualToType igtett = new IsGreaterThanOrEqualToType ();

  123      igtett.FieldURIOrConstant = StartDateReceivedConstant;

  124      igtett.Item = StartDateReceivedField;

  125      RestrictionType rt = new RestrictionType ();

  126      rt.Item = igtett;

  127      fiFindItemRequest.Restriction = rt;

  128  

  129      DistinguishedFolderIdType [] faFolderIDArray = new DistinguishedFolderIdType [2];

  130      faFolderIDArray[0] = new DistinguishedFolderIdType ();

  131      faFolderIDArray[0].Id = DistinguishedFolderIdNameType .inbox; //only load Inbox-items

  132      //fiFindItemRequest.ItemShape.AdditionalProperties = new BasePathToElementType[3];

  133      //fiFindItemRequest.ItemShape.AdditionalProperties[0] = ptBodySum;

  134      //fiFindItemRequest.ItemShape.AdditionalProperties[1] = ptItemURI;

  135      //fiFindItemRequest.ItemShape.AdditionalProperties[2] = ptFromEmailDisplay;

  136      fiFindItemRequest.ParentFolderIds = faFolderIDArray;

  137      FindItemResponseType frFindItemResponse;

  138      int emails = 0;

  139      int errors = 0;

  140      try

  141      {

  142          exchange.FindItem( null , null , Thread .CurrentThread.CurrentUICulture.ToString(), null , fiFindItemRequest, out frFindItemResponse);

  143          foreach ( FindItemResponseMessageType firmtMessage in frFindItemResponse.ResponseMessages.Items)

  144          {

  145              if (firmtMessage.RootFolder.TotalItemsInView > 0)

  146              {

  147                  foreach ( ItemType miMailboxItem in (( ArrayOfRealItemsType )firmtMessage.RootFolder.Item).Items)

  148                  {

  149                      //if (miMailboxItem.ExtendedProperty != null)

  150                      //{

  151                      //    if (miMailboxItem.ExtendedProperty.Length == 3)

  152                      //    {

  153                      emails++;

  154                      //TODO: Create item batches for effective download

  156                      try

  157                      {

  158                          GetItemResponseType giResponse;

  159                          giResponse = GetCurrentItem(exchange, miMailboxItem);

  160                          if (giResponse != null && giResponse.ResponseMessages != null && giResponse.ResponseMessages.Items.Count() > 0)

  161                          {

  162                              ItemType [] array = (( ItemInfoResponseMessageType )giResponse.ResponseMessages.Items[0]).Items.Items;

  163                              foreach ( ItemType t in array)

  164                              {

  165                                  MessageType details = t as MessageType ;

  166                                  if (details == null )

  167                                  {

  168                                      //This is not a mail item

  169                                      //should i handle this?

  170                                  }

  171                                  else

  172                                  {

  173                                      Console .WriteLine( "[{0}] - <{1}>{2} - {3}" , details.DateTimeReceived.ToString( "u" ), details.From.Item.Name, details.From.Item.EmailAddress, details.Subject.ToString());

   174                                      //if (details.Body != null)

  175                                      //    Console.WriteLine(details.Body.Value);

  176                                  }

  177                              }

  178                          }

  179                      }

  180                      catch ( Exception ex)

  181                      {

  182                          errors++;

  183                          Console .WriteLine( "[{0}] - <{1}> - {2}" , miMailboxItem.DateTimeReceived.ToString( "u" ),

miMailboxItem.DisplayTo, miMailboxItem.ItemId.Id);

  184                          Console .WriteLine( "--Error receiving item: " + ex.Message);

  185                      }

  186                      //only default, then no email address loaded (and some other properties)

  189                      //    }

  190                      //}

  191                  }

  192              }

  193          }

  194      }

  195      catch ( Exception ex)

  196      {

  197          Console .WriteLine(ex.ToString());

  198          throw ;

  199      }

  200      Console .WriteLine( "Emails received {0}, errors {1}" , emails, errors);

  201  }

  203   private static GetItemResponseType GetCurrentItem( ExchangeServicePortTypeClient exchange, ItemType miMailboxItem)

  204  {

  205      GetItemResponseType giResponse;

  206      GetItemType giType = new GetItemType ();

  207      giType.ItemShape = new ItemResponseShapeType ();

  208      giType.ItemShape.BaseShape = DefaultShapeNamesType .Default;

  209      giType.ItemShape.IncludeMimeContent = true ;

  210      giType.ItemShape.IncludeMimeContentSpecified = false ;

  211      giType.ItemShape.BodyType = BodyTypeResponseType .Text; // miMailboxItem.Body.BodyType1;

  212      giType.ItemShape.BodyTypeSpecified = true ;

  213      ItemIdType current = new ItemIdType ();

  214      current.Id = miMailboxItem.ItemId.Id.ToString();

  215      giType.ItemIds = new ItemIdType [] { current };

  216      exchange.GetItem( null , null , null , null , giType, out giResponse);

   217      return giResponse;

  218  }

Ende Bei einigen Versuchen erhielt ich die Fehlermeldung, dass er Response zu groß war, allerdings gab es dafür eine schnelle Abhilfe, einfach die Verarbeitung des Responses auf Streaming umstellen.

   19                   < binding name = " ExchangeServiceBinding " closeTimeout = " 00:01:00 "

   20                       openTimeout = " 00:01:00 " receiveTimeout = " 00:10:00 " sendTimeout = " 00:01:00 "

   21                       allowCookies = " false " bypassProxyOnLocal = " false " hostNameComparisonMode = " StrongWildcard "

   22                       maxBufferSize = " 65536 " maxBufferPoolSize = " 524288 " maxReceivedMessageSize = " 655369 "

   23                       messageEncoding = " Text " textEncoding = " utf-8 " transferMode = " StreamedResponse "

   24                       useDefaultWebProxy = " true " >

   25                       < readerQuotas maxDepth = " 32 " maxStringContentLength = " 8192 " maxArrayLength = " 16384 "

   26                           maxBytesPerRead = " 4096 " maxNameTableCharCount = " 16384 " />

   27                       < security mode = " Transport " >

   28                         <!-- <transport clientCredentialType="Windows" proxyCredentialType="None" /> -->

   29                         < transport clientCredentialType = " Ntlm " proxyCredentialType = " None " />

   30                         < message clientCredentialType = " UserName " algorithmSuite = " Default " />

    31                       </ security >

   32                   </ binding >

Mein größtes Problem ist allerdings, dass die GetItem-Methode für einige Mails immer mal wieder einen Fehler wirft. Leider bekomme ich den Fiddler auch nicht zur Arbeit mit dem Exchange überredet, da bei uns nur HTTPs zulässig ist. Falls jemand einen Tipp für mich hat, was das sein kann, wäre ich sehr dankbar. Da in den meisten Fällen die Email erfolgreich verarbeitet werden kann, kann man die Lösung durchaus zum Verarbeiten nutzen. Mich ärgert allerdings trotzdem, dass Emails nicht korrekt herausgeschrieben werden.

In meinem Code sollte noch einige Funktionen optimiert werden. Zum einen sollte man mehrere Items mit einer Anfrage abrufen, da jeder Abruf ein Roundtrip mit dem Server erfordert. Des Weiteren muss das ErrorHandling deutlich verbessert werden, aber Schritt für Schritt.